summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac7
-rw-r--r--man/systemd.resource-control.xml14
-rw-r--r--man/vconsole.conf.xml13
-rw-r--r--src/login/logind-user.c2
-rw-r--r--src/systemctl/systemctl.c10
-rw-r--r--src/test/test-condition.c4
-rw-r--r--src/test/test-path-util.c3
-rw-r--r--src/vconsole/vconsole-setup.c251
-rwxr-xr-xtest/udev-test.pl8
-rw-r--r--units/systemd-vconsole-setup.service.in3
11 files changed, 189 insertions, 129 deletions
diff --git a/Makefile.am b/Makefile.am
index 720defa6cb..7dd021b56a 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -4632,9 +4632,6 @@ nodist_udevrules_DATA += \
nodist_systemunit_DATA += \
units/systemd-vconsole-setup.service
-
-SYSINIT_TARGET_WANTS += \
- systemd-vconsole-setup.service
endif
EXTRA_DIST += \
diff --git a/configure.ac b/configure.ac
index cf595e68c0..a86deca471 100644
--- a/configure.ac
+++ b/configure.ac
@@ -211,9 +211,12 @@ AS_CASE([$CC], [*clang*],
-Wno-gnu-variable-sized-type-not-at-end \
])])
+AC_ARG_ENABLE([lto], [AS_HELP_STRING([--disable-lto], [disable -flto])],
+ [], [enable_lto=yes])
AS_CASE([$CFLAGS], [*-O[[12345sz\ ]]*],
- [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [\
- -flto])],
+ [AS_IF([test "x$enable_lto" = "xyes"],
+ [CC_CHECK_FLAGS_APPEND([with_cflags], [CFLAGS], [-flto])],
+ [AC_MSG_RESULT([disabling -flto as requested])])],
[AC_MSG_RESULT([skipping -flto, optimization not enabled])])
AC_SUBST([OUR_CFLAGS], "$with_cflags $sanitizer_cflags")
diff --git a/man/systemd.resource-control.xml b/man/systemd.resource-control.xml
index bf44a68345..0e98ca78b8 100644
--- a/man/systemd.resource-control.xml
+++ b/man/systemd.resource-control.xml
@@ -99,9 +99,10 @@
<refsect1>
<title>Unified and Legacy Control Group Hierarchies</title>
- <para>The unified control group hierarchy is the new version of kernel control group interface. Depending on the
- resource type, there are differences in resource control capabilities. Also, because of interface changes, some
- resource types have a separate set of options on the unified hierarchy.</para>
+ <para>The unified control group hierarchy is the new version of kernel control group interface, see <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroup-v2.txt">cgroup-v2.txt</ulink>. Depending on the resource type,
+ there are differences in resource control capabilities. Also, because of interface changes, some resource types
+ have separate set of options on the unified hierarchy.</para>
<para>
<variablelist>
@@ -126,6 +127,13 @@
settings of a unit for a given resource type are for the other hierarchy type, the settings are translated and
applied. If there are any valid settings for the hierarchy in use, all translations are disabled for the resource
type. Mixing the two types of settings on a unit can lead to confusing results.</para>
+
+ <para>Legacy control group hierarchy (see <ulink
+ url="https://www.kernel.org/doc/Documentation/cgroup-v1/cgroups.txt">cgroups.txt</ulink>), also called cgroup-v1,
+ doesn't allow safe delegation of controllers to unprivileged processes. If the system uses the legacy control group
+ hierarchy, resource control is disabled for systemd user instance, see
+ <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
+ </para>
</refsect1>
<refsect1>
diff --git a/man/vconsole.conf.xml b/man/vconsole.conf.xml
index 27196d44e9..7f6ae3452f 100644
--- a/man/vconsole.conf.xml
+++ b/man/vconsole.conf.xml
@@ -55,8 +55,11 @@
<para>The <filename>/etc/vconsole.conf</filename> file configures
the virtual console, i.e. keyboard mapping and console font. It is
- applied at boot by
- <citerefentry><refentrytitle>systemd-vconsole-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
+ applied at boot by udev using <filename>90-vconsole.rules</filename> file.
+ You can safely mask this file if you want to avoid this kind of initialization.
+ There is also <citerefentry><refentrytitle>systemd-vconsole-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+ provided that you can conveniently use at any time to [re]initialize consoles.
+ </para>
<para>The basic file format of the
<filename>vconsole.conf</filename> is a newline-separated list of
@@ -68,10 +71,10 @@
<para>Note that the kernel command line options
<varname>vconsole.keymap=</varname>,
- <varname>vconsole.keymap.toggle=</varname>,
+ <varname>vconsole.keymap_toggle=</varname>,
<varname>vconsole.font=</varname>,
- <varname>vconsole.font.map=</varname>,
- <varname>vconsole.font.unimap=</varname> may be used
+ <varname>vconsole.font_map=</varname>,
+ <varname>vconsole.font_unimap=</varname> may be used
to override the console settings at boot.</para>
<para>Depending on the operating system other configuration files
diff --git a/src/login/logind-user.c b/src/login/logind-user.c
index 348e396292..63363035e7 100644
--- a/src/login/logind-user.c
+++ b/src/login/logind-user.c
@@ -893,7 +893,7 @@ int config_parse_user_tasks_max(
/* First, try to parse as percentage */
r = parse_percent(rvalue);
- if (r > 0 && r < 100)
+ if (r >= 0)
k = system_tasks_max_scale(r, 100U);
else {
diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c
index 91caae009e..782824ff38 100644
--- a/src/systemctl/systemctl.c
+++ b/src/systemctl/systemctl.c
@@ -5566,10 +5566,12 @@ static int enable_sysv_units(const char *verb, char **args) {
if (!found_sysv)
continue;
- if (found_native)
- log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
- else
- log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
+ if (!arg_quiet) {
+ if (found_native)
+ log_info("Synchronizing state of %s with SysV service script with %s.", name, argv[0]);
+ else
+ log_info("%s is not a native service, redirecting to systemd-sysv-install.", name);
+ }
if (!isempty(arg_root))
argv[c++] = q = strappend("--root=", arg_root);
diff --git a/src/test/test-condition.c b/src/test/test-condition.c
index 4ef61ebfa5..66003aa6bd 100644
--- a/src/test/test-condition.c
+++ b/src/test/test-condition.c
@@ -144,9 +144,9 @@ static void test_condition_test_host(void) {
assert_se(hostname);
/* if hostname looks like an id128 then skip testing it */
- if (id128_is_valid(hostname)) {
+ if (id128_is_valid(hostname))
log_notice("hostname is an id128, skipping test");
- } else {
+ else {
condition = condition_new(CONDITION_HOST, hostname, false, false);
assert_se(condition_test(condition));
condition_free(condition);
diff --git a/src/test/test-path-util.c b/src/test/test-path-util.c
index 6094d4c3e5..164a10d8a8 100644
--- a/src/test/test-path-util.c
+++ b/src/test/test-path-util.c
@@ -114,7 +114,8 @@ static void test_find_binary(const char *self) {
assert_se(find_binary(self, &p) == 0);
puts(p);
- assert_se(endswith(p, "/lt-test-path-util"));
+ /* libtool might prefix the binary name with "lt-" */
+ assert_se(endswith(p, "/lt-test-path-util") || endswith(p, "/test-path-util"));
assert_se(path_is_absolute(p));
free(p);
diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c
index 1118118450..59e6c90c9a 100644
--- a/src/vconsole/vconsole-setup.c
+++ b/src/vconsole/vconsole-setup.c
@@ -2,6 +2,7 @@
This file is part of systemd.
Copyright 2010 Kay Sievers
+ Copyright 2016 Michal Soltys <soltys@ziu.info>
systemd is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as published by
@@ -27,6 +28,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
+#include <termios.h>
#include <unistd.h>
#include "alloc-util.h"
@@ -50,67 +52,80 @@ static bool is_vconsole(int fd) {
return ioctl(fd, TIOCLINUX, data) >= 0;
}
-static int disable_utf8(int fd) {
- int r = 0, k;
+static bool is_allocated(unsigned int idx) {
+ char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)];
- if (ioctl(fd, KDSKBMODE, K_XLATE) < 0)
- r = -errno;
-
- k = loop_write(fd, "\033%@", 3, false);
- if (k < 0)
- r = k;
+ xsprintf(vcname, "/dev/vcs%i", idx);
+ return access(vcname, F_OK) == 0;
+}
- k = write_string_file("/sys/module/vt/parameters/default_utf8", "0", 0);
- if (k < 0)
- r = k;
+static bool is_allocated_byfd(int fd) {
+ struct vt_stat vcs = {};
- if (r < 0)
- log_warning_errno(r, "Failed to disable UTF-8: %m");
+ if (ioctl(fd, VT_GETSTATE, &vcs) < 0) {
+ log_warning_errno(errno, "VT_GETSTATE failed: %m");
+ return false;
+ }
+ return is_allocated(vcs.v_active);
+}
- return r;
+static bool is_settable(int fd) {
+ int r, curr_mode;
+
+ r = ioctl(fd, KDGKBMODE, &curr_mode);
+ /*
+ * Make sure we only adjust consoles in K_XLATE or K_UNICODE mode.
+ * Oterwise we would (likely) interfere with X11's processing of the
+ * key events.
+ *
+ * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
+ */
+ return r == 0 && IN_SET(curr_mode, K_XLATE, K_UNICODE);
}
-static int enable_utf8(int fd) {
- int r = 0, k;
- long current = 0;
-
- if (ioctl(fd, KDGKBMODE, &current) < 0 || current == K_XLATE) {
- /*
- * Change the current keyboard to unicode, unless it
- * is currently in raw or off mode anyway. We
- * shouldn't interfere with X11's processing of the
- * key events.
- *
- * http://lists.freedesktop.org/archives/systemd-devel/2013-February/008573.html
- *
- */
-
- if (ioctl(fd, KDSKBMODE, K_UNICODE) < 0)
- r = -errno;
+static int toggle_utf8(int fd, bool utf8) {
+ int r;
+ struct termios tc = {};
+
+ r = ioctl(fd, KDSKBMODE, utf8 ? K_UNICODE : K_XLATE);
+ if (r < 0)
+ return log_warning_errno(errno, "Failed to %s UTF-8 kbdmode: %m", utf8 ? "enable" : "disable");
+
+ r = loop_write(fd, utf8 ? "\033%G" : "\033%@", 3, false);
+ if (r < 0)
+ return log_warning_errno(r, "Failed to %s UTF-8 term processing: %m", utf8 ? "enable" : "disable");
+
+ r = tcgetattr(fd, &tc);
+ if (r >= 0) {
+ if (utf8)
+ tc.c_iflag |= IUTF8;
+ else
+ tc.c_iflag &= ~IUTF8;
+ r = tcsetattr(fd, TCSANOW, &tc);
}
+ if (r < 0)
+ return log_warning_errno(errno, "Failed to %s iutf8 flag: %m", utf8 ? "enable" : "disable");
- k = loop_write(fd, "\033%G", 3, false);
- if (k < 0)
- r = k;
+ return 0;
+}
- k = write_string_file("/sys/module/vt/parameters/default_utf8", "1", 0);
- if (k < 0)
- r = k;
+static int toggle_utf8_sysfs(bool utf8) {
+ int r;
+ r = write_string_file("/sys/module/vt/parameters/default_utf8", one_zero(utf8), 0);
if (r < 0)
- log_warning_errno(r, "Failed to enable UTF-8: %m");
-
+ log_warning_errno(r, "Failed to %s sysfs UTF-8 flag: %m", utf8 ? "enable" : "disable");
return r;
}
static int keyboard_load_and_wait(const char *vc, const char *map, const char *map_toggle, bool utf8) {
const char *args[8];
- int i = 0, r;
+ int i = 0;
pid_t pid;
/* An empty map means kernel map */
if (isempty(map))
- return 1;
+ return 0;
args[i++] = KBD_LOADKEYS;
args[i++] = "-q";
@@ -135,34 +150,31 @@ static int keyboard_load_and_wait(const char *vc, const char *map, const char *m
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true);
- if (r < 0)
- return r;
-
- return r == 0;
+ return wait_for_terminate_and_warn(KBD_LOADKEYS, pid, true);
}
static int font_load_and_wait(const char *vc, const char *font, const char *map, const char *unimap) {
const char *args[9];
- int i = 0, r;
+ int i = 0;
pid_t pid;
- /* An empty font means kernel font */
- if (isempty(font))
- return 1;
+ /* Any part can be set independently */
+ if (isempty(font) && isempty(map) && isempty(unimap))
+ return 0;
args[i++] = KBD_SETFONT;
args[i++] = "-C";
args[i++] = vc;
- args[i++] = font;
- if (map) {
+ if (!isempty(map)) {
args[i++] = "-m";
args[i++] = map;
}
- if (unimap) {
+ if (!isempty(unimap)) {
args[i++] = "-u";
args[i++] = unimap;
}
+ if (!isempty(font))
+ args[i++] = font;
args[i++] = NULL;
pid = fork();
@@ -177,11 +189,7 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
_exit(EXIT_FAILURE);
}
- r = wait_for_terminate_and_warn(KBD_SETFONT, pid, true);
- if (r < 0)
- return r;
-
- return r == 0;
+ return wait_for_terminate_and_warn(KBD_SETFONT, pid, true);
}
/*
@@ -189,13 +197,21 @@ static int font_load_and_wait(const char *vc, const char *font, const char *map,
* we update all possibly already allocated VTs with the configured
* font. It also allows to restart systemd-vconsole-setup.service,
* to apply a new font to all VTs.
+ *
+ * We also setup per-console utf8 related stuff: kbdmode, term
+ * processing, stty iutf8.
*/
-static void font_copy_to_all_vcs(int fd) {
+static void setup_remaining_vcs(int fd, bool utf8) {
+ struct console_font_op cfo = {
+ .op = KD_FONT_OP_GET, .flags = 0,
+ .width = 32, .height = 32,
+ .charcount = 512,
+ };
struct vt_stat vcs = {};
- unsigned char map8[E_TABSZ];
- unsigned short map16[E_TABSZ];
+ struct unimapinit adv = {};
struct unimapdesc unimapd;
_cleanup_free_ struct unipair* unipairs = NULL;
+ _cleanup_free_ void *fontbuf = NULL;
int i, r;
unipairs = new(struct unipair, USHRT_MAX);
@@ -204,54 +220,73 @@ static void font_copy_to_all_vcs(int fd) {
return;
}
+ fontbuf = malloc(cfo.width * cfo.height * cfo.charcount / 8);
+ if (!fontbuf) {
+ log_oom();
+ return;
+ }
+
/* get active, and 16 bit mask of used VT numbers */
r = ioctl(fd, VT_GETSTATE, &vcs);
if (r < 0) {
- log_debug_errno(errno, "VT_GETSTATE failed, ignoring: %m");
+ log_warning_errno(errno, "VT_GETSTATE failed, ignoring remaining consoles: %m");
return;
}
- for (i = 1; i <= 15; i++) {
- char vcname[strlen("/dev/vcs") + DECIMAL_STR_MAX(int)];
- _cleanup_close_ int vcfd = -1;
- struct console_font_op cfo = {};
+ /* get fonts from source console */
+ cfo.data = fontbuf;
+ r = ioctl(fd, KDFONTOP, &cfo);
+ if (r < 0)
+ log_warning_errno(errno, "KD_FONT_OP_GET failed, fonts will not be copied: %m");
+ else {
+ unimapd.entries = unipairs;
+ unimapd.entry_ct = USHRT_MAX;
+ r = ioctl(fd, GIO_UNIMAP, &unimapd);
+ if (r < 0)
+ log_warning_errno(errno, "GIO_UNIMAP failed, fonts will not be copied: %m");
+ else
+ cfo.op = KD_FONT_OP_SET;
+ }
+
+ for (i = 1; i <= 63; i++) {
+ char ttyname[strlen("/dev/tty") + DECIMAL_STR_MAX(int)];
+ _cleanup_close_ int fd_d = -1;
- if (i == vcs.v_active)
+ if (i == vcs.v_active || !is_allocated(i))
continue;
- /* skip non-allocated ttys */
- xsprintf(vcname, "/dev/vcs%i", i);
- if (access(vcname, F_OK) < 0)
+ /* try to open terminal */
+ xsprintf(ttyname, "/dev/tty%i", i);
+ fd_d = open_terminal(ttyname, O_RDWR|O_CLOEXEC);
+ if (fd_d < 0) {
+ log_warning_errno(fd_d, "Unable to open tty%i, fonts will not be copied: %m", i);
continue;
+ }
- xsprintf(vcname, "/dev/tty%i", i);
- vcfd = open_terminal(vcname, O_RDWR|O_CLOEXEC);
- if (vcfd < 0)
+ if (!is_settable(fd_d))
continue;
- /* copy font from active VT, where the font was uploaded to */
- cfo.op = KD_FONT_OP_COPY;
- cfo.height = vcs.v_active-1; /* tty1 == index 0 */
- (void) ioctl(vcfd, KDFONTOP, &cfo);
+ toggle_utf8(fd_d, utf8);
- /* copy map of 8bit chars */
- if (ioctl(fd, GIO_SCRNMAP, map8) >= 0)
- (void) ioctl(vcfd, PIO_SCRNMAP, map8);
+ if (cfo.op != KD_FONT_OP_SET)
+ continue;
- /* copy map of 8bit chars -> 16bit Unicode values */
- if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0)
- (void) ioctl(vcfd, PIO_UNISCRNMAP, map16);
+ r = ioctl(fd_d, KDFONTOP, &cfo);
+ if (r < 0) {
+ log_warning_errno(errno, "KD_FONT_OP_SET failed, fonts will not be copied to tty%i: %m", i);
+ continue;
+ }
/* copy unicode translation table */
/* unimapd is a ushort count and a pointer to an
array of struct unipair { ushort, ushort } */
- unimapd.entries = unipairs;
- unimapd.entry_ct = USHRT_MAX;
- if (ioctl(fd, GIO_UNIMAP, &unimapd) >= 0) {
- struct unimapinit adv = { 0, 0, 0 };
-
- (void) ioctl(vcfd, PIO_UNIMAPCLR, &adv);
- (void) ioctl(vcfd, PIO_UNIMAP, &unimapd);
+ r = ioctl(fd_d, PIO_UNIMAPCLR, &adv);
+ if (r < 0)
+ log_warning_errno(errno, "PIO_UNIMAPCLR failed, unimaps might be incorrect for tty%i: %m", i);
+ else {
+ r = ioctl(fd_d, PIO_UNIMAP, &unimapd);
+ if (r < 0)
+ log_warning_errno(errno, "PIO_UNIMAP failed, unimaps might be incorrect for tty%i: %m", i);
}
}
}
@@ -289,6 +324,16 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
}
+ if (!is_allocated_byfd(fd)) {
+ log_error("Virtual console %s is not allocated.", vc);
+ return EXIT_FAILURE;
+ }
+
+ if (!is_settable(fd)) {
+ log_error("Virtual console %s is not in K_XLATE or K_UNICODE.", vc);
+ return EXIT_FAILURE;
+ }
+
utf8 = is_locale_utf8();
r = parse_env_file("/etc/vconsole.conf", NEWLINE,
@@ -306,8 +351,12 @@ int main(int argc, char **argv) {
if (detect_container() <= 0) {
r = parse_env_file("/proc/cmdline", WHITESPACE,
"vconsole.keymap", &vc_keymap,
- "vconsole.keymap.toggle", &vc_keymap_toggle,
+ "vconsole.keymap_toggle", &vc_keymap_toggle,
"vconsole.font", &vc_font,
+ "vconsole.font_map", &vc_font_map,
+ "vconsole.font_unimap", &vc_font_unimap,
+ /* compatibility with obsolete multiple-dot scheme */
+ "vconsole.keymap.toggle", &vc_keymap_toggle,
"vconsole.font.map", &vc_font_map,
"vconsole.font.unimap", &vc_font_unimap,
NULL);
@@ -316,17 +365,17 @@ int main(int argc, char **argv) {
log_warning_errno(r, "Failed to read /proc/cmdline: %m");
}
- if (utf8)
- (void) enable_utf8(fd);
- else
- (void) disable_utf8(fd);
+ toggle_utf8_sysfs(utf8);
+ toggle_utf8(fd, utf8);
+ font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) == 0;
+ keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) == 0;
- font_ok = font_load_and_wait(vc, vc_font, vc_font_map, vc_font_unimap) > 0;
- keyboard_ok = keyboard_load_and_wait(vc, vc_keymap, vc_keymap_toggle, utf8) > 0;
-
- /* Only copy the font when we executed setfont successfully */
- if (font_copy && font_ok)
- (void) font_copy_to_all_vcs(fd);
+ if (font_copy) {
+ if (font_ok)
+ setup_remaining_vcs(fd, utf8);
+ else
+ log_warning("Setting source virtual console failed, ignoring remaining ones.");
+ }
return font_ok && keyboard_ok ? EXIT_SUCCESS : EXIT_FAILURE;
}
diff --git a/test/udev-test.pl b/test/udev-test.pl
index 35a2668fb3..129af854f1 100755
--- a/test/udev-test.pl
+++ b/test/udev-test.pl
@@ -1538,15 +1538,15 @@ if (!($<==0)) {
# skip the test when running in a chroot
system("systemd-detect-virt", "-r", "-q");
if ($? >> 8 == 0) {
- print "Running in a chroot, skipping the test.\n";
- exit($EXIT_TEST_SKIP);
+ print "Running in a chroot, skipping the test.\n";
+ exit($EXIT_TEST_SKIP);
}
# skip the test when running in a container
system("systemd-detect-virt", "-c", "-q");
if ($? >> 8 == 0) {
- print "Running in a container, skipping the test.\n";
- exit($EXIT_TEST_SKIP);
+ print "Running in a container, skipping the test.\n";
+ exit($EXIT_TEST_SKIP);
}
udev_setup();
diff --git a/units/systemd-vconsole-setup.service.in b/units/systemd-vconsole-setup.service.in
index 6160361871..2bd1fd1a5d 100644
--- a/units/systemd-vconsole-setup.service.in
+++ b/units/systemd-vconsole-setup.service.in
@@ -9,11 +9,8 @@
Description=Setup Virtual Console
Documentation=man:systemd-vconsole-setup.service(8) man:vconsole.conf(5)
DefaultDependencies=no
-Conflicts=shutdown.target
-Before=sysinit.target shutdown.target
ConditionPathExists=/dev/tty0
[Service]
Type=oneshot
-RemainAfterExit=yes
ExecStart=@rootlibexecdir@/systemd-vconsole-setup