diff --git a/Makefile.am b/Makefile.am index 3d9e5c1..46487f6 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1095,7 +1095,7 @@ BUILT_SOURCES += \ src/shared/errno-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) - $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include errno.h - < /dev/null | $(AWK) '/^#define[ \t]+E[^ _]+[ \t]+[0-9]/ { print $$2; }' > $@ + $(AM_V_GEN)$(CPP) $(CFLAGS) $(AM_CPPFLAGS) $(CPPFLAGS) -dM -include errno.h - < /dev/null | $(AWK) '/^#define[ \t]+E[^ _]+[ \t]+/ { print $$2; }' > $@ src/shared/errno-from-name.gperf: src/shared/errno-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) @@ -1107,7 +1107,7 @@ src/shared/errno-from-name.h: src/shared/errno-from-name.gperf src/shared/errno-to-name.h: src/shared/errno-list.txt $(AM_V_at)$(MKDIR_P) $(dir $@) - $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const errno_names[] = { "} { printf "[%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' < $< > $@ + $(AM_V_GEN)$(AWK) 'BEGIN{ print "static const char* const errno_names[] = { "} !/EDEADLOCK/ && !/EWOULDBLOCK/ && !/ENOTSUP/ { printf "[%s] = \"%s\",\n", $$1, $$1 } END{print "};"}' < $< > $@ src/shared/af-list.txt: $(AM_V_at)$(MKDIR_P) $(dir $@) @@ -1707,7 +1707,9 @@ dist_tmpfiles_DATA += \ endif SYSINIT_TARGET_WANTS += \ - systemd-tmpfiles-setup-dev.service \ + systemd-tmpfiles-setup-dev.service + +MULTI_USER_TARGET_WANTS += \ systemd-tmpfiles-setup.service dist_zshcompletion_DATA += \ @@ -1961,6 +1963,7 @@ systemd_cgls_SOURCES = \ src/cgls/cgls.c systemd_cgls_LDADD = \ + libsystemd-internal.la \ libsystemd-shared.la # ------------------------------------------------------------------------------ diff --git a/TODO b/TODO index e2ca1e6..d7efdd5 100644 --- a/TODO +++ b/TODO @@ -1,4 +1,6 @@ Bugfixes: +* Should systemctl status \* work on all unit types, not just .service? + * enabling an instance unit creates a pointless link, and the unit will be started with getty@getty.service: $ systemctl enable getty@.service diff --git a/rules/42-usb-hid-pm.rules b/rules/42-usb-hid-pm.rules index c675b5b..4c300da 100644 --- a/rules/42-usb-hid-pm.rules +++ b/rules/42-usb-hid-pm.rules @@ -12,10 +12,6 @@ ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Mouse", ATTR{serial}!= ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Tablet", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto" ACTION=="add", SUBSYSTEM=="usb", ATTR{product}=="QEMU USB Keyboard", ATTR{serial}!="1", TEST=="power/control", ATTR{power/control}="auto" -# Catch-all for Avocent HID devices. Keyed off interface in order to only -# trigger on HID class devices. -ACTION=="add", SUBSYSTEM=="usb", ATTRS{idVendor}=="0624", ATTR{bInterfaceClass}=="03", TEST=="../power/control", ATTR{../power/control}="auto" - # Dell DRAC 4 ACTION=="add", SUBSYSTEM=="usb", ATTR{idVendor}=="413c", ATTR{idProduct}=="2500", TEST=="power/control", ATTR{power/control}="auto" diff --git a/rules/99-systemd.rules.in b/rules/99-systemd.rules.in index db72373..2875958 100644 --- a/rules/99-systemd.rules.in +++ b/rules/99-systemd.rules.in @@ -14,10 +14,6 @@ KERNEL=="vport*", TAG+="systemd" SUBSYSTEM=="block", KERNEL!="ram*", TAG+="systemd" SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UDEV_DISABLE_OTHER_RULES_FLAG}=="1", ENV{SYSTEMD_READY}="0" -# Ignore encrypted devices with no identified superblock on it, since -# we are probably still calling mke2fs or mkswap on it. -SUBSYSTEM=="block", KERNEL!="ram*", ENV{DM_UUID}=="CRYPT-*", ENV{ID_PART_TABLE_TYPE}=="", ENV{ID_FS_USAGE}=="", ENV{SYSTEMD_READY}="0" - # Ignore raid devices that are not yet assembled and started SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", TEST!="md/array_state", ENV{SYSTEMD_READY}="0" SUBSYSTEM=="block", ENV{DEVTYPE}=="disk", KERNEL=="md*", ATTR{md/array_state}=="|clear|inactive", ENV{SYSTEMD_READY}="0" @@ -43,7 +39,7 @@ SUBSYSTEM=="net", KERNEL!="lo", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsys SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_ALIAS}+="/sys/subsystem/bluetooth/devices/%k" SUBSYSTEM=="bluetooth", TAG+="systemd", ENV{SYSTEMD_WANTS}+="bluetooth.target" -ENV{ID_SMARTCARD_READER}=="*?", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" +ENV{ID_SMARTCARD_READER}=="?*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="smartcard.target" SUBSYSTEM=="sound", KERNEL=="card*", TAG+="systemd", ENV{SYSTEMD_WANTS}+="sound.target" SUBSYSTEM=="printer", TAG+="systemd", ENV{SYSTEMD_WANTS}+="printer.target" diff --git a/src/cgls/cgls.c b/src/cgls/cgls.c index b8e275d..1840594 100644 --- a/src/cgls/cgls.c +++ b/src/cgls/cgls.c @@ -35,6 +35,10 @@ #include "build.h" #include "output-mode.h" #include "fileio.h" +#include "sd-bus.h" +#include "bus-util.h" +#include "bus-error.h" +#include "unit-name.h" static bool arg_no_pager = false; static bool arg_kernel_threads = false; @@ -127,6 +131,7 @@ int main(int argc, char *argv[]) { int r = 0, retval = EXIT_FAILURE; int output_flags; char _cleanup_free_ *root = NULL; + _cleanup_bus_unref_ sd_bus *bus = NULL; log_parse_environment(); log_open(); @@ -151,6 +156,12 @@ int main(int argc, char *argv[]) { arg_all * OUTPUT_SHOW_ALL | (arg_full > 0) * OUTPUT_FULL_WIDTH; + r = bus_open_transport(BUS_TRANSPORT_LOCAL, NULL, false, &bus); + if (r < 0) { + log_error("Failed to create bus connection: %s", strerror(-r)); + goto finish; + } + if (optind < argc) { int i; @@ -189,8 +200,52 @@ int main(int argc, char *argv[]) { } else { if (arg_machine) { char *m; + const char *cgroup; + _cleanup_free_ char *scope = NULL; + _cleanup_free_ char *path = NULL; + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; + m = strappenda("/run/systemd/machines/", arg_machine); - r = parse_env_file(m, NEWLINE, "CGROUP", &root, NULL); + r = parse_env_file(m, NEWLINE, "SCOPE", &scope, NULL); + if (r < 0) { + log_error("Failed to get machine path: %s", strerror(-r)); + goto finish; + } + + path = unit_dbus_path_from_name(scope); + if (!path) { + r = log_oom(); + goto finish; + } + + r = sd_bus_get_property( + bus, + "org.freedesktop.systemd1", + path, + "org.freedesktop.systemd1.Scope", + "ControlGroup", + &error, + &reply, + "s"); + + if (r < 0) { + log_error("Failed to query ControlGroup: %s", bus_error_message(&error, -r)); + goto finish; + } + + r = sd_bus_message_read(reply, "s", &cgroup); + if (r < 0) { + bus_log_parse_error(r); + goto finish; + } + + root = strdup(cgroup); + if (!root) { + r = log_oom(); + goto finish; + } + } else r = cg_get_root_path(&root); if (r < 0) { diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 3dd4c91..4201e1e 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -871,7 +871,7 @@ int manager_setup_cgroup(Manager *m) { safe_close(m->pin_cgroupfs_fd); m->pin_cgroupfs_fd = open(path, O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY|O_NONBLOCK); - if (r < 0) { + if (m->pin_cgroupfs_fd < 0) { log_error("Failed to open pin file: %m"); return -errno; } diff --git a/src/core/dbus-cgroup.c b/src/core/dbus-cgroup.c index 775825b..5b1c4e3 100644 --- a/src/core/dbus-cgroup.c +++ b/src/core/dbus-cgroup.c @@ -173,6 +173,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->cpu_accounting = b; + u->cgroup_realized_mask &= ~CGROUP_CPUACCT; unit_write_drop_in_private(u, mode, name, b ? "CPUAccounting=yes" : "CPUAccounting=no"); } @@ -192,6 +193,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->cpu_shares = ul; + u->cgroup_realized_mask &= ~CGROUP_CPU; unit_write_drop_in_private_format(u, mode, name, "CPUShares=%lu", ul); } @@ -206,6 +208,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->blockio_accounting = b; + u->cgroup_realized_mask &= ~CGROUP_BLKIO; unit_write_drop_in_private(u, mode, name, b ? "BlockIOAccounting=yes" : "BlockIOAccounting=no"); } @@ -225,6 +228,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->blockio_weight = ul; + u->cgroup_realized_mask &= ~CGROUP_BLKIO; unit_write_drop_in_private_format(u, mode, name, "BlockIOWeight=%lu", ul); } @@ -294,6 +298,8 @@ int bus_cgroup_set_property( cgroup_context_free_blockio_device_bandwidth(c, a); } + u->cgroup_realized_mask &= ~CGROUP_BLKIO; + f = open_memstream(&buf, &size); if (!f) return -ENOMEM; @@ -375,6 +381,8 @@ int bus_cgroup_set_property( cgroup_context_free_blockio_device_weight(c, c->blockio_device_weights); } + u->cgroup_realized_mask &= ~CGROUP_BLKIO; + f = open_memstream(&buf, &size); if (!f) return -ENOMEM; @@ -398,6 +406,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_accounting = b; + u->cgroup_realized_mask &= ~CGROUP_MEMORY; unit_write_drop_in_private(u, mode, name, b ? "MemoryAccounting=yes" : "MemoryAccounting=no"); } @@ -412,6 +421,7 @@ int bus_cgroup_set_property( if (mode != UNIT_CHECK) { c->memory_limit = limit; + u->cgroup_realized_mask &= ~CGROUP_MEMORY; unit_write_drop_in_private_format(u, mode, name, "%s=%" PRIu64, name, limit); } @@ -433,6 +443,7 @@ int bus_cgroup_set_property( char *buf; c->device_policy = p; + u->cgroup_realized_mask &= ~CGROUP_DEVICE; buf = strappenda("DevicePolicy=", policy); unit_write_drop_in_private(u, mode, name, buf); @@ -511,6 +522,8 @@ int bus_cgroup_set_property( cgroup_context_free_device_allow(c, c->device_allow); } + u->cgroup_realized_mask &= ~CGROUP_DEVICE; + f = open_memstream(&buf, &size); if (!f) return -ENOMEM; diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index 13b3d0d..37d4154 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -842,7 +842,7 @@ int bus_exec_context_set_transient_property( strv_free(c->environment); c->environment = e; - joined = strv_join(c->environment, " "); + joined = strv_join_quoted(c->environment); if (!joined) return -ENOMEM; diff --git a/src/core/job.c b/src/core/job.c index 35a9de6..dc4f441 100644 --- a/src/core/job.c +++ b/src/core/job.c @@ -1060,6 +1060,9 @@ int job_coldplug(Job *j) { if (r < 0) return r; + if (j->state == JOB_WAITING) + job_add_to_run_queue(j); + if (j->begin_usec == 0 || j->unit->job_timeout == 0) return 0; diff --git a/src/core/killall.c b/src/core/killall.c index 57ed41c..eab48f7 100644 --- a/src/core/killall.c +++ b/src/core/killall.c @@ -168,7 +168,7 @@ static int killall(int sig, Set *pids, bool send_sighup) { continue; if (sig == SIGKILL) { - _cleanup_free_ char *s; + _cleanup_free_ char *s = NULL; get_process_comm(pid, &s); log_notice("Sending SIGKILL to PID "PID_FMT" (%s).", pid, strna(s)); diff --git a/src/core/machine-id-setup.c b/src/core/machine-id-setup.c index d459afe..2a58e48 100644 --- a/src/core/machine-id-setup.c +++ b/src/core/machine-id-setup.c @@ -93,32 +93,9 @@ static int generate(char id[34], const char *root) { } } - /* If that didn't work, see if we are running in qemu/kvm and a - * machine ID was passed in via -uuid on the qemu/kvm command - * line */ - - r = detect_vm(&vm_id); - if (r > 0 && streq(vm_id, "kvm")) { - char uuid[37]; - - fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); - if (fd >= 0) { - k = loop_read(fd, uuid, 36, false); - safe_close(fd); - - if (k >= 36) { - r = shorten_uuid(id, uuid); - if (r >= 0) { - log_info("Initializing machine ID from KVM UUID."); - return 0; - } - } - } - } - - /* If that didn't work either, see if we are running in a - * container, and a machine ID was passed in via - * $container_uuid the way libvirt/LXC does it */ + /* If that didn't work, see if we are running in a container, + * and a machine ID was passed in via $container_uuid the way + * libvirt/LXC does it */ r = detect_container(NULL); if (r > 0) { _cleanup_free_ char *e = NULL; @@ -133,6 +110,30 @@ static int generate(char id[34], const char *root) { } } } + + } else { + /* If we are not running in a container, see if we are + * running in qemu/kvm and a machine ID was passed in + * via -uuid on the qemu/kvm command line */ + + r = detect_vm(&vm_id); + if (r > 0 && streq(vm_id, "kvm")) { + char uuid[37]; + + fd = open("/sys/class/dmi/id/product_uuid", O_RDONLY|O_CLOEXEC|O_NOCTTY|O_NOFOLLOW); + if (fd >= 0) { + k = loop_read(fd, uuid, 36, false); + safe_close(fd); + + if (k >= 36) { + r = shorten_uuid(id, uuid); + if (r >= 0) { + log_info("Initializing machine ID from KVM UUID."); + return 0; + } + } + } + } } /* If that didn't work, generate a random machine id */ diff --git a/src/core/main.c b/src/core/main.c index 41605ee..c65701d 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1840,6 +1840,7 @@ finish: if (reexecute) { const char **args; unsigned i, args_size; + sigset_t ss; /* Close and disarm the watchdog, so that the new * instance can reinitialize it, but doesn't get @@ -1883,7 +1884,7 @@ finish: char_array_0(sfd); i = 0; - args[i++] = SYSTEMD_BINARY_PATH; + args[i++] = "/run/current-system/systemd/lib/systemd/systemd"; if (switch_root_dir) args[i++] = "--switched-root"; args[i++] = arg_running_as == SYSTEMD_SYSTEM ? "--system" : "--user"; @@ -1923,6 +1924,13 @@ finish: args[i++] = NULL; assert(i <= args_size); + /* reenable any blocked signals, especially important + * if we switch from initial ramdisk to init=... */ + reset_all_signal_handlers(); + + assert_se(sigemptyset(&ss) == 0); + assert_se(sigprocmask(SIG_SETMASK, &ss, NULL) == 0); + if (switch_root_init) { args[0] = switch_root_init; execv(args[0], (char* const*) args); diff --git a/src/core/manager.c b/src/core/manager.c index 224106c..7342095 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -422,7 +422,7 @@ int manager_new(SystemdRunningAs running_as, Manager **_m) { return -ENOMEM; #ifdef ENABLE_EFI - if (detect_container(NULL) <= 0) + if (running_as == SYSTEMD_SYSTEM && detect_container(NULL) <= 0) boot_timestamps(&m->userspace_timestamp, &m->firmware_timestamp, &m->loader_timestamp); #endif @@ -2129,9 +2129,6 @@ int manager_serialize(Manager *m, FILE *f, FDSet *fds, bool switching_root) { if (u->id != t) continue; - if (!unit_can_serialize(u)) - continue; - /* Start marker */ fputs(u->id, f); fputc('\n', f); diff --git a/src/core/namespace.c b/src/core/namespace.c index 9f15211..e41cf5b 100644 --- a/src/core/namespace.c +++ b/src/core/namespace.c @@ -42,6 +42,7 @@ #include "mkdir.h" #include "dev-setup.h" #include "def.h" +#include "label.h" typedef enum MountMode { /* This is ordered by priority! */ @@ -68,6 +69,7 @@ static int append_mounts(BindMount **p, char **strv, MountMode mode) { STRV_FOREACH(i, strv) { (*p)->ignore = false; + (*p)->done = false; if ((mode == INACCESSIBLE || mode == READONLY || mode == READWRITE) && (*i)[0] == '-') { (*p)->ignore = true; @@ -217,7 +219,10 @@ static int mount_dev(BindMount *m) { goto fail; } + label_context_set(d, st.st_mode); r = mknod(dn, st.st_mode, st.st_rdev); + label_context_clear(); + if (r < 0) { r = -errno; goto fail; @@ -350,7 +355,7 @@ int setup_namespace( private_dev; if (n > 0) { - m = mounts = (BindMount *) alloca(n * sizeof(BindMount)); + m = mounts = (BindMount *) alloca0(n * sizeof(BindMount)); r = append_mounts(&m, read_write_dirs, READWRITE); if (r < 0) return r; diff --git a/src/core/service.c b/src/core/service.c index ae3695a..6b3aa45 100644 --- a/src/core/service.c +++ b/src/core/service.c @@ -1096,11 +1096,6 @@ static int service_verify(Service *s) { return -EINVAL; } - if (s->type == SERVICE_ONESHOT && s->restart != SERVICE_RESTART_NO) { - log_error_unit(UNIT(s)->id, "%s has Restart setting other than no, which isn't allowed for Type=oneshot services. Refusing.", UNIT(s)->id); - return -EINVAL; - } - if (s->type == SERVICE_DBUS && !s->bus_name) { log_error_unit(UNIT(s)->id, "%s is of type D-Bus but no D-Bus service name has been specified. Refusing.", UNIT(s)->id); return -EINVAL; diff --git a/src/core/socket.c b/src/core/socket.c index 7c18a2b..1a560a6 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -663,16 +663,25 @@ static int instance_from_socket(int fd, unsigned nr, char **instance) { int k; k = getpeercred(fd, &ucred); - if (k < 0) + if (k == -ENODATA) { + /* This handles the case where somebody is + * connecting from another pid/uid namespace + * (e.g. from outside of our container). */ + if (asprintf(&r, + "%u-unknown", + nr) < 0) + return -ENOMEM; + } + else if (k < 0) return k; - - if (asprintf(&r, - "%u-%lu-%lu", - nr, - (unsigned long) ucred.pid, - (unsigned long) ucred.uid) < 0) - return -ENOMEM; - + else { + if (asprintf(&r, + "%u-%lu-%lu", + nr, + (unsigned long) ucred.pid, + (unsigned long) ucred.uid) < 0) + return -ENOMEM; + } break; } @@ -1242,6 +1251,8 @@ static int socket_spawn(Socket *s, ExecCommand *c, pid_t *_pid) { NULL, s->exec_runtime, &pid); + if (r < 0) + goto fail; strv_free(argv); if (r < 0) @@ -1497,6 +1508,12 @@ static void socket_enter_running(Socket *s, int cfd) { } if (!pending) { + if (!UNIT_ISSET(s->service)) { + log_error_unit(UNIT(s)->id, "%s: service to activate vanished, refusing activation.", UNIT(s)->id); + r = -ENOENT; + goto fail; + } + r = manager_add_job(UNIT(s)->manager, JOB_START, UNIT_DEREF(s->service), JOB_REPLACE, true, &error, NULL); if (r < 0) goto fail; diff --git a/src/core/timer.c b/src/core/timer.c index 6c85304..720b8af 100644 --- a/src/core/timer.c +++ b/src/core/timer.c @@ -111,6 +111,23 @@ static int timer_add_default_dependencies(Timer *t) { return unit_add_two_dependencies_by_name(UNIT(t), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_SHUTDOWN_TARGET, NULL, true); } +static void update_stampfile(Timer *t, usec_t timestamp) { + _cleanup_close_ int fd = -1; + + mkdir_parents_label(t->stamp_path, 0755); + + /* Update the file atime + mtime, if we can */ + fd = open(t->stamp_path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644); + if (fd >= 0) { + struct timespec ts[2]; + + timespec_store(&ts[0], timestamp); + ts[1] = ts[0]; + + futimens(fd, ts); + } +} + static int timer_setup_persistent(Timer *t) { int r; @@ -131,7 +148,7 @@ static int timer_setup_persistent(Timer *t) { e = getenv("XDG_DATA_HOME"); if (e) - t->stamp_path = strjoin(e, "/systemd/timers/", UNIT(t)->id, NULL); + t->stamp_path = strjoin(e, "/systemd/timers/stamp-", UNIT(t)->id, NULL); else { _cleanup_free_ char *h = NULL; @@ -496,22 +513,8 @@ static void timer_enter_running(Timer *t) { dual_timestamp_get(&t->last_trigger); - if (t->stamp_path) { - _cleanup_close_ int fd = -1; - - mkdir_parents_label(t->stamp_path, 0755); - - /* Update the file atime + mtime, if we can */ - fd = open(t->stamp_path, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644); - if (fd >= 0) { - struct timespec ts[2]; - - timespec_store(&ts[0], t->last_trigger.realtime); - ts[1] = ts[0]; - - futimens(fd, ts); - } - } + if (t->stamp_path) + update_stampfile(t, t->last_trigger.realtime); timer_set_state(t, TIMER_RUNNING); return; @@ -539,6 +542,11 @@ static int timer_start(Unit *u) { if (stat(t->stamp_path, &st) >= 0) t->last_trigger.realtime = timespec_load(&st.st_atim); + else if (errno == ENOENT) + /* The timer has never run before, + * make sure a stamp file exists. + */ + update_stampfile(t, now(CLOCK_REALTIME)); } t->result = TIMER_SUCCESS; diff --git a/src/core/transaction.c b/src/core/transaction.c index d00f427..2befc32 100644 --- a/src/core/transaction.c +++ b/src/core/transaction.c @@ -378,7 +378,7 @@ static int transaction_verify_order_one(Transaction *tr, Job *j, Job *from, unsi "Found dependency on %s/%s", k->unit->id, job_type_to_string(k->type)); - if (!delete && + if (!delete && hashmap_get(tr->jobs, k->unit) && !unit_matters_to_anchor(k->unit, k)) { /* Ok, we can drop this one, so let's * do so. */ diff --git a/src/core/umount.c b/src/core/umount.c index d1258f0..0311812 100644 --- a/src/core/umount.c +++ b/src/core/umount.c @@ -404,6 +404,8 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool log_e * anyway, since we are running from it. They have * already been remounted ro. */ if (path_equal(m->path, "/") + || path_equal(m->path, "/nix") + || path_equal(m->path, "/nix/store") #ifndef HAVE_SPLIT_USR || path_equal(m->path, "/usr") #endif diff --git a/src/core/unit.c b/src/core/unit.c index 153b79b..ed52694 100644 --- a/src/core/unit.c +++ b/src/core/unit.c @@ -2287,25 +2287,25 @@ bool unit_can_serialize(Unit *u) { } int unit_serialize(Unit *u, FILE *f, FDSet *fds, bool serialize_jobs) { - ExecRuntime *rt; int r; assert(u); assert(f); assert(fds); - if (!unit_can_serialize(u)) - return 0; - - r = UNIT_VTABLE(u)->serialize(u, f, fds); - if (r < 0) - return r; + if (unit_can_serialize(u)) { + ExecRuntime *rt; - rt = unit_get_exec_runtime(u); - if (rt) { - r = exec_runtime_serialize(rt, u, f, fds); + r = UNIT_VTABLE(u)->serialize(u, f, fds); if (r < 0) return r; + + rt = unit_get_exec_runtime(u); + if (rt) { + r = exec_runtime_serialize(rt, u, f, fds); + if (r < 0) + return r; + } } dual_timestamp_serialize(f, "inactive-exit-timestamp", &u->inactive_exit_timestamp); @@ -2367,17 +2367,14 @@ void unit_serialize_item(Unit *u, FILE *f, const char *key, const char *value) { } int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { - size_t offset; ExecRuntime **rt = NULL; + size_t offset; int r; assert(u); assert(f); assert(fds); - if (!unit_can_serialize(u)) - return 0; - offset = UNIT_VTABLE(u)->exec_runtime_offset; if (offset > 0) rt = (ExecRuntime**) ((uint8_t*) u + offset); @@ -2487,24 +2484,34 @@ int unit_deserialize(Unit *u, FILE *f, FDSet *fds) { if (!s) return -ENOMEM; - free(u->cgroup_path); - u->cgroup_path = s; + if (u->cgroup_path) { + void *p; + p = hashmap_remove(u->manager->cgroup_unit, u->cgroup_path); + log_info("Removing cgroup_path %s from hashmap (%p)", + u->cgroup_path, p); + free(u->cgroup_path); + } + + u->cgroup_path = s; assert(hashmap_put(u->manager->cgroup_unit, s, u) == 1); + continue; } - if (rt) { - r = exec_runtime_deserialize_item(rt, u, l, v, fds); + if (unit_can_serialize(u)) { + if (rt) { + r = exec_runtime_deserialize_item(rt, u, l, v, fds); + if (r < 0) + return r; + if (r > 0) + continue; + } + + r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds); if (r < 0) return r; - if (r > 0) - continue; } - - r = UNIT_VTABLE(u)->deserialize_item(u, l, v, fds); - if (r < 0) - return r; } } diff --git a/src/cryptsetup/cryptsetup-generator.c b/src/cryptsetup/cryptsetup-generator.c index 75d56dd..be8fb2f 100644 --- a/src/cryptsetup/cryptsetup-generator.c +++ b/src/cryptsetup/cryptsetup-generator.c @@ -29,6 +29,7 @@ #include "mkdir.h" #include "strv.h" #include "fileio.h" +#include "path-util.h" static const char *arg_dest = "/tmp"; static bool arg_enabled = true; @@ -144,16 +145,19 @@ static int create_disk( if (!uu) return log_oom(); - if (is_device_path(uu)) { - _cleanup_free_ char *dd; + if (!path_equal(uu, "/dev/null")) { - dd = unit_name_from_path(uu, ".device"); - if (!dd) - return log_oom(); + if (is_device_path(uu)) { + _cleanup_free_ char *dd; - fprintf(f, "After=%1$s\nRequires=%1$s\n", dd); - } else - fprintf(f, "RequiresMountsFor=%s\n", password); + dd = unit_name_from_path(uu, ".device"); + if (!dd) + return log_oom(); + + fprintf(f, "After=%1$s\nRequires=%1$s\n", dd); + } else + fprintf(f, "RequiresMountsFor=%s\n", password); + } } } @@ -287,7 +291,7 @@ static int parse_proc_cmdline_item(const char *key, const char *value) { } else if (STR_IN_SET(key, "luks.key", "rd.luks.key") && value) { free(arg_keyfile); - arg_keyfile = strdup(key); + arg_keyfile = strdup(value); if (!arg_keyfile) return log_oom(); diff --git a/src/cryptsetup/cryptsetup.c b/src/cryptsetup/cryptsetup.c index 9b9074c..ad6c76c 100644 --- a/src/cryptsetup/cryptsetup.c +++ b/src/cryptsetup/cryptsetup.c @@ -88,6 +88,13 @@ static int parse_one_option(const char *option) { return 0; } + if (arg_key_size % 8) { + log_error("size= not a multiple of 8, ignoring."); + return 0; + } + + arg_key_size /= 8; + } else if (startswith(option, "key-slot=")) { arg_type = CRYPT_LUKS1; @@ -404,7 +411,7 @@ static int attach_luks_or_plain(struct crypt_device *cd, /* for CRYPT_PLAIN limit reads * from keyfile to key length, and * ignore keyfile-size */ - arg_keyfile_size = arg_key_size / 8; + arg_keyfile_size = arg_key_size; /* In contrast to what the name * crypt_setup() might suggest this @@ -567,7 +574,7 @@ int main(int argc, char *argv[]) { else until = 0; - arg_key_size = (arg_key_size > 0 ? arg_key_size : 256); + arg_key_size = (arg_key_size > 0 ? arg_key_size : (256 / 8)); if (key_file) { struct stat st; diff --git a/src/fsck/fsck.c b/src/fsck/fsck.c index 18f2aca..2a2b1ea 100644 --- a/src/fsck/fsck.c +++ b/src/fsck/fsck.c @@ -285,7 +285,7 @@ int main(int argc, char *argv[]) { type = udev_device_get_property_value(udev_device, "ID_FS_TYPE"); if (type) { - const char *checker = strappenda("/sbin/fsck.", type); + const char *checker = strappenda("/run/current-system/sw/sbin/fsck.", type); r = access(checker, X_OK); if (r < 0) { if (errno == ENOENT) { @@ -302,7 +302,7 @@ int main(int argc, char *argv[]) { return EXIT_FAILURE; } - cmdline[i++] = "/sbin/fsck"; + cmdline[i++] = "/run/current-system/sw/sbin/fsck"; cmdline[i++] = "-a"; cmdline[i++] = "-T"; cmdline[i++] = "-l"; diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c index 6a4aa2c..700e90a 100644 --- a/src/getty-generator/getty-generator.c +++ b/src/getty-generator/getty-generator.c @@ -72,7 +72,7 @@ static int add_serial_getty(const char *tty) { log_debug("Automatically adding serial getty for /dev/%s.", tty); - n = unit_name_replace_instance("serial-getty@.service", tty); + n = unit_name_from_path_instance("serial-getty", tty, ".service"); if (!n) return log_oom(); @@ -86,7 +86,7 @@ static int add_container_getty(const char *tty) { log_debug("Automatically adding container getty for /dev/pts/%s.", tty); - n = unit_name_replace_instance("container-getty@.service", tty); + n = unit_name_from_path_instance("container-getty", tty, ".service"); if (!n) return log_oom(); diff --git a/src/journal/catalog.c b/src/journal/catalog.c index 3ed0b7e..02dedc4 100644 --- a/src/journal/catalog.c +++ b/src/journal/catalog.c @@ -103,7 +103,7 @@ static int finish_item( const char *payload) { ssize_t offset; - CatalogItem *i; + _cleanup_free_ CatalogItem *i = NULL; int r; assert(h); @@ -126,13 +126,14 @@ static int finish_item( i->offset = htole64((uint64_t) offset); r = hashmap_put(h, i, i); - if (r == EEXIST) { + if (r == -EEXIST) { log_warning("Duplicate entry for " SD_ID128_FORMAT_STR ".%s, ignoring.", SD_ID128_FORMAT_VAL(id), language ? language : "C"); - free(i); return 0; - } + } else if (r < 0) + return r; + i = NULL; return 0; } @@ -383,8 +384,8 @@ error: int catalog_update(const char* database, const char* root, const char* const* dirs) { _cleanup_strv_free_ char **files = NULL; char **f; - Hashmap *h; struct strbuf *sb = NULL; + _cleanup_hashmap_free_free_ Hashmap *h = NULL; _cleanup_free_ CatalogItem *items = NULL; CatalogItem *i; Iterator j; @@ -406,13 +407,17 @@ int catalog_update(const char* database, const char* root, const char* const* di } STRV_FOREACH(f, files) { - log_debug("reading file '%s'", *f); - catalog_import_file(h, sb, *f); + log_debug("Reading file '%s'", *f); + r = catalog_import_file(h, sb, *f); + if (r < 0) { + log_error("Failed to import file '%s': %s.", + *f, strerror(-r)); + goto finish; + } } if (hashmap_size(h) <= 0) { log_info("No items in catalog."); - r = 0; goto finish; } else log_debug("Found %u items in catalog.", hashmap_size(h)); @@ -443,11 +448,7 @@ int catalog_update(const char* database, const char* root, const char* const* di log_debug("%s: wrote %u items, with %zu bytes of strings, %ld total size.", database, n, sb->len, r); - r = 0; - finish: - if (h) - hashmap_free_free(h); if (sb) strbuf_cleanup(sb); diff --git a/src/journal/journal-file.c b/src/journal/journal-file.c index f2f1f35..fd9d2a8 100644 --- a/src/journal/journal-file.c +++ b/src/journal/journal-file.c @@ -274,12 +274,6 @@ static int journal_file_verify_header(JournalFile *f) { !VALID64(le64toh(f->header->entry_array_offset))) return -ENODATA; - if (le64toh(f->header->data_hash_table_offset) < le64toh(f->header->header_size) || - le64toh(f->header->field_hash_table_offset) < le64toh(f->header->header_size) || - le64toh(f->header->tail_object_offset) < le64toh(f->header->header_size) || - le64toh(f->header->entry_array_offset) < le64toh(f->header->header_size)) - return -ENODATA; - if (f->writable) { uint8_t state; sd_id128_t machine_id; diff --git a/src/journal/journal-remote-parse.c b/src/journal/journal-remote-parse.c index 142de0e..239ff38 100644 --- a/src/journal/journal-remote-parse.c +++ b/src/journal/journal-remote-parse.c @@ -40,7 +40,7 @@ void source_free(RemoteSource *source) { static int get_line(RemoteSource *source, char **line, size_t *size) { ssize_t n, remain; - char *c; + char *c = NULL; char *newbuf = NULL; size_t newsize = 0; @@ -49,7 +49,9 @@ static int get_line(RemoteSource *source, char **line, size_t *size) { assert(source->filled <= source->size); assert(source->buf == NULL || source->size > 0); - c = memchr(source->buf, '\n', source->filled); + if (source->buf) + c = memchr(source->buf, '\n', source->filled); + if (c != NULL) goto docopy; diff --git a/src/journal/journald-kmsg.c b/src/journal/journald-kmsg.c index 35948ea..48725e4 100644 --- a/src/journal/journald-kmsg.c +++ b/src/journal/journald-kmsg.c @@ -152,7 +152,7 @@ static void dev_kmsg_record(Server *s, char *p, size_t l) { /* Did we lose any? */ if (serial > *s->kernel_seqnum) server_driver_message(s, SD_MESSAGE_JOURNAL_MISSED, "Missed %"PRIu64" kernel messages", - serial - *s->kernel_seqnum - 1); + serial - *s->kernel_seqnum); /* Make sure we never read this one again. Note that * we always store the next message serial we expect diff --git a/src/journal/journald-server.c b/src/journal/journald-server.c index 6da81e7..b6f8e7e 100644 --- a/src/journal/journald-server.c +++ b/src/journal/journald-server.c @@ -67,6 +67,7 @@ #define DEFAULT_SYNC_INTERVAL_USEC (5*USEC_PER_MINUTE) #define DEFAULT_RATE_LIMIT_INTERVAL (30*USEC_PER_SEC) #define DEFAULT_RATE_LIMIT_BURST 1000 +#define DEFAULT_MAX_FILE_USEC USEC_PER_MONTH #define RECHECK_AVAILABLE_SPACE_USEC (30*USEC_PER_SEC) @@ -1473,6 +1474,8 @@ int server_init(Server *s) { s->forward_to_syslog = true; s->forward_to_wall = true; + s->max_file_usec = DEFAULT_MAX_FILE_USEC; + s->max_level_store = LOG_DEBUG; s->max_level_syslog = LOG_DEBUG; s->max_level_kmsg = LOG_NOTICE; diff --git a/src/journal/microhttpd-util.c b/src/journal/microhttpd-util.c index f693e0f..9a8d5c6 100644 --- a/src/journal/microhttpd-util.c +++ b/src/journal/microhttpd-util.c @@ -129,7 +129,7 @@ void log_func_gnutls(int level, const char *message) { if (0 <= level && level < (int) ELEMENTSOF(log_level_map)) ourlevel = log_level_map[level]; else - level = LOG_DEBUG; + ourlevel = LOG_DEBUG; log_meta(ourlevel, NULL, 0, NULL, "gnutls: %s", message); } diff --git a/src/journal/test-catalog.c b/src/journal/test-catalog.c index b087a8b..967ab67 100644 --- a/src/journal/test-catalog.c +++ b/src/journal/test-catalog.c @@ -157,7 +157,8 @@ int main(int argc, char *argv[]) { setlocale(LC_ALL, "de_DE.UTF-8"); - log_set_max_level(LOG_DEBUG); + log_parse_environment(); + log_open(); test_catalog_file_lang(); diff --git a/src/libudev/libudev-monitor.c b/src/libudev/libudev-monitor.c index ba1b04d..85b1e40 100644 --- a/src/libudev/libudev-monitor.c +++ b/src/libudev/libudev-monitor.c @@ -108,15 +108,13 @@ static struct udev_monitor *udev_monitor_new(struct udev *udev) /* we consider udev running when /dev is on devtmpfs */ static bool udev_has_devtmpfs(struct udev *udev) { - struct file_handle *h; + union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ, }; int mount_id; _cleanup_fclose_ FILE *f = NULL; char line[LINE_MAX], *e; int r; - h = alloca(MAX_HANDLE_SZ); - h->handle_bytes = MAX_HANDLE_SZ; - r = name_to_handle_at(AT_FDCWD, "/dev", h, &mount_id, 0); + r = name_to_handle_at(AT_FDCWD, "/dev", &h.handle, &mount_id, 0); if (r < 0) return false; diff --git a/src/login/70-uaccess.rules b/src/login/70-uaccess.rules index e1cf897..57f619d 100644 --- a/src/login/70-uaccess.rules +++ b/src/login/70-uaccess.rules @@ -12,7 +12,7 @@ ENV{MAJOR}=="", GOTO="uaccess_end" SUBSYSTEM=="usb", ENV{ID_USB_INTERFACES}=="*:060101:*", TAG+="uaccess" # Digicams with proprietary protocol -ENV{ID_GPHOTO2}=="*?", TAG+="uaccess" +ENV{ID_GPHOTO2}=="?*", TAG+="uaccess" # SCSI and USB scanners ENV{libsane_matched}=="yes", TAG+="uaccess" @@ -49,13 +49,13 @@ SUBSYSTEM=="drm", KERNEL=="card*|renderD*", TAG+="uaccess" SUBSYSTEM=="misc", KERNEL=="kvm", TAG+="uaccess" # smart-card readers -ENV{ID_SMARTCARD_READER}=="*?", TAG+="uaccess" +ENV{ID_SMARTCARD_READER}=="?*", TAG+="uaccess" # (USB) authentication devices -ENV{ID_SECURITY_TOKEN}=="*?", TAG+="uaccess" +ENV{ID_SECURITY_TOKEN}=="?*", TAG+="uaccess" # PDA devices -ENV{ID_PDA}=="*?", TAG+="uaccess" +ENV{ID_PDA}=="?*", TAG+="uaccess" # Programmable remote control ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" @@ -64,10 +64,10 @@ ENV{ID_REMOTE_CONTROL}=="1", TAG+="uaccess" SUBSYSTEM=="input", ENV{ID_INPUT_JOYSTICK}=="?*", TAG+="uaccess" # color measurement devices -ENV{COLOR_MEASUREMENT_DEVICE}=="*?", TAG+="uaccess" +ENV{COLOR_MEASUREMENT_DEVICE}=="?*", TAG+="uaccess" # DDC/CI device, usually high-end monitors such as the DreamColor -ENV{DDC_DEVICE}=="*?", TAG+="uaccess" +ENV{DDC_DEVICE}=="?*", TAG+="uaccess" # media player raw devices (for user-mode drivers, Android SDK, etc.) SUBSYSTEM=="usb", ENV{ID_MEDIA_PLAYER}=="?*", TAG+="uaccess" diff --git a/src/login/logind-acl.c b/src/login/logind-acl.c index dc86f0f..4bbeb64 100644 --- a/src/login/logind-acl.c +++ b/src/login/logind-acl.c @@ -279,7 +279,9 @@ int devnode_acl_all(struct udev *udev, log_debug("Fixing up ACLs at %s for seat %s", n, seat); k = devnode_acl(n, flush, del, old_uid, add, new_uid); - if (k < 0) + if (k == -ENOENT) + log_debug("Device %s disappeared while setting ACLs", n); + else if (k < 0) r = k; } diff --git a/src/login/logind-action.c b/src/login/logind-action.c index 1928f43..d69c7ad 100644 --- a/src/login/logind-action.c +++ b/src/login/logind-action.c @@ -79,14 +79,12 @@ int manager_handle_action( return 0; } - /* If we have more than one or no displays connected, - * don't react to lid closing. The no display case we - * treat like this under the assumption that there is - * no modern drm driver available. */ + /* If we have more than one display connected, + * don't react to lid closing. */ n = manager_count_displays(m); if (n < 0) log_warning("Display counting failed: %s", strerror(-n)); - else if (n != 1) { + else if (n > 1) { log_debug("Ignoring lid switch request, %i displays connected.", n); return 0; } diff --git a/src/login/logind-seat.c b/src/login/logind-seat.c index 3f5efdc..1ee6ced 100644 --- a/src/login/logind-seat.c +++ b/src/login/logind-seat.c @@ -275,8 +275,13 @@ int seat_switch_to(Seat *s, unsigned int num) { if (!num) return -EINVAL; - if (num >= s->position_count || !s->positions[num]) + if (num >= s->position_count || !s->positions[num]) { + /* allow switching to unused VTs to trigger auto-activate */ + if (seat_has_vts(s) && num < 64) + return chvt(num); + return -EINVAL; + } return session_activate(s->positions[num]); } diff --git a/src/login/logind-session.c b/src/login/logind-session.c index 4ca6b5d..02a780d 100644 --- a/src/login/logind-session.c +++ b/src/login/logind-session.c @@ -213,7 +213,6 @@ int session_save(Session *s) { if (s->scope) fprintf(f, "SCOPE=%s\n", s->scope); - if (s->scope_job) fprintf(f, "SCOPE_JOB=%s\n", s->scope_job); @@ -229,17 +228,54 @@ int session_save(Session *s) { if (s->display) fprintf(f, "DISPLAY=%s\n", s->display); - if (s->remote_host) - fprintf(f, "REMOTE_HOST=%s\n", s->remote_host); + if (s->remote_host) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->remote_host); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + + fprintf(f, "REMOTE_HOST=%s\n", escaped); + } + + if (s->remote_user) { + _cleanup_free_ char *escaped; + + escaped = cescape(s->remote_user); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + + fprintf(f, "REMOTE_USER=%s\n", escaped); + } + + if (s->service) { + _cleanup_free_ char *escaped; - if (s->remote_user) - fprintf(f, "REMOTE_USER=%s\n", s->remote_user); + escaped = cescape(s->service); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + + fprintf(f, "SERVICE=%s\n", escaped); + } - if (s->service) - fprintf(f, "SERVICE=%s\n", s->service); + if (s->desktop) { + _cleanup_free_ char *escaped; - if (s->desktop) - fprintf(f, "DESKTOP=%s\n", s->desktop); + + escaped = cescape(s->desktop); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + + fprintf(f, "DESKTOP=%s\n", escaped); + } if (s->seat && seat_has_vts(s->seat)) fprintf(f, "VTNR=%u\n", s->vtnr); @@ -972,6 +1008,10 @@ void session_mute_vt(Session *s) { if (vt < 0) return; + r = fchown(vt, s->user->uid, -1); + if (r < 0) + goto error; + r = ioctl(vt, KDSKBMODE, K_OFF); if (r < 0) goto error; @@ -1026,6 +1066,8 @@ void session_restore_vt(Session *s) { mode.mode = VT_AUTO; ioctl(vt, VT_SETMODE, &mode); + fchown(vt, 0, -1); + s->vtfd = safe_close(s->vtfd); } diff --git a/src/login/org.freedesktop.login1.policy.in b/src/login/org.freedesktop.login1.policy.in index b96d32d..b8e90f1 100644 --- a/src/login/org.freedesktop.login1.policy.in +++ b/src/login/org.freedesktop.login1.policy.in @@ -254,7 +254,7 @@ auth_admin_keep auth_admin_keep - auth_admin_keep + yes org.freedesktop.login1.hibernate diff --git a/src/login/pam-module.c b/src/login/pam-module.c index 9873dd5..1259457 100644 --- a/src/login/pam-module.c +++ b/src/login/pam-module.c @@ -475,7 +475,7 @@ _public_ PAM_EXTERN int pam_sm_open_session( } if (session_fd >= 0) { - session_fd = dup(session_fd); + session_fd = fcntl(session_fd, F_DUPFD_CLOEXEC, 3); if (session_fd < 0) { pam_syslog(handle, LOG_ERR, "Failed to dup session fd: %m"); return PAM_SESSION_ERR; diff --git a/src/machine/machine.c b/src/machine/machine.c index 9a5cc9a..de701ad 100644 --- a/src/machine/machine.c +++ b/src/machine/machine.c @@ -123,17 +123,42 @@ int machine_save(Machine *m) { "NAME=%s\n", m->name); - if (m->unit) - fprintf(f, "SCOPE=%s\n", m->unit); /* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */ + if (m->unit) { + _cleanup_free_ char *escaped; + + escaped = cescape(m->unit); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + + fprintf(f, "SCOPE=%s\n", escaped); /* We continue to call this "SCOPE=" because it is internal only, and we want to stay compatible with old files */ + } if (m->scope_job) fprintf(f, "SCOPE_JOB=%s\n", m->scope_job); - if (m->service) - fprintf(f, "SERVICE=%s\n", m->service); + if (m->service) { + _cleanup_free_ char *escaped; - if (m->root_directory) - fprintf(f, "ROOT=%s\n", m->root_directory); + escaped = cescape(m->service); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + fprintf(f, "SERVICE=%s\n", escaped); + } + + if (m->root_directory) { + _cleanup_free_ char *escaped; + + escaped = cescape(m->root_directory); + if (!escaped) { + r = -ENOMEM; + goto finish; + } + fprintf(f, "ROOT=%s\n", escaped); + } if (!sd_id128_equal(m->id, SD_ID128_NULL)) fprintf(f, "ID=" SD_ID128_FORMAT_STR "\n", SD_ID128_FORMAT_VAL(m->id)); @@ -330,16 +355,18 @@ static int machine_stop_scope(Machine *m) { if (!m->unit) return 0; - r = manager_stop_unit(m->manager, m->unit, &error, &job); - if (r < 0) { - log_error("Failed to stop machine scope: %s", bus_error_message(&error, r)); - return r; + if (!m->registered) { + r = manager_stop_unit(m->manager, m->unit, &error, &job); + if (r < 0) { + log_error("Failed to stop machine scope: %s", bus_error_message(&error, r)); + return r; + } } free(m->scope_job); m->scope_job = job; - return r; + return 0; } int machine_stop(Machine *m) { @@ -415,6 +442,8 @@ int machine_kill(Machine *m, KillWho who, int signo) { if (kill(m->leader, signo) < 0) return -errno; + + return 0; } /* Otherwise make PID 1 do it for us, for the entire cgroup */ diff --git a/src/machine/machine.h b/src/machine/machine.h index f4aefc5..de3536d 100644 --- a/src/machine/machine.h +++ b/src/machine/machine.h @@ -72,6 +72,7 @@ struct Machine { bool in_gc_queue:1; bool started:1; + bool registered:1; sd_bus_message *create_message; diff --git a/src/machine/machined-dbus.c b/src/machine/machined-dbus.c index 9473105..154a335 100644 --- a/src/machine/machined-dbus.c +++ b/src/machine/machined-dbus.c @@ -241,6 +241,7 @@ static int method_create_or_register_machine(Manager *manager, sd_bus_message *m m->leader = leader; m->class = c; m->id = id; + m->registered = true; if (!isempty(service)) { m->service = strdup(service); diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 9a9ed9d..4efa5b7 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -769,6 +769,15 @@ static int setup_resolv_conf(const char *dest) { return 0; } +static char* id128_format_as_uuid(sd_id128_t id, char s[37]) { + + snprintf(s, 37, + "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", + SD_ID128_FORMAT_VAL(id)); + + return s; +} + static int setup_boot_id(const char *dest) { _cleanup_free_ char *from = NULL, *to = NULL; sd_id128_t rnd = {}; @@ -794,10 +803,7 @@ static int setup_boot_id(const char *dest) { return r; } - snprintf(as_uuid, sizeof(as_uuid), - "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", - SD_ID128_FORMAT_VAL(rnd)); - char_array_0(as_uuid); + id128_format_as_uuid(rnd, as_uuid); r = write_string_file(from, as_uuid); if (r < 0) { @@ -2378,7 +2384,7 @@ static int change_uid_gid(char **_home) { _cleanup_fclose_ FILE *f = NULL; _cleanup_close_ int fd = -1; unsigned n_uids = 0; - size_t sz, l; + size_t sz = 0, l; uid_t uid; gid_t gid; pid_t pid; @@ -2667,6 +2673,7 @@ int main(int argc, char *argv[]) { goto finish; } } else { +#if 0 const char *p; p = strappenda(arg_directory, @@ -2676,6 +2683,7 @@ int main(int argc, char *argv[]) { goto finish; } +#endif } } else { char template[] = "/tmp/nspawn-root-XXXXXX"; @@ -2966,7 +2974,9 @@ int main(int argc, char *argv[]) { } if (!sd_id128_equal(arg_uuid, SD_ID128_NULL)) { - if (asprintf((char**)(envp + n_env++), "container_uuid=" SD_ID128_FORMAT_STR, SD_ID128_FORMAT_VAL(arg_uuid)) < 0) { + char as_uuid[37]; + + if (asprintf((char**)(envp + n_env++), "container_uuid=%s", id128_format_as_uuid(arg_uuid, as_uuid)) < 0) { log_oom(); goto child_fail; } @@ -3136,6 +3146,10 @@ int main(int argc, char *argv[]) { if (!arg_quiet) log_info("Container %s is being rebooted.", arg_machine); + if (getenv("EXIT_ON_REBOOT") != 0) { + r = 10; + break; + } continue; } else if (status.si_code == CLD_KILLED || status.si_code == CLD_DUMPED) { diff --git a/src/nss-myhostname/netlink.c b/src/nss-myhostname/netlink.c index d61ecdf..228a3a4 100644 --- a/src/nss-myhostname/netlink.c +++ b/src/nss-myhostname/netlink.c @@ -112,6 +112,10 @@ static int read_reply(int fd, struct address **list, unsigned *n_list) { ifaddrmsg->ifa_scope == RT_SCOPE_NOWHERE) continue; + if (ifaddrmsg->ifa_family == AF_INET6 && + ifaddrmsg->ifa_scope == RT_SCOPE_LINK) + continue; + if (ifaddrmsg->ifa_flags & IFA_F_DEPRECATED) continue; diff --git a/src/python-systemd/_reader.c b/src/python-systemd/_reader.c index 059b904..9a19a10 100644 --- a/src/python-systemd/_reader.c +++ b/src/python-systemd/_reader.c @@ -902,7 +902,6 @@ static PyObject* get_catalog(PyObject *self, PyObject *args) { sd_id128_t id; _cleanup_free_ char *msg = NULL; - assert(!self); assert(args); if (!PyArg_ParseTuple(args, "z:get_catalog", &id_)) diff --git a/src/python-systemd/journal.py b/src/python-systemd/journal.py index 9c7e004..dd1f229 100644 --- a/src/python-systemd/journal.py +++ b/src/python-systemd/journal.py @@ -293,7 +293,7 @@ class Reader(_Reader): monotonic = monotonic.totalseconds() monotonic = int(monotonic * 1000000) if isinstance(bootid, _uuid.UUID): - bootid = bootid.get_hex() + bootid = bootid.hex return super(Reader, self).seek_monotonic(monotonic, bootid) def log_level(self, level): @@ -314,7 +314,7 @@ class Reader(_Reader): Equivalent to add_match(MESSAGE_ID=`messageid`). """ if isinstance(messageid, _uuid.UUID): - messageid = messageid.get_hex() + messageid = messageid.hex self.add_match(MESSAGE_ID=messageid) def this_boot(self, bootid=None): @@ -346,7 +346,7 @@ class Reader(_Reader): def get_catalog(mid): if isinstance(mid, _uuid.UUID): - mid = mid.get_hex() + mid = mid.hex return _get_catalog(mid) def _make_line(field, value): diff --git a/src/readahead/readahead-common.c b/src/readahead/readahead-common.c index 5ffa88b..49679fc 100644 --- a/src/readahead/readahead-common.c +++ b/src/readahead/readahead-common.c @@ -75,7 +75,7 @@ int fs_on_ssd(const char *p) { if (major(st.st_dev) == 0) { _cleanup_fclose_ FILE *f = NULL; int mount_id; - struct file_handle *h; + union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ, }; /* Might be btrfs, which exposes "ssd" as mount flag if it is on ssd. * @@ -83,9 +83,7 @@ int fs_on_ssd(const char *p) { * and then lookup the mount ID in mountinfo to find * the mount options. */ - h = alloca(MAX_HANDLE_SZ); - h->handle_bytes = MAX_HANDLE_SZ; - r = name_to_handle_at(AT_FDCWD, p, h, &mount_id, AT_SYMLINK_FOLLOW); + r = name_to_handle_at(AT_FDCWD, p, &h.handle, &mount_id, AT_SYMLINK_FOLLOW); if (r < 0) return false; diff --git a/src/shared/conf-parser.c b/src/shared/conf-parser.c index d27b1b7..905a2e1 100644 --- a/src/shared/conf-parser.c +++ b/src/shared/conf-parser.c @@ -336,8 +336,8 @@ int config_parse(const char *unit, if (!f) { f = ours = fopen(filename, "re"); if (!f) { - log_error("Failed to open configuration file '%s': %m", filename); - return -errno; + log_full(errno == ENOENT ? LOG_DEBUG : LOG_ERR, "Failed to open configuration file '%s': %m", filename); + return errno == ENOENT ? 0 : -errno; } } diff --git a/src/shared/generator.c b/src/shared/generator.c index 6110303..e679cb1 100644 --- a/src/shared/generator.c +++ b/src/shared/generator.c @@ -48,7 +48,7 @@ int generator_write_fsck_deps( const char *checker; int r; - checker = strappenda("/sbin/fsck.", fstype); + checker = strappenda("/run/current-system/sw/sbin/fsck.", fstype); r = access(checker, X_OK); if (r < 0) { log_warning("Checking was requested for %s, but %s cannot be used: %m", what, checker); diff --git a/src/shared/install.c b/src/shared/install.c index 7409046..4517c9c 100644 --- a/src/shared/install.c +++ b/src/shared/install.c @@ -560,7 +560,7 @@ int unit_file_mask( unsigned *n_changes) { char **i; - _cleanup_free_ char *prefix; + _cleanup_free_ char *prefix = NULL; int r; assert(scope >= 0); diff --git a/src/shared/log.c b/src/shared/log.c index a4b3b68..890a9fa 100644 --- a/src/shared/log.c +++ b/src/shared/log.c @@ -878,6 +878,9 @@ void log_parse_environment(void) { if (l == 5 && startswith(w, "debug")) { log_set_max_level(LOG_DEBUG); break; + } else if (l == 5 && startswith(w, "quiet")) { + log_set_max_level(LOG_WARNING); + break; } } } diff --git a/src/shared/logs-show.c b/src/shared/logs-show.c index 9d14933..b0b66f6 100644 --- a/src/shared/logs-show.c +++ b/src/shared/logs-show.c @@ -547,7 +547,9 @@ static int output_export( startswith(data, "_BOOT_ID=")) continue; - if (!utf8_is_printable(data, length)) { + if (utf8_is_printable_newline(data, length, false)) + fwrite(data, length, 1, f); + else { const char *c; uint64_t le64; @@ -562,8 +564,7 @@ static int output_export( le64 = htole64(length - (c - (const char*) data) - 1); fwrite(&le64, sizeof(le64), 1, f); fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f); - } else - fwrite(data, length, 1, f); + } fputc('\n', f); } diff --git a/src/shared/unit-name.c b/src/shared/unit-name.c index 6c167b4..d0e71f2 100644 --- a/src/shared/unit-name.c +++ b/src/shared/unit-name.c @@ -332,7 +332,7 @@ char *unit_name_path_unescape(const char *f) { } bool unit_name_is_template(const char *n) { - const char *p; + const char *p, *e; assert(n); @@ -340,11 +340,15 @@ bool unit_name_is_template(const char *n) { if (!p) return false; - return p[1] == '.'; + e = strrchr(p+1, '.'); + if (!e) + return false; + + return e == p + 1; } bool unit_name_is_instance(const char *n) { - const char *p; + const char *p, *e; assert(n); @@ -352,7 +356,11 @@ bool unit_name_is_instance(const char *n) { if (!p) return false; - return p[1] != '.'; + e = strrchr(p+1, '.'); + if (!e) + return false; + + return e > p + 1; } char *unit_name_replace_instance(const char *f, const char *i) { diff --git a/src/shared/utf8.c b/src/shared/utf8.c index 0b524d8..c559c13 100644 --- a/src/shared/utf8.c +++ b/src/shared/utf8.c @@ -136,7 +136,7 @@ int utf8_encoded_to_unichar(const char *str) { return unichar; } -bool utf8_is_printable(const char* str, size_t length) { +bool utf8_is_printable_newline(const char* str, size_t length, bool newline) { const uint8_t *p; assert(str); @@ -145,7 +145,8 @@ bool utf8_is_printable(const char* str, size_t length) { int encoded_len = utf8_encoded_valid_unichar((const char *)p); int val = utf8_encoded_to_unichar((const char*)p); - if (encoded_len < 0 || val < 0 || is_unicode_control(val)) + if (encoded_len < 0 || val < 0 || is_unicode_control(val) || + (!newline && val == '\n')) return false; length -= encoded_len; diff --git a/src/shared/utf8.h b/src/shared/utf8.h index c0eb73a..c087995 100644 --- a/src/shared/utf8.h +++ b/src/shared/utf8.h @@ -31,7 +31,10 @@ const char *utf8_is_valid(const char *s) _pure_; char *ascii_is_valid(const char *s) _pure_; char *utf8_escape_invalid(const char *s); -bool utf8_is_printable(const char* str, size_t length) _pure_; +bool utf8_is_printable_newline(const char* str, size_t length, bool newline) _pure_; +_pure_ static inline bool utf8_is_printable(const char* str, size_t length) { + return utf8_is_printable_newline(str, length, true); +} char *utf16_to_utf8(const void *s, size_t length); diff --git a/src/shared/util.c b/src/shared/util.c index ffe6624..2a2b2b2 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -166,19 +166,19 @@ int close_nointr(int fd) { assert(fd >= 0); r = close(fd); - - /* Just ignore EINTR; a retry loop is the wrong - * thing to do on Linux. - * - * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html - * https://bugzilla.gnome.org/show_bug.cgi?id=682819 - * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR - * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain - */ - if (_unlikely_(r < 0 && errno == EINTR)) - return 0; - else if (r >= 0) + if (r >= 0) return r; + else if (errno == EINTR) + /* + * Just ignore EINTR; a retry loop is the wrong + * thing to do on Linux. + * + * http://lkml.indiana.edu/hypermail/linux/kernel/0509.1/0877.html + * https://bugzilla.gnome.org/show_bug.cgi?id=682819 + * http://utcc.utoronto.ca/~cks/space/blog/unix/CloseEINTR + * https://sites.google.com/site/michaelsafyan/software-engineering/checkforeintrwheninvokingclosethinkagain + */ + return 0; else return -errno; } @@ -195,7 +195,13 @@ int safe_close(int fd) { if (fd >= 0) { PROTECT_ERRNO; - assert_se(close_nointr(fd) == 0); + + /* The kernel might return pretty much any error code + * via close(), but the fd will be closed anyway. The + * only condition we want to check for here is whether + * the fd was invalid at all... */ + + assert_se(close_nointr(fd) != -EBADF); } return -1; @@ -1365,7 +1371,7 @@ bool ignore_file(const char *filename) { assert(filename); if (endswith(filename, "~")) - return false; + return true; return ignore_file_allow_backup(filename); } @@ -1495,6 +1501,7 @@ bool fstype_is_network(const char *fstype) { static const char table[] = "cifs\0" "smbfs\0" + "sshfs\0" "ncpfs\0" "ncp\0" "nfs\0" @@ -1581,8 +1588,9 @@ int read_one_char(FILE *f, char *ret, usec_t t, bool *need_nl) { if (fd_wait_for_event(fileno(f), POLLIN, t) <= 0) return -ETIMEDOUT; + errno = 0; if (!fgets(line, sizeof(line), f)) - return -EIO; + return errno ? -errno : -EIO; truncate_nl(line); @@ -5327,6 +5335,9 @@ bool string_is_safe(const char *p) { if (*t > 0 && *t < ' ') return false; + if (*t == 127) + return false; + if (strchr("\\\"\'", *t)) return false; } @@ -5343,10 +5354,14 @@ bool string_has_cc(const char *p) { assert(p); - for (t = p; *t; t++) + for (t = p; *t; t++) { if (*t > 0 && *t < ' ' && *t != '\t') return true; + if (*t == 127) + return true; + } + return false; } @@ -6391,3 +6406,19 @@ void hexdump(FILE *f, const void *p, size_t s) { s -= 16; } } + +int update_reboot_param_file(const char *param) +{ + int r = 0; + + if (param) { + + r = write_string_file(REBOOT_PARAM_FILE, param); + if (r < 0) + log_error("Failed to write reboot param to " + REBOOT_PARAM_FILE": %s", strerror(-r)); + } else + unlink(REBOOT_PARAM_FILE); + + return r; +} diff --git a/src/shared/util.h b/src/shared/util.h index 90464c9..122ac91 100644 --- a/src/shared/util.h +++ b/src/shared/util.h @@ -22,6 +22,7 @@ ***/ #include +#include #include #include #include @@ -922,3 +923,10 @@ uint64_t physical_memory(void); char* mount_test_option(const char *haystack, const char *needle); void hexdump(FILE *f, const void *p, size_t s); + +union file_handle_union { + struct file_handle handle; + char padding[sizeof(struct file_handle) + MAX_HANDLE_SZ]; +}; + +int update_reboot_param_file(const char *param); diff --git a/src/shared/virt.c b/src/shared/virt.c index ec2ddcf..f03e790 100644 --- a/src/shared/virt.c +++ b/src/shared/virt.c @@ -149,7 +149,7 @@ static int detect_vm_dmi(const char **_id) { /* Returns a short identifier for the various VM implementations */ int detect_vm(const char **id) { - _cleanup_free_ char *hvtype = NULL, *cpuinfo_contents = NULL; + _cleanup_free_ char *domcap = NULL, *cpuinfo_contents = NULL; static thread_local int cached_found = -1; static thread_local const char *cached_id = NULL; const char *_id = NULL; @@ -163,17 +163,37 @@ int detect_vm(const char **id) { return cached_found; } - /* Try high-level hypervisor sysfs file first: + /* Try xen capabilities file first, if not found try high-level hypervisor sysfs file: * - * https://bugs.freedesktop.org/show_bug.cgi?id=61491 */ - r = read_one_line_file("/sys/hypervisor/type", &hvtype); + * https://bugs.freedesktop.org/show_bug.cgi?id=77271 */ + r = read_one_line_file("/proc/xen/capabilities", &domcap); if (r >= 0) { - if (streq(hvtype, "xen")) { + char *cap, *i = domcap; + + while ((cap = strsep(&i, ","))) + if (streq(cap, "control_d")) + break; + + if (!i) { _id = "xen"; r = 1; - goto finish; } - } else if (r != -ENOENT) + + goto finish; + + } else if (r == -ENOENT) { + _cleanup_free_ char *hvtype = NULL; + + r = read_one_line_file("/sys/hypervisor/type", &hvtype); + if (r >= 0) { + if (streq(hvtype, "xen")) { + _id = "xen"; + r = 1; + goto finish; + } + } else if (r != -ENOENT) + return r; + } else return r; /* this will set _id to "other" and return 0 for unknown hypervisors */ diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index 0887bc3..d02ee2b 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -461,7 +461,7 @@ static int output_units_list(const UnitInfo *unit_infos, unsigned c) { } if (circle_len > 0) - printf("%s%s%s", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle); + printf("%s%s%s ", on_circle, circle ? draw_special_char(DRAW_BLACK_CIRCLE) : " ", off_circle); printf("%s%-*s%s %s%-*s%s %s%-*s %-*s%s %-*s", on_active, id_len, id, off_active, @@ -2561,7 +2561,7 @@ static int start_unit_one( log_debug("Adding %s to the set", p); r = set_consume(s, p); - if (r < 0) + if (r < 0 && r != -EEXIST) return log_oom(); } @@ -4240,7 +4240,7 @@ static int show_all( _cleanup_free_ UnitInfo *unit_infos = NULL; const UnitInfo *u; unsigned c; - int r; + int r, ret = 0; r = get_unit_list(bus, NULL, NULL, &unit_infos, 0, &reply); if (r < 0) @@ -4262,9 +4262,11 @@ static int show_all( r = show_one(verb, bus, p, show_properties, new_line, ellipsized); if (r < 0) return r; + else if (r > 0 && ret == 0) + ret = r; } - return 0; + return ret; } static int show_system_status(sd_bus *bus) { @@ -4386,7 +4388,12 @@ static int show(sd_bus *bus, char **args) { } } - show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized); + r = show_one(args[0], bus, unit, show_properties, + &new_line, &ellipsized); + if (r < 0) + return r; + else if (r > 0 && ret == 0) + ret = r; } if (!strv_isempty(patterns)) { @@ -4403,7 +4410,12 @@ static int show(sd_bus *bus, char **args) { if (!unit) return log_oom(); - show_one(args[0], bus, unit, show_properties, &new_line, &ellipsized); + r = show_one(args[0], bus, unit, show_properties, + &new_line, &ellipsized); + if (r < 0) + return r; + else if (r > 0 && ret == 0) + ret = r; } } } @@ -5403,15 +5415,15 @@ static int systemctl_help(void) { " otherwise restart if active\n" " isolate NAME Start one unit and stop all others\n" " kill NAME... Send signal to processes of a unit\n" - " is-active NAME... Check whether units are active\n" - " is-failed NAME... Check whether units are failed\n" - " status [NAME...|PID...] Show runtime status of one or more units\n" - " show [NAME...|JOB...] Show properties of one or more\n" + " is-active PATTERN... Check whether units are active\n" + " is-failed PATTERN... Check whether units are failed\n" + " status [PATTERN...|PID...] Show runtime status of one or more units\n" + " show [PATTERN...|JOB...] Show properties of one or more\n" " units/jobs or the manager\n" - " cat NAME... Show files and drop-ins of one or more units\n" + " cat PATTERN... Show files and drop-ins of one or more units\n" " set-property NAME ASSIGNMENT... Sets one or more properties of a unit\n" - " help NAME...|PID... Show manual for one or more units\n" - " reset-failed [NAME...] Reset failed state for all, one, or more\n" + " help PATTERN...|PID... Show manual for one or more units\n" + " reset-failed [PATTERN...] Reset failed state for all, one, or more\n" " units\n" " list-dependencies [NAME] Recursively show units which are required\n" " or wanted by this unit or by which this\n" @@ -5973,13 +5985,10 @@ static int halt_parse_argv(int argc, char *argv[]) { } } - if (arg_action == ACTION_REBOOT && argc == optind + 1) { - r = write_string_file(REBOOT_PARAM_FILE, argv[optind]); - if (r < 0) { - log_error("Failed to write reboot param to " - REBOOT_PARAM_FILE": %s", strerror(-r)); + if (arg_action == ACTION_REBOOT && (argc == optind || argc == optind + 1)) { + r = update_reboot_param_file(argc == optind + 1 ? argv[optind] : NULL); + if (r < 0) return r; - } } else if (optind < argc) { log_error("Too many arguments."); return -EINVAL; diff --git a/src/test/test-udev.c b/src/test/test-udev.c index b064744..b057cc8 100644 --- a/src/test/test-udev.c +++ b/src/test/test-udev.c @@ -155,9 +155,8 @@ int main(int argc, char *argv[]) { } } - err = udev_event_execute_rules(event, rules, &sigmask_orig); - if (err == 0) - udev_event_execute_run(event, NULL); + udev_event_execute_rules(event, rules, &sigmask_orig); + udev_event_execute_run(event, NULL); out: if (event != NULL && event->fd_signal >= 0) close(event->fd_signal); diff --git a/src/tmpfiles/tmpfiles.c b/src/tmpfiles/tmpfiles.c index 33e7cbc..04b472d 100644 --- a/src/tmpfiles/tmpfiles.c +++ b/src/tmpfiles/tmpfiles.c @@ -217,19 +217,16 @@ static bool unix_socket_alive(const char *fn) { } static int dir_is_mount_point(DIR *d, const char *subdir) { - struct file_handle *h; + union file_handle_union h = { .handle.handle_bytes = MAX_HANDLE_SZ }; int mount_id_parent, mount_id; int r_p, r; - h = alloca(MAX_HANDLE_SZ); - - h->handle_bytes = MAX_HANDLE_SZ; - r_p = name_to_handle_at(dirfd(d), ".", h, &mount_id_parent, 0); + r_p = name_to_handle_at(dirfd(d), ".", &h.handle, &mount_id_parent, 0); if (r_p < 0) r_p = -errno; - h->handle_bytes = MAX_HANDLE_SZ; - r = name_to_handle_at(dirfd(d), subdir, h, &mount_id, 0); + h.handle.handle_bytes = MAX_HANDLE_SZ; + r = name_to_handle_at(dirfd(d), subdir, &h.handle, &mount_id, 0); if (r < 0) r = -errno; diff --git a/src/tty-ask-password-agent/tty-ask-password-agent.c b/src/tty-ask-password-agent/tty-ask-password-agent.c index 1d067af..3203474 100644 --- a/src/tty-ask-password-agent/tty-ask-password-agent.c +++ b/src/tty-ask-password-agent/tty-ask-password-agent.c @@ -432,7 +432,7 @@ static int wall_tty_block(void) { r = get_ctty_devnr(0, &devnr); if (r < 0) - return -r; + return r; if (asprintf(&p, "/run/systemd/ask-password-block/%u:%u", major(devnr), minor(devnr)) < 0) return -ENOMEM; diff --git a/src/udev/accelerometer/accelerometer.c b/src/udev/accelerometer/accelerometer.c index 925d38d..32adf27 100644 --- a/src/udev/accelerometer/accelerometer.c +++ b/src/udev/accelerometer/accelerometer.c @@ -180,7 +180,7 @@ get_prev_orientation(struct udev_device *dev) return string_to_orientation(value); } -#define SET_AXIS(axis, code_) if (ev[i].code == code_) { if (got_##axis == 0) { axis = ev[i].value; got_##axis = true; } } +#define READ_AXIS(axis, var) { memzero(&abs_info, sizeof(abs_info)); r = ioctl(fd, EVIOCGABS(axis), &abs_info); if (r < 0) return; var = abs_info.value; } /* accelerometers */ static void test_orientation(struct udev *udev, @@ -189,10 +189,9 @@ static void test_orientation(struct udev *udev, { OrientationUp old, new; _cleanup_close_ int fd = -1; - struct input_event ev[64]; - bool got_syn = false; - bool got_x = false, got_y = false, got_z = false; + struct input_absinfo abs_info; int x = 0, y = 0, z = 0; + int r; char text[64]; old = get_prev_orientation(dev); @@ -201,30 +200,10 @@ static void test_orientation(struct udev *udev, if (fd < 0) return; - while (1) { - int i, r; - - r = read(fd, ev, sizeof(struct input_event) * 64); - - if (r < (int) sizeof(struct input_event)) - return; - - for (i = 0; i < r / (int) sizeof(struct input_event); i++) { - if (got_syn) { - if (ev[i].type == EV_ABS) { - SET_AXIS(x, ABS_X); - SET_AXIS(y, ABS_Y); - SET_AXIS(z, ABS_Z); - } - } - if (ev[i].type == EV_SYN && ev[i].code == SYN_REPORT) - got_syn = true; - if (got_x && got_y && got_z) - goto read_dev; - } - } + READ_AXIS(ABS_X, x); + READ_AXIS(ABS_Y, y); + READ_AXIS(ABS_Z, z); -read_dev: new = orientation_calc(old, x, y, z); snprintf(text, sizeof(text), "ID_INPUT_ACCELEROMETER_ORIENTATION=%s", orientation_to_string(new)); diff --git a/src/udev/net/link-config.c b/src/udev/net/link-config.c index 5bb6b02..b31ad80 100644 --- a/src/udev/net/link-config.c +++ b/src/udev/net/link-config.c @@ -184,7 +184,7 @@ failure: } static bool enable_name_policy(void) { - _cleanup_free_ char *line; + _cleanup_free_ char *line = NULL; char *w, *state; int r; size_t l; @@ -391,7 +391,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev case MACPOLICY_PERSISTENT: if (!mac_is_permanent(device)) { r = get_mac(device, false, &generated_mac); - if (r < 0) + if (r == -ENOENT) + break; + else if (r < 0) return r; mac = &generated_mac; } @@ -399,7 +401,9 @@ int link_config_apply(link_config_ctx *ctx, link_config *config, struct udev_dev case MACPOLICY_RANDOM: if (!mac_is_random(device)) { r = get_mac(device, true, &generated_mac); - if (r < 0) + if (r == -ENOENT) + break; + else if (r < 0) return r; mac = &generated_mac; } diff --git a/src/udev/udev-event.c b/src/udev/udev-event.c index 5998be2..5213a4a 100644 --- a/src/udev/udev-event.c +++ b/src/udev/udev-event.c @@ -771,18 +771,17 @@ static int rename_netif(struct udev_event *event) log_error("error changing net interface name %s to %s: %s", oldname, name, strerror(-r)); else - print_kmsg("renamed network interface %s to %s", oldname, name); + print_kmsg("renamed network interface %s to %s\n", oldname, name); return r; } -int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, const sigset_t *sigmask) +void udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, const sigset_t *sigmask) { struct udev_device *dev = event->dev; - int err = 0; if (udev_device_get_subsystem(dev) == NULL) - return -1; + return; if (streq(udev_device_get_action(dev), "remove")) { udev_device_read_db(dev, NULL); @@ -816,9 +815,10 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, event->name != NULL && !streq(event->name, udev_device_get_sysname(dev))) { char syspath[UTIL_PATH_SIZE]; char *pos; + int r; - err = rename_netif(event); - if (err == 0) { + r = rename_netif(event); + if (r >= 0) { log_debug("renamed netif to '%s'", event->name); /* remember old name */ @@ -881,7 +881,6 @@ int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, udev_device_unref(event->dev_db); event->dev_db = NULL; } - return err; } void udev_event_execute_run(struct udev_event *event, const sigset_t *sigmask) diff --git a/src/udev/udev-rules.c b/src/udev/udev-rules.c index 2630264..17f47f2 100644 --- a/src/udev/udev-rules.c +++ b/src/udev/udev-rules.c @@ -2555,10 +2555,15 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) struct stat stats; /* we assure, that the permissions tokens are sorted before the static token */ + if (mode == 0 && uid == 0 && gid == 0 && tags == NULL) goto next; strscpyl(device_node, sizeof(device_node), "/dev/", rules_str(rules, cur->key.value_off), NULL); + if (stat(device_node, &stats) != 0) + break; + if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) + break; /* export the tags to a directory as symlinks, allowing otherwise dead nodes to be tagged */ if (tags) { @@ -2588,11 +2593,6 @@ int udev_rules_apply_static_dev_perms(struct udev_rules *rules) if (mode == 0 && uid == 0 && gid == 0) break; - if (stat(device_node, &stats) != 0) - break; - if (!S_ISBLK(stats.st_mode) && !S_ISCHR(stats.st_mode)) - break; - if (mode == 0) { if (gid > 0) mode = 0660; diff --git a/src/udev/udev.h b/src/udev/udev.h index 936adfb..62538bc 100644 --- a/src/udev/udev.h +++ b/src/udev/udev.h @@ -84,7 +84,7 @@ int udev_event_apply_subsys_kernel(struct udev_event *event, const char *string, int udev_event_spawn(struct udev_event *event, const char *cmd, char **envp, const sigset_t *sigmask, char *result, size_t ressize); -int udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, const sigset_t *sigset); +void udev_event_execute_rules(struct udev_event *event, struct udev_rules *rules, const sigset_t *sigset); void udev_event_execute_run(struct udev_event *event, const sigset_t *sigset); int udev_build_argv(struct udev *udev, char *cmd, int *argc, char *argv[]); diff --git a/src/udev/udevadm-test.c b/src/udev/udevadm-test.c index 6cd311b..6a2f548 100644 --- a/src/udev/udevadm-test.c +++ b/src/udev/udevadm-test.c @@ -43,7 +43,6 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) _cleanup_udev_device_unref_ struct udev_device *dev = NULL; _cleanup_udev_event_unref_ struct udev_event *event = NULL; sigset_t mask, sigmask_orig; - int err; int rc = 0, c; static const struct option options[] = { @@ -139,18 +138,16 @@ static int adm_test(struct udev *udev, int argc, char *argv[]) goto out; } - err = udev_event_execute_rules(event, rules, &sigmask_orig); + udev_event_execute_rules(event, rules, &sigmask_orig); udev_list_entry_foreach(entry, udev_device_get_properties_list_entry(dev)) printf("%s=%s\n", udev_list_entry_get_name(entry), udev_list_entry_get_value(entry)); - if (err == 0) { - udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) { - char program[UTIL_PATH_SIZE]; + udev_list_entry_foreach(entry, udev_list_get_entry(&event->run_list)) { + char program[UTIL_PATH_SIZE]; - udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program)); - printf("run: '%s'\n", program); - } + udev_event_apply_format(event, udev_list_entry_get_name(entry), program, sizeof(program)); + printf("run: '%s'\n", program); } out: if (event != NULL && event->fd_signal >= 0) diff --git a/src/udev/udevd.c b/src/udev/udevd.c index f21c227..93afca1 100644 --- a/src/udev/udevd.c +++ b/src/udev/udevd.c @@ -288,10 +288,9 @@ static void worker_new(struct event *event) udev_event->exec_delay = exec_delay; /* apply rules, create node, symlinks */ - err = udev_event_execute_rules(udev_event, rules, &sigmask_orig); + udev_event_execute_rules(udev_event, rules, &sigmask_orig); - if (err == 0) - udev_event_execute_run(udev_event, &sigmask_orig); + udev_event_execute_run(udev_event, &sigmask_orig); /* apply/restore inotify watch */ if (err == 0 && udev_event->inotify_watch) { diff --git a/src/vconsole/vconsole-setup.c b/src/vconsole/vconsole-setup.c index 0f2b706..645b1e6 100644 --- a/src/vconsole/vconsole-setup.c +++ b/src/vconsole/vconsole-setup.c @@ -180,6 +180,10 @@ static int font_load(const char *vc, const char *font, const char *map, const ch */ static void font_copy_to_all_vcs(int fd) { struct vt_stat vcs = {}; + unsigned char map8[E_TABSZ]; + unsigned short map16[E_TABSZ]; + struct unimapdesc unimapd; + struct unipair unipairs[USHRT_MAX]; int i, r; /* get active, and 16 bit mask of used VT numbers */ @@ -209,17 +213,35 @@ static void font_copy_to_all_vcs(int fd) { cfo.op = KD_FONT_OP_COPY; cfo.height = vcs.v_active-1; /* tty1 == index 0 */ ioctl(vcfd, KDFONTOP, &cfo); + + /* copy map of 8bit chars */ + if (ioctl(fd, GIO_SCRNMAP, map8) >= 0) + ioctl(vcfd, PIO_SCRNMAP, map8); + + /* copy map of 8bit chars -> 16bit Unicode values */ + if (ioctl(fd, GIO_UNISCRNMAP, map16) >= 0) + ioctl(vcfd, PIO_UNISCRNMAP, map16); + + /* 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 }; + + ioctl(vcfd, PIO_UNIMAPCLR, &adv); + ioctl(vcfd, PIO_UNIMAP, &unimapd); + } } } int main(int argc, char **argv) { const char *vc; - char *vc_keymap = NULL; - char *vc_keymap_toggle = NULL; - char *vc_font = NULL; - char *vc_font_map = NULL; - char *vc_font_unimap = NULL; - int fd = -1; + _cleanup_free_ char + *vc_keymap = NULL, *vc_keymap_toggle = NULL, + *vc_font = NULL, *vc_font_map = NULL, *vc_font_unimap = NULL; + _cleanup_close_ int fd = -1; bool utf8; pid_t font_pid = 0, keymap_pid = 0; bool font_copy = false; @@ -241,12 +263,12 @@ int main(int argc, char **argv) { fd = open_terminal(vc, O_RDWR|O_CLOEXEC); if (fd < 0) { log_error("Failed to open %s: %m", vc); - goto finish; + return EXIT_FAILURE; } if (!is_vconsole(fd)) { log_error("Device %s is not a virtual console.", vc); - goto finish; + return EXIT_FAILURE; } utf8 = is_locale_utf8(); @@ -281,27 +303,27 @@ int main(int argc, char **argv) { else disable_utf8(fd); - r = EXIT_FAILURE; - if (keymap_load(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid) >= 0 && - font_load(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid) >= 0) - r = EXIT_SUCCESS; - -finish: - if (keymap_pid > 0) - wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid); + r = font_load(vc, vc_font, vc_font_map, vc_font_unimap, &font_pid); + if (r < 0) { + log_error("Failed to start " KBD_SETFONT ": %s", strerror(-r)); + return EXIT_FAILURE; + } - if (font_pid > 0) { + if (font_pid > 0) wait_for_terminate_and_warn(KBD_SETFONT, font_pid); - if (font_copy) - font_copy_to_all_vcs(fd); + + r = keymap_load(vc, vc_keymap, vc_keymap_toggle, utf8, &keymap_pid); + if (r < 0) { + log_error("Failed to start " KBD_LOADKEYS ": %s", strerror(-r)); + return EXIT_FAILURE; } - free(vc_keymap); - free(vc_font); - free(vc_font_map); - free(vc_font_unimap); + if (keymap_pid > 0) + wait_for_terminate_and_warn(KBD_LOADKEYS, keymap_pid); - safe_close(fd); + /* Only copy the font when we started setfont successfully */ + if (font_copy && font_pid > 0) + font_copy_to_all_vcs(fd); - return r; + return EXIT_SUCCESS; } diff --git a/tmpfiles.d/systemd.conf b/tmpfiles.d/systemd.conf index 7c6d6b9..c470045 100644 --- a/tmpfiles.d/systemd.conf +++ b/tmpfiles.d/systemd.conf @@ -23,6 +23,6 @@ d /run/systemd/machines 0755 root root - d /run/systemd/shutdown 0755 root root - m /var/log/journal 2755 root systemd-journal - - -m /var/log/journal/%m 2755 root systemd-journal - - +Z /var/log/journal/%m 2755 root systemd-journal - - m /run/log/journal 2755 root systemd-journal - - -m /run/log/journal/%m 2755 root systemd-journal - - +Z /run/log/journal/%m 2755 root systemd-journal - - diff --git a/units/console-getty.service.m4.in b/units/console-getty.service.m4.in index 8ac51a4..cae9fb5 100644 --- a/units/console-getty.service.m4.in +++ b/units/console-getty.service.m4.in @@ -15,7 +15,6 @@ After=rc-local.service Before=getty.target [Service] -ExecStart=-/sbin/agetty --noclear --keep-baud console 115200,38400,9600 $TERM Type=idle Restart=always RestartSec=0 diff --git a/units/container-getty@.service.m4.in b/units/container-getty@.service.m4.in index 4f7794b..bad2a9a 100644 --- a/units/container-getty@.service.m4.in +++ b/units/container-getty@.service.m4.in @@ -16,7 +16,6 @@ Before=getty.target IgnoreOnIsolate=yes [Service] -ExecStart=-/sbin/agetty --noclear --keep-baud pts/%I 115200,38400,9600 $TERM Type=idle Restart=always RestartSec=0 diff --git a/units/emergency.service.in b/units/emergency.service.in index 94c090f..0d20640 100644 --- a/units/emergency.service.in +++ b/units/emergency.service.in @@ -15,7 +15,6 @@ Before=shutdown.target [Service] Environment=HOME=/root WorkingDirectory=/root -ExecStartPre=-/bin/plymouth quit ExecStartPre=-/bin/echo -e 'Welcome to emergency mode! After logging in, type "journalctl -xb" to view\\nsystem logs, "systemctl reboot" to reboot, "systemctl default" to try again\\nto boot into default mode.' ExecStart=-/sbin/sulogin ExecStopPost=@SYSTEMCTL@ --fail --no-block default diff --git a/units/getty@.service.m4 b/units/getty@.service.m4 index aa853b8..8bcc647 100644 --- a/units/getty@.service.m4 +++ b/units/getty@.service.m4 @@ -23,11 +23,12 @@ IgnoreOnIsolate=yes # On systems without virtual consoles, don't start any getty. Note # that serial gettys are covered by serial-getty@.service, not this # unit. -ConditionPathExists=/dev/tty0 +ConditionPathExists=|/dev/tty0 +ConditionVirtualization=|lxc +ConditionVirtualization=|lxc-libvirt [Service] # the VT is cleared by TTYVTDisallocate -ExecStart=-/sbin/agetty --noclear %I $TERM Type=idle Restart=always RestartSec=0 diff --git a/units/kmod-static-nodes.service.in b/units/kmod-static-nodes.service.in index 368f980..d0c1bd2 100644 --- a/units/kmod-static-nodes.service.in +++ b/units/kmod-static-nodes.service.in @@ -10,7 +10,6 @@ Description=Create list of required static device nodes for the current kernel DefaultDependencies=no Before=sysinit.target systemd-tmpfiles-setup-dev.service ConditionCapability=CAP_MKNOD -ConditionPathExists=/lib/modules/%v/modules.devname [Service] Type=oneshot diff --git a/units/local-fs.target b/units/local-fs.target index ae3cedc..0e36840 100644 --- a/units/local-fs.target +++ b/units/local-fs.target @@ -13,3 +13,5 @@ DefaultDependencies=no Conflicts=shutdown.target OnFailure=emergency.target OnFailureJobMode=replace-irreversibly + +X-StopOnReconfiguration=yes diff --git a/units/remote-fs.target b/units/remote-fs.target index 43ffa5c..156a681 100644 --- a/units/remote-fs.target +++ b/units/remote-fs.target @@ -12,5 +12,7 @@ After=remote-fs-pre.target DefaultDependencies=no Conflicts=shutdown.target +X-StopOnReconfiguration=yes + [Install] WantedBy=multi-user.target diff --git a/units/rescue.service.m4.in b/units/rescue.service.m4.in index 552ef89..af3915f 100644 --- a/units/rescue.service.m4.in +++ b/units/rescue.service.m4.in @@ -16,7 +16,6 @@ Before=shutdown.target [Service] Environment=HOME=/root WorkingDirectory=/root -ExecStartPre=-/bin/plymouth quit ExecStartPre=-/bin/echo -e 'Welcome to rescue mode! Type "systemctl default" or ^D to enter default mode.\\nType "journalctl -xb" to view system logs. Type "systemctl reboot" to reboot.' ExecStart=-/sbin/sulogin ExecStopPost=-@SYSTEMCTL@ --fail --no-block default diff --git a/units/serial-getty@.service.m4 b/units/serial-getty@.service.m4 index 4ac51e7..96daa5c 100644 --- a/units/serial-getty@.service.m4 +++ b/units/serial-getty@.service.m4 @@ -22,10 +22,8 @@ Before=getty.target IgnoreOnIsolate=yes [Service] -ExecStart=-/sbin/agetty --keep-baud 115200,38400,9600 %I $TERM Type=idle Restart=always -RestartSec=0 UtmpIdentifier=%I TTYPath=/dev/%I TTYReset=yes diff --git a/units/sysinit.target b/units/sysinit.target index 8f4fb8f..e0f0147 100644 --- a/units/sysinit.target +++ b/units/sysinit.target @@ -9,6 +9,5 @@ Description=System Initialization Documentation=man:systemd.special(7) Conflicts=emergency.service emergency.target -Wants=local-fs.target swap.target -After=local-fs.target swap.target emergency.service emergency.target +After=emergency.service emergency.target RefuseManualStart=yes diff --git a/units/systemd-backlight@.service.in b/units/systemd-backlight@.service.in index e945d87..77728f2 100644 --- a/units/systemd-backlight@.service.in +++ b/units/systemd-backlight@.service.in @@ -19,3 +19,4 @@ Type=oneshot RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-backlight load %i ExecStop=@rootlibexecdir@/systemd-backlight save %i +X-RestartIfChanged=false diff --git a/units/systemd-journal-flush.service.in b/units/systemd-journal-flush.service.in index 503e8a6..fe23b8b 100644 --- a/units/systemd-journal-flush.service.in +++ b/units/systemd-journal-flush.service.in @@ -10,8 +10,9 @@ Description=Trigger Flushing of Journal to Persistent Storage Documentation=man:systemd-journald.service(8) man:journald.conf(5) DefaultDependencies=no Requires=systemd-journald.service -After=systemd-journald.service local-fs.target remote-fs.target +After=systemd-journald.service Before=systemd-user-sessions.service +RequiresMountsFor=/var/log/journal [Service] ExecStart=@rootbindir@/systemctl kill --kill-who=main --signal=SIGUSR1 systemd-journald.service diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in index de93879..c9a49f3 100644 --- a/units/systemd-journald.service.in +++ b/units/systemd-journald.service.in @@ -25,3 +25,8 @@ WatchdogSec=1min # Increase the default a bit in order to allow many simultaneous # services being run since we keep one fd open per service. LimitNOFILE=16384 + +# Don't restart journald, since that causes services connected to +# journald to stop logging (see +# https://bugs.freedesktop.org/show_bug.cgi?id=56043). +X-RestartIfChanged=no diff --git a/units/systemd-nspawn@.service.in b/units/systemd-nspawn@.service.in index ff36e90..e373628 100644 --- a/units/systemd-nspawn@.service.in +++ b/units/systemd-nspawn@.service.in @@ -11,6 +11,7 @@ Documentation=man:systemd-nspawn(1) [Service] ExecStart=@bindir@/systemd-nspawn --quiet --keep-unit --boot --link-journal=guest --directory=/var/lib/container/%i +KillMode=mixed Type=notify [Install] diff --git a/units/systemd-random-seed.service.in b/units/systemd-random-seed.service.in index 1879b2f..9b895b9 100644 --- a/units/systemd-random-seed.service.in +++ b/units/systemd-random-seed.service.in @@ -19,3 +19,4 @@ Type=oneshot RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-random-seed load ExecStop=@rootlibexecdir@/systemd-random-seed save +X-RestartIfChanged=false diff --git a/units/systemd-rfkill@.service.in b/units/systemd-rfkill@.service.in index 9d264a2..c505535 100644 --- a/units/systemd-rfkill@.service.in +++ b/units/systemd-rfkill@.service.in @@ -19,3 +19,4 @@ Type=oneshot RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-rfkill load %I ExecStop=@rootlibexecdir@/systemd-rfkill save %I +X-RestartIfChanged=false diff --git a/units/systemd-tmpfiles-setup.service.in b/units/systemd-tmpfiles-setup.service.in index 01043b7..507f820 100644 --- a/units/systemd-tmpfiles-setup.service.in +++ b/units/systemd-tmpfiles-setup.service.in @@ -12,7 +12,7 @@ DefaultDependencies=no Wants=local-fs.target Conflicts=shutdown.target After=systemd-readahead-collect.service systemd-readahead-replay.service local-fs.target -Before=sysinit.target shutdown.target +Before=shutdown.target ConditionDirectoryNotEmpty=|/usr/lib/tmpfiles.d ConditionDirectoryNotEmpty=|/lib/tmpfiles.d ConditionDirectoryNotEmpty=|/usr/local/lib/tmpfiles.d diff --git a/units/systemd-update-utmp.service.in b/units/systemd-update-utmp.service.in index da7dda7..e638145 100644 --- a/units/systemd-update-utmp.service.in +++ b/units/systemd-update-utmp.service.in @@ -11,7 +11,7 @@ Documentation=man:systemd-update-utmp.service(8) man:utmp(5) DefaultDependencies=no RequiresMountsFor=/var/log/wtmp Conflicts=shutdown.target -After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service systemd-tmpfiles-setup.service auditd.service +After=systemd-readahead-collect.service systemd-readahead-replay.service systemd-remount-fs.service auditd.service Before=sysinit.target shutdown.target [Service] @@ -19,3 +19,4 @@ Type=oneshot RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-update-utmp reboot ExecStop=@rootlibexecdir@/systemd-update-utmp shutdown +X-RestartIfChanged=false diff --git a/units/systemd-user-sessions.service.in b/units/systemd-user-sessions.service.in index 0869e73..b6ed958 100644 --- a/units/systemd-user-sessions.service.in +++ b/units/systemd-user-sessions.service.in @@ -15,3 +15,6 @@ Type=oneshot RemainAfterExit=yes ExecStart=@rootlibexecdir@/systemd-user-sessions start ExecStop=@rootlibexecdir@/systemd-user-sessions stop + +# Restart kills all active sessions. +X-RestartIfChanged=no