From ee9629a030bd9122bbb9b0f83fb869779d3ee2f6 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 8 Mar 2025 20:04:17 +0100 Subject: [PATCH 01/48] core/main: log about save_env() error (cherry picked from commit eda75b2cb27f171130191d1613c04c9d5e929efd) (cherry picked from commit 551aee593050ef9219466db05e8d7ba195d19f9b) (cherry picked from commit cc0ef08a48e0cf775c45d0f88c6be7b4fa30cb14) (cherry picked from commit bc59217b1b6940a4319a4ec3dc99ebe220509249) --- src/core/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/main.c b/src/core/main.c index f7d54e68b5..0eef8d7ecb 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2844,7 +2844,7 @@ static int save_env(void) { l = strv_copy(environ); if (!l) - return -ENOMEM; + return log_oom(); strv_free_and_replace(saved_env, l); return 0; From d6268568d564496dd27de07af02fb66fa8c1a6d3 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 5 Mar 2025 18:22:19 +0100 Subject: [PATCH 02/48] core/main: assign mac_init() retval to r If it fails, we'd submit the errno to supervisor via sd_notify() later. (cherry picked from commit 550f4718bc6b11d8801af3b7eb888aa4ba0fdc90) (cherry picked from commit e19548b78f2c7e2e921403d3ce8543143c313209) (cherry picked from commit ed7abadcf8ab834b8b1d111d20685c6edd085e00) (cherry picked from commit ce3f95983a0089150b635f0b200ee8eeae9dc822) --- src/core/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 0eef8d7ecb..0c6c2d1874 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2958,7 +2958,8 @@ int main(int argc, char *argv[]) { goto finish; } - if (mac_init() < 0) { + r = mac_init(); + if (r < 0) { error_message = "Failed to initialize MAC support"; goto finish; } @@ -3031,7 +3032,8 @@ int main(int argc, char *argv[]) { * operate. */ capability_ambient_set_apply(0, /* also_inherit= */ false); - if (mac_init() < 0) { + r = mac_init(); + if (r < 0) { error_message = "Failed to initialize MAC support"; goto finish; } From 3fc5d55b667344f0f9be2ccc9fc6647fd6387740 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 5 Mar 2025 18:35:50 +0100 Subject: [PATCH 03/48] core/main: correct retval for reexec/switch-root/soft-reboot For these objectives we ought to execve() at the end, i.e. if we ever hit the return path something went wrong in do_reexecute(). Let's properly report that via retval. (cherry picked from commit 590e0e3bacb012bc86ff46f8dbe3f1b415e9cafd) (cherry picked from commit efcd9c6e62dbc66e5bc70046e8ad1df2ad97947f) (cherry picked from commit 1282484941ca8e65de1586f15fcb09ad897f20e0) (cherry picked from commit c82f2e66feacf6eadb63aab45697fe5172ed7646) --- src/core/main.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 0c6c2d1874..536654ff44 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2073,7 +2073,7 @@ static int invoke_main_loop( log_notice("Reexecuting."); - *ret_retval = EXIT_SUCCESS; + *ret_retval = EXIT_FAILURE; *ret_switch_root_dir = *ret_switch_root_init = NULL; return objective; @@ -2096,7 +2096,7 @@ static int invoke_main_loop( log_notice("Switching root."); - *ret_retval = EXIT_SUCCESS; + *ret_retval = EXIT_FAILURE; /* Steal the switch root parameters */ *ret_switch_root_dir = TAKE_PTR(m->switch_root); @@ -2116,7 +2116,7 @@ static int invoke_main_loop( log_notice("Soft-rebooting."); - *ret_retval = EXIT_SUCCESS; + *ret_retval = EXIT_FAILURE; *ret_switch_root_dir = TAKE_PTR(m->switch_root); *ret_switch_root_init = NULL; From d4590ac63da100dd4ecabea8c39c6c88b1386dc0 Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Mon, 10 Mar 2025 12:21:26 +0100 Subject: [PATCH 04/48] umount: do not move busy network mounts If a network mount returns EBUSY on umount, the logic introduced in 6dc68a00cfc816678fd713b12ae2a4cf2ae6da85 causes shutdown to hang indefinitely on `fstatat()` (i.e., within `is_dir(m->path, true)`). Hence, skip this logic for network mounts (following the same motivation we use to skip read-only mounts in this kind of file systems). Fixes 6dc68a00cfc816678fd713b12ae2a4cf2ae6da85 (cherry picked from commit cef2181cda87cbecd6e92f6d7a3bb8556067a88e) (cherry picked from commit 18dde3dd2aa8f05ecf950dab313efd5baf064625) (cherry picked from commit b7cb53a368fb998b9251e7c453d4e59a4d35a9d2) (cherry picked from commit 771f946ce01ebba49509c9cba787276aff67fc9a) --- src/shutdown/umount.c | 14 +++++++++----- src/shutdown/umount.h | 2 +- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/shutdown/umount.c b/src/shutdown/umount.c index 1586c2e214..967bd8b30e 100644 --- a/src/shutdown/umount.c +++ b/src/shutdown/umount.c @@ -63,7 +63,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { struct libmnt_fs *fs; const char *path, *fstype; unsigned long remount_flags = 0u; - bool try_remount_ro, is_api_vfs; + bool try_remount_ro, is_api_vfs, is_network; _cleanup_free_ MountPoint *m = NULL; r = mnt_table_next_fs(table, iter, &fs); @@ -98,6 +98,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { PATH_STARTSWITH_SET(path, "/dev", "/sys", "/proc")) continue; + is_network = fstype_is_network(fstype); is_api_vfs = fstype_is_api_vfs(fstype); /* If we are in a container, don't attempt to read-only mount anything as that brings no real @@ -108,7 +109,7 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { * leave a "dirty fs") and could hang if the network is down. Note that umount2() is more * careful and will not hang because of the network being down. */ try_remount_ro = detect_container() <= 0 && - !fstype_is_network(fstype) && + !is_network && !is_api_vfs && !fstype_is_ro(fstype) && !fstab_test_yes_no_option(options, "ro\0rw\0"); @@ -152,7 +153,11 @@ int mount_points_list_get(const char *mountinfo, MountPoint **head) { /* Unmount sysfs/procfs/… lazily, since syncing doesn't matter there, and it's OK if * something keeps an fd open to it. */ .umount_lazily = is_api_vfs, - .leaf = leaf, + + /* If a mount point is not a leaf, moving it would invalidate our mount table. + * If a mount point is on the network and the network is down, it can hang and block + * the shutdown. */ + .umount_move_if_busy = leaf && !is_network, }; m->path = strdup(path); @@ -405,10 +410,9 @@ static int mount_points_list_umount(MountPoint **head, bool *changed, bool last_ *changed = true; /* If a mount is busy, we move it to not keep parent mount points busy. - * If a mount point is not a leaf, moving it would invalidate our mount table. * More moving will occur in next iteration with a fresh mount table. */ - if (r != -EBUSY || !m->leaf) + if (r != -EBUSY || !m->umount_move_if_busy) continue; _cleanup_free_ char *dirname = NULL; diff --git a/src/shutdown/umount.h b/src/shutdown/umount.h index f8f9ae8038..e76106cc05 100644 --- a/src/shutdown/umount.h +++ b/src/shutdown/umount.h @@ -18,7 +18,7 @@ typedef struct MountPoint { unsigned long remount_flags; bool try_remount_ro; bool umount_lazily; - bool leaf; + bool umount_move_if_busy; LIST_FIELDS(struct MountPoint, mount_point); } MountPoint; From e84a55f2b5cc69e4d3f277d5633f2625e2a52515 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Mar 2025 11:43:46 +0100 Subject: [PATCH 05/48] manager: explicitly create our private runtime directory So far /run/systemd/ was created as side-effect of initializing the D-Bus client/server. But in one of the next commits we'll suppress connecting to D-Bus in test runs, hence let's move the logic our of the D-Bus code and into manager_startup(). Then, also drop creating it again and again in PID 1 at various places, and just rely on it to exist. (cherry picked from commit e75fbee6248736d2a71aa96438b495887ef761ea) (cherry picked from commit a4bb3316e0324c343a036a6fb87d57381af4b824) (cherry picked from commit d0c4baba4cff48415fae5f21d191e235279d9e21) (cherry picked from commit 61884a1b404d30f4f0537a699d678322ce5724c9) --- src/core/core-varlink.c | 2 +- src/core/dbus.c | 2 -- src/core/manager.c | 25 ++++++++++++++++++++++--- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/src/core/core-varlink.c b/src/core/core-varlink.c index b4de317f30..82a6f9f547 100644 --- a/src/core/core-varlink.c +++ b/src/core/core-varlink.c @@ -504,7 +504,7 @@ static int manager_varlink_init_system(Manager *m) { bool fresh = r > 0; if (!MANAGER_IS_TEST_RUN(m)) { - (void) mkdir_p_label("/run/systemd/userdb", 0755); + (void) mkdir_label("/run/systemd/userdb", 0755); FOREACH_STRING(address, "/run/systemd/userdb/io.systemd.DynamicUser", VARLINK_ADDR_PATH_MANAGED_OOM_SYSTEM) { if (!fresh) { diff --git a/src/core/dbus.c b/src/core/dbus.c index b08e97f2e0..216526b8da 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -33,7 +33,6 @@ #include "fd-util.h" #include "fs-util.h" #include "log.h" -#include "mkdir-label.h" #include "process-util.h" #include "selinux-access.h" #include "serialize.h" @@ -966,7 +965,6 @@ int bus_init_private(Manager *m) { return log_error_errno(r, "Can't set path for AF_UNIX socket to bind to: %m"); sa_len = r; - (void) mkdir_parents_label(sa.un.sun_path, 0755); (void) sockaddr_un_unlink(&sa.un); fd = socket(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0); diff --git a/src/core/manager.c b/src/core/manager.c index 185923061c..9ef91199f3 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -308,7 +308,7 @@ static int manager_check_ask_password(Manager *m) { if (!m->ask_password_event_source) { assert(m->ask_password_inotify_fd < 0); - (void) mkdir_p_label("/run/systemd/ask-password", 0755); + (void) mkdir_label("/run/systemd/ask-password", 0755); m->ask_password_inotify_fd = inotify_init1(IN_NONBLOCK|IN_CLOEXEC); if (m->ask_password_inotify_fd < 0) @@ -994,7 +994,7 @@ int manager_new(RuntimeScope runtime_scope, ManagerTestRunFlags test_run_flags, r = xdg_user_runtime_dir(&units_path, "/systemd/units"); if (r < 0) return r; - r = mkdir_p_label(units_path, 0755); + r = mkdir_label(units_path, 0755); } if (r < 0 && r != -EEXIST) @@ -1044,7 +1044,6 @@ static int manager_setup_notify(Manager *m) { m->notify_socket); sa_len = r; - (void) mkdir_parents_label(m->notify_socket, 0755); (void) sockaddr_un_unlink(&sa.un); r = mac_selinux_bind(fd, &sa.sa, sa_len); @@ -1881,11 +1880,31 @@ void manager_reloading_stopp(Manager **m) { } } +static int manager_make_runtime_dir(Manager *m) { + int r; + + assert(m); + + _cleanup_free_ char *d = path_join(m->prefix[EXEC_DIRECTORY_RUNTIME], "systemd"); + if (!d) + return log_oom(); + + r = mkdir_label(d, 0755); + if (r < 0 && r != -EEXIST) + return log_error_errno(r, "Failed to create directory '%s/': %m", d); + + return 0; +} + int manager_startup(Manager *m, FILE *serialization, FDSet *fds, const char *root) { int r; assert(m); + r = manager_make_runtime_dir(m); + if (r < 0) + return r; + /* If we are running in test mode, we still want to run the generators, * but we should not touch the real generator directories. */ r = lookup_paths_init_or_warn(&m->lookup_paths, m->runtime_scope, From 13f0136f1d07791f610cc744dad4ad24a39958ea Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Mar 2025 18:19:34 +0100 Subject: [PATCH 06/48] analyze: don't connect to bus from analyze test run This thing should not be "live", hence don't try to connect to the bus, or bind the private bus socket. Fixes: #36540 (cherry picked from commit 71a737d68db8c8a72fdc076d0ec87f43d3ecd7a1) (cherry picked from commit b4565a757f858ec3b45fe44574b2cd7dc8f7ac90) (cherry picked from commit 071fd1744e2f3302e54f0e96db2a7cf10c0963ba) (cherry picked from commit ad180871acd3b42540e171b2daee3c1c5aaae780) --- src/core/manager.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/manager.c b/src/core/manager.c index 9ef91199f3..5ba7873a62 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1804,6 +1804,9 @@ static bool manager_dbus_is_running(Manager *m, bool deserialized) { static void manager_setup_bus(Manager *m) { assert(m); + if (MANAGER_IS_TEST_RUN(m)) + return; + /* Let's set up our private bus connection now, unconditionally */ (void) bus_init_private(m); From 4d7389950e02c2e97d7c01840d7d829ff0678fc3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Mar 2025 11:49:13 +0100 Subject: [PATCH 07/48] test-execute: prominently show which test we are about to enter (cherry picked from commit 66c2a2e42ac5d6cbd526f4bba31dcd3218550cde) (cherry picked from commit 830b30814a0079d9689261c8916692cf7e9dfd56) (cherry picked from commit d04e76a0c38afc1f80f46498f3426c5df9367e95) (cherry picked from commit 09610dbe66931d77b3311584a2601bb3495b65ee) --- src/test/test-execute.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/test/test-execute.c b/src/test/test-execute.c index 31cc7bdcef..5a5634c5f5 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -1352,9 +1352,10 @@ static void run_tests(RuntimeScope scope, char **patterns) { //manager_override_log_level(m, LOG_DEBUG); for (const test_entry *test = tests; test->f; test++) - if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE)) + if (strv_fnmatch_or_empty(patterns, test->name, FNM_NOESCAPE)) { + log_info("Starting %s.", test->name); test->f(m); - else + } else log_info("Skipping %s because it does not match any pattern.", test->name); } From d651f20432d044449f8efe135968e7104100188c Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Mar 2025 17:51:39 +0100 Subject: [PATCH 08/48] getty-generator: don't use "3270!tty1" when instantiating serial-getty@.service on s390x Path of the 3270 console in /sys is "/sys/class/tty/3270!tty1" but its device node is "/dev/3270/tty1". (cherry picked from commit dbe61d9ec7d9c197856756378af6add930b5a5a9) (cherry picked from commit 23dc4450cddd5ee89d291600e226a3615b56a185) (cherry picked from commit 7b4d672e07747b1dd7f596248fc479088e4485ad) (cherry picked from commit 26bcf286cb757597d10e7b57d2dd7f50f4bab31e) --- src/getty-generator/getty-generator.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/getty-generator/getty-generator.c b/src/getty-generator/getty-generator.c index 4379b4b648..dd570e886b 100644 --- a/src/getty-generator/getty-generator.c +++ b/src/getty-generator/getty-generator.c @@ -273,17 +273,17 @@ static int run(const char *dest, const char *dest_early, const char *dest_late) return r; } - /* Automatically add in a serial getty on the first virtualizer console */ + /* Automatically add a serial getty to each available virtualizer console. */ FOREACH_STRING(j, "hvc0", "xvc0", "hvsi0", "sclp_line0", "ttysclp0", - "3270!tty1") { + "3270/tty1") { _cleanup_free_ char *p = NULL; - p = path_join("/sys/class/tty", j); + p = path_join("/dev", j); if (!p) return log_oom(); if (access(p, F_OK) < 0) From 8812b4d3c86bb0f45d383122d690fa5a8e27c276 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Mar 2025 11:43:07 +0100 Subject: [PATCH 09/48] udevadm: check number of passed arguments We didn't check the number of arguments first, hence ended up outputting some ugly complaints with `(null)` in a format string. And what's worse accepted any number of arguments, where we'd ignore all but the first two though. (cherry picked from commit e5dfe2cd8d32c3ddd3ca6763dbbe2d0ea2ab61aa) (cherry picked from commit 81b821d08ceb5feec4b879d59c194897a957eb5e) (cherry picked from commit 3fc144d45c37bddc930858953aeafb2062fe73c7) (cherry picked from commit cafcfa7c3776c01a8487c5d463752a9c8599a212) --- src/udev/udevadm-test-builtin.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/udev/udevadm-test-builtin.c b/src/udev/udevadm-test-builtin.c index 088b4da3c1..dfea849fd0 100644 --- a/src/udev/udevadm-test-builtin.c +++ b/src/udev/udevadm-test-builtin.c @@ -58,16 +58,11 @@ static int parse_argv(int argc, char *argv[]) { assert_not_reached(); } - arg_command = argv[optind++]; - if (!arg_command) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "Command missing."); - - arg_syspath = argv[optind++]; - if (!arg_syspath) - return log_error_errno(SYNTHETIC_ERRNO(EINVAL), - "device is missing."); + if (argc != optind + 2) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Expected two arguments: command string and device path."); + arg_command = ASSERT_PTR(argv[optind]); + arg_syspath = ASSERT_PTR(argv[optind+1]); return 1; } From a5c3c5100bc041ad755487c54807eeb79aa85e93 Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 17 Mar 2025 12:28:37 +0100 Subject: [PATCH 10/48] sd_bus_open_user_machine(): Don't shortcut without necessary env Don't shortcut if we don't have the necessary environment variables set in sd_bus_open_user_machine(). (cherry picked from commit 9e34c34b7b027da24b084a58246c1d88bdbcc817) (cherry picked from commit bd06aa555603f877774942dcda4664e8e44f21fd) (cherry picked from commit 71cca3e39c63038ace72be1cb3955a5546caf607) (cherry picked from commit 9ab7f1463438498f4a5fc7fb9931f51882e16f9b) --- src/libsystemd/sd-bus/sd-bus.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/libsystemd/sd-bus/sd-bus.c b/src/libsystemd/sd-bus/sd-bus.c index f89de1acce..77d7565592 100644 --- a/src/libsystemd/sd-bus/sd-bus.c +++ b/src/libsystemd/sd-bus/sd-bus.c @@ -1727,8 +1727,10 @@ _public_ int sd_bus_open_user_machine(sd_bus **ret, const char *user_and_machine assert_return(user_and_machine, -EINVAL); assert_return(ret, -EINVAL); - /* Shortcut things if we'd end up on this host and as the same user. */ - if (user_and_machine_equivalent(user_and_machine)) + /* Shortcut things if we'd end up on this host and as the same user and have one of the necessary + * environment variables set already. */ + if (user_and_machine_equivalent(user_and_machine) && + (secure_getenv("DBUS_SESSION_BUS_ADDRESS") || secure_getenv("XDG_RUNTIME_DIR"))) return sd_bus_open_user(ret); r = user_and_machine_valid(user_and_machine); From 52ab740b5c5742a930ad368eebb5f6539d7f6899 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 19 Mar 2025 01:32:12 +0900 Subject: [PATCH 11/48] initctl: fix error handling Fixes a bug introduced by cc090ca7fec93cd6b41bd7a756cd5fe32df44764 (v246). (cherry picked from commit 59cb9b12abc7efb714d15d357c96bd86ef2ddafc) (cherry picked from commit 8e6fa4e7c61f928510ba176c2d3e05f6c7d0a895) (cherry picked from commit 7e7c3bdf9cee7226ff9c5fd8b1dd474bcb8127d0) (cherry picked from commit a5bea0c25b52a711f07837d18e9989fcb7c3ed14) --- src/initctl/initctl.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/initctl/initctl.c b/src/initctl/initctl.c index d1b7c30562..1c86e20b3b 100644 --- a/src/initctl/initctl.c +++ b/src/initctl/initctl.c @@ -318,8 +318,7 @@ static int run(int argc, char *argv[]) { n = sd_listen_fds(true); if (n < 0) - return log_error_errno(errno, - "Failed to read listening file descriptors from environment: %m"); + return log_error_errno(n, "Failed to read listening file descriptors from environment: %m"); if (n <= 0 || n > SERVER_FD_MAX) return log_error_errno(SYNTHETIC_ERRNO(EINVAL), From b59dab9a5cf07b674aefb54f8cbf0f6ca51d2a91 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Mar 2025 16:54:27 +0100 Subject: [PATCH 12/48] cgroup: whenever we migrate a PID to a unit, explicitly drop unit from empty notification queue A unit might be pending in the empty queue still when we add a PID to the cgroup. At that point, let's explicitly remove the unit from that queue. Fixes: #36781 (cherry picked from commit bb160976b0d2d84d3b23149ce6a4d5b89a665643) (cherry picked from commit 13b011f0e84bd30d524a10e0dd839b508b8e0011) (cherry picked from commit c834d98ddfb568a26ee4920b7431d384cbcbb069) (cherry picked from commit cc0764c291f3592b42834274cc8908f2661ae233) --- src/core/cgroup.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/core/cgroup.c b/src/core/cgroup.c index 8ce69d1ef7..8fe93059e7 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -51,6 +51,8 @@ * out specific attributes from us. */ #define LOG_LEVEL_CGROUP_WRITE(r) (IN_SET(abs(r), ENOENT, EROFS, EACCES, EPERM) ? LOG_DEBUG : LOG_WARNING) +static void unit_remove_from_cgroup_empty_queue(Unit *u); + uint64_t tasks_max_resolve(const TasksMax *tasks_max) { if (tasks_max->scale == 0) return tasks_max->value; @@ -2502,6 +2504,10 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) { else { if (ret >= 0) ret++; /* Count successful additions */ + + /* the cgroup is definitely not empty now, in case the unit was in + * the cgroup empty queue, drop it from there */ + unit_remove_from_cgroup_empty_queue(u); continue; /* When the bus thing worked via the bus we are fully done for this PID. */ } } @@ -2510,8 +2516,10 @@ int unit_attach_pids_to_cgroup(Unit *u, Set *pids, const char *suffix_path) { ret = r; /* Remember first error */ continue; - } else if (ret >= 0) + } else if (ret >= 0) { + unit_remove_from_cgroup_empty_queue(u); ret++; /* Count successful additions */ + } r = cg_all_unified(); if (r < 0) From b7ecca12ecd0a40dd408c52f44d192c98601dae5 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 13 Mar 2025 12:11:40 +0900 Subject: [PATCH 13/48] TEST-73-LOCALE: do not unnecessarily restart systemd-localed It is not necessary to clear previous keymap assignment, as `localectl set-keymap` will anyway overwrite the previous assignment. This drops the unnecessary restart of systemd-localed in the loop. The mkosi test image contains about 500~700 keymaps. The test performance is greatly improved by reducing the number of restarts, especially when the test is running with sanitizers. On Fedora 41 with sanitizers, Before: 1/1 systemd:integration-tests / TEST-73-LOCALE OK 1157.50s After: 1/1 systemd:integration-tests / TEST-73-LOCALE OK 104.43s (cherry picked from commit d8a353552a924592d41a1538ee95d516c9facf30) (cherry picked from commit 614a284f472c0f162f1ea93092c1b03646138f0b) (cherry picked from commit 593df05716174359dfc2d861fabed6e304974a1e) (cherry picked from commit 7aa1a971081d29aa1d8306e8c3c953f77976b71d) --- test/units/testsuite-73.sh | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/units/testsuite-73.sh b/test/units/testsuite-73.sh index df5af4ba87..2e11ce2c51 100755 --- a/test/units/testsuite-73.sh +++ b/test/units/testsuite-73.sh @@ -239,11 +239,6 @@ testcase_vc_keymap() { assert_in "VC Keymap:" "$(localectl)" for i in $(localectl list-keymaps); do - # clear previous conversion from VC -> X11 keymap - systemctl stop systemd-localed.service - wait_vconsole_setup - rm -f /etc/vconsole.conf /etc/X11/xorg.conf.d/00-keyboard.conf /etc/default/keyboard - # set VC keymap assert_rc 0 localectl set-keymap "$i" output=$(localectl) From d43a3f2583cea34423cb34e74182d82f3f79cc0f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Mar 2025 17:38:26 +0100 Subject: [PATCH 14/48] core: fix C type handler for ExitCode property (cherry picked from commit 0b0cb6f33d0c1256e8cc2b77ab361b55ac911105) (cherry picked from commit aba08e3edb180b620e5152cdbc2bd8922adc8680) (cherry picked from commit 6300dc3179a9f5657b755e38e2ddc96d9499a4dc) (cherry picked from commit 0bc549f7faa6f0a6a3ebfede0c978483ecd15e0e) --- src/core/dbus-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index dea69bb6e2..91fe54bb11 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -3007,7 +3007,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_WRITABLE_PROPERTY("ServiceWatchdogs", "b", bus_property_get_bool, bus_property_set_bool, offsetof(Manager, service_watchdogs), 0), SD_BUS_PROPERTY("ControlGroup", "s", NULL, offsetof(Manager, cgroup_root), 0), SD_BUS_PROPERTY("SystemState", "s", property_get_system_state, 0, 0), - SD_BUS_PROPERTY("ExitCode", "y", bus_property_get_unsigned, offsetof(Manager, return_value), 0), + SD_BUS_PROPERTY("ExitCode", "y", NULL, offsetof(Manager, return_value), 0), SD_BUS_PROPERTY("DefaultTimerAccuracyUSec", "t", bus_property_get_usec, offsetof(Manager, default_timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, default_timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), From 973bf786e05b30839356127833498abe51e4b6b5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Mar 2025 17:51:18 +0100 Subject: [PATCH 15/48] core: not sure why but TTYRows/TTYColumns property is 16bit towards outside, 32bit inside, handle that properly (cherry picked from commit ed13622bc83deeade066aac31cd96d5c52efe028) (cherry picked from commit e3b16c73ae0263ded58297e0ed7a080c76217e71) (cherry picked from commit e40142c1abdff8475e689f219447d4093f3f2bae) (cherry picked from commit 826ebfc6670f2f341f77a6db44f1c6ec30cc0081) --- src/core/dbus-execute.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/core/dbus-execute.c b/src/core/dbus-execute.c index a9a375290b..e5c7491338 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -1183,6 +1183,23 @@ static int property_get_image_policy( return sd_bus_message_append(reply, "s", s); } +static int property_get_unsigned_as_uint16( + sd_bus *bus, + const char *path, + const char *interface, + const char *property, + sd_bus_message *reply, + void *userdata, + sd_bus_error *error) { + + unsigned *value = ASSERT_PTR(userdata); + + /* Returns an unsigned as a D-Bus "q" type, i.e. as 16-bit value, even if unsigned is 32-bit. We'll saturate if it doesn't fit. */ + + uint16_t q = *value >= UINT16_MAX ? UINT16_MAX : (uint16_t) *value; + return sd_bus_message_append_basic(reply, 'q', &q); +} + const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST), @@ -1260,8 +1277,8 @@ const sd_bus_vtable bus_exec_vtable[] = { SD_BUS_PROPERTY("TTYReset", "b", bus_property_get_bool, offsetof(ExecContext, tty_reset), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYVHangup", "b", bus_property_get_bool, offsetof(ExecContext, tty_vhangup), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("TTYVTDisallocate", "b", bus_property_get_bool, offsetof(ExecContext, tty_vt_disallocate), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("TTYRows", "q", bus_property_get_unsigned, offsetof(ExecContext, tty_rows), SD_BUS_VTABLE_PROPERTY_CONST), - SD_BUS_PROPERTY("TTYColumns", "q", bus_property_get_unsigned, offsetof(ExecContext, tty_cols), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTYRows", "q", property_get_unsigned_as_uint16, offsetof(ExecContext, tty_rows), SD_BUS_VTABLE_PROPERTY_CONST), + SD_BUS_PROPERTY("TTYColumns", "q", property_get_unsigned_as_uint16, offsetof(ExecContext, tty_cols), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogPriority", "i", bus_property_get_int, offsetof(ExecContext, syslog_priority), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogIdentifier", "s", NULL, offsetof(ExecContext, syslog_identifier), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("SyslogLevelPrefix", "b", bus_property_get_bool, offsetof(ExecContext, syslog_level_prefix), SD_BUS_VTABLE_PROPERTY_CONST), From 8a5835c650e017600069262cb202d26bf0c84b8c Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 24 Mar 2025 18:25:29 +0000 Subject: [PATCH 16/48] man: fix typo in org.freedesktop.systemd1.xml (cherry picked from commit b065ff03b1e9a6409d0e4fec10e3b802cc067e8b) (cherry picked from commit 694aa0115d77e41dbda80891d8a4b766313adfae) (cherry picked from commit 00e48cb057cff5caa84ba532e67004faa25310fe) (cherry picked from commit 5959e2f2cba357329c9a4a21bf9a7b085d36c67a) --- man/org.freedesktop.systemd1.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/org.freedesktop.systemd1.xml b/man/org.freedesktop.systemd1.xml index 7a30647084..742e4751f6 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -8457,7 +8457,7 @@ node /org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dclean_2etimer { elapsation point on the CLOCK_REALTIME clock, relative to its epoch. NextElapseUSecRealtime contains the next elapsation point on the - CLOCK_REALTIME clock in miscroseconds since the epoch, or 0 if this timer event + CLOCK_REALTIME clock in microseconds since the epoch, or 0 if this timer event does not include at least one calendar event. Similarly, NextElapseUSecMonotonic contains the next elapsation point on the From 8d69f9872d985d988267150507c80e2825a77c2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Mon, 24 Mar 2025 22:04:04 +0100 Subject: [PATCH 17/48] man/systemd-remount-fs: fix grammar (cherry picked from commit 7a468f277b217b8bf25fca89706364afa99e376c) (cherry picked from commit 2a35f220477ca655d1f49f119348e3f216405d54) (cherry picked from commit 47315320d5e165437eb63570c22557c72e09079b) (cherry picked from commit d7a20c4b0a7c7a860b3327fd22326713cf296312) --- man/systemd-remount-fs.service.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd-remount-fs.service.xml b/man/systemd-remount-fs.service.xml index 266db88461..4c772fb034 100644 --- a/man/systemd-remount-fs.service.xml +++ b/man/systemd-remount-fs.service.xml @@ -51,7 +51,7 @@ Note: systemd-remount-fs.service is usually pulled in by systemd-fstab-generator8, hence it is also affected by the kernel command line option fstab=, which may be used - to disable the generator. It may also pulled in by + to disable the generator. It may also be pulled in by systemd-gpt-auto-generator8, which is affected by systemd.gpt_auto and other options. From 33109f27cc7f52b1a54c9f8af5ec5439a42e1ec9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 25 Mar 2025 10:40:12 +0100 Subject: [PATCH 18/48] man/systed.swap: update description of implicit deps This changed in e3e6f996894f0eea0e766b4194922f5c7235fb01. Closes https://github.com/systemd/systemd/issues/36761. (cherry picked from commit 4dd94e5ba1de7e3aa732176e0b60d94aec50c05e) (cherry picked from commit 65b3d7f08a8ecf66164eaafba9e467e558e4cf59) (cherry picked from commit faa5d159df0b19ff03fcf6928a80a2e4d01011ae) (cherry picked from commit b4f19201029831cde8a30ad0c743c90d827ab309) --- man/systemd.swap.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemd.swap.xml b/man/systemd.swap.xml index 8287382eb6..e0b323af54 100644 --- a/man/systemd.swap.xml +++ b/man/systemd.swap.xml @@ -72,7 +72,7 @@ All swap units automatically get the - BindsTo= and After= + Requires= and After= dependencies on the device units or the mount units of the files they are activated from. From 2489f0987591618502a4fc43594994b5b8b37c0a Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Mar 2025 11:51:38 +0200 Subject: [PATCH 19/48] homed: don't log error we don't have (cherry picked from commit 521b6bb1177b534db6cab28c889e6550680517c4) (cherry picked from commit 03605d767ffcd446da876a97de967d4d8b56272c) (cherry picked from commit 92d03c858c59b94d13049ff04da2135c1f22c4dd) (cherry picked from commit a3549e26eea044a10aba6a180d24dac0b7b0ecb1) --- src/home/homed-manager.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/home/homed-manager.c b/src/home/homed-manager.c index b2179c53c7..8e74b6ed88 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -553,7 +553,7 @@ static int search_quota(uid_t uid, const char *exclude_quota_path) { if ((FLAGS_SET(req.dqb_valid, QIF_SPACE) && req.dqb_curspace > 0) || (FLAGS_SET(req.dqb_valid, QIF_INODES) && req.dqb_curinodes > 0)) { - log_debug_errno(errno, "Quota reports UID " UID_FMT " occupies disk space on %s.", uid, where); + log_debug("Quota reports UID " UID_FMT " occupies disk space on %s.", uid, where); return 1; } } From a01661a11879e0cc27335d2c870c35cf384f3992 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 29 Mar 2025 17:55:45 +0000 Subject: [PATCH 20/48] test: skip TEST-75-RESOLVED if resolved is disabled at build time (cherry picked from commit 75b16ac59ed25d6aad77d5a39022476312fb3349) (cherry picked from commit 0a0e4d9bf5817d8f9a36d8dbb4a0d8eaad43dc82) (cherry picked from commit f084ad2db957830f1bda55c0befa3c4780d08ed9) (cherry picked from commit 76a9c2aa6b1e9775370000f5a02c257f80c68352) --- test/units/testsuite-75.sh | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/units/testsuite-75.sh b/test/units/testsuite-75.sh index c8cb85af56..e45c6112c7 100755 --- a/test/units/testsuite-75.sh +++ b/test/units/testsuite-75.sh @@ -14,6 +14,11 @@ set -o pipefail # shellcheck source=test/units/util.sh . "$(dirname "$0")"/util.sh +if ! command -v resolvectl >/dev/null || ! command -v networkctl >/dev/null; then + echo "resolved/networkd not found, skipping..." | tee --append /skipped + exit 77 +fi + RUN_OUT="$(mktemp)" run() { From 8e1d2758006fd69df19f7d190edf95f984472f17 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 29 Mar 2025 17:56:04 +0000 Subject: [PATCH 21/48] test: skip networkd tests if networkd/resolved are disabled at build time (cherry picked from commit da2498352635921621a636014fee0547c53058b2) (cherry picked from commit 88a0d3dfcb7f5769ac1b1add3d66d9699252dfe0) (cherry picked from commit 37ada4a1f5cfd1ca191e228a0ece01a2035126d4) (cherry picked from commit a61f73231f39c363df4088ff41d07e08091bd1fe) --- test/networkd-test.py | 6 ++++++ test/test-network/systemd-networkd-tests.py | 4 ++++ 2 files changed, 10 insertions(+) diff --git a/test/networkd-test.py b/test/networkd-test.py index 349213d831..76c1331ab6 100755 --- a/test/networkd-test.py +++ b/test/networkd-test.py @@ -47,6 +47,12 @@ def setUpModule(): global tmpmounts """Initialize the environment, and perform sanity checks on it.""" + + if shutil.which('networkctl') is None: + raise unittest.SkipTest('networkd not installed') + if shutil.which('resolvectl') is None: + raise unittest.SkipTest('resolved not installed') + if NETWORKD_WAIT_ONLINE is None: raise OSError(errno.ENOENT, 'systemd-networkd-wait-online not found') diff --git a/test/test-network/systemd-networkd-tests.py b/test/test-network/systemd-networkd-tests.py index 0cd48e34b6..f3a79b1f1f 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -6160,6 +6160,10 @@ def test_mtu_link_ipv6_mtu(self): if not os.path.exists(os.path.join(systemd_source_dir, "meson_options.txt")): raise RuntimeError(f"{systemd_source_dir} doesn't appear to be a systemd source tree") + if networkd_bin is None or resolved_bin is None or timesyncd_bin is None: + print("networkd tests require networkd/resolved/timesyncd to be enabled") + sys.exit(77) + use_valgrind = ns.use_valgrind enable_debug = ns.enable_debug asan_options = ns.asan_options From 66378ccffcc3cb15e9f7074bcce0009b00fddfd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Thu, 10 Apr 2025 13:51:21 +0200 Subject: [PATCH 22/48] test-sd-device: limit the number of iterations when testing device parent/child functions The test "hangs" and times out on some arm64 machines. It actually works as expected, but the machine has 2016 children under /sys/devices/system/memory/, and the tests do a double loop over this, which is slow enough to hit the 120 s limit. Add a limit on the number of iterations. Another option would be to exclude "memory" subsystem. But we may have other subsystems which have the same problem in the future, so I think it'll be more robust to not try to limit the fix to a specific subsystem. (cherry picked from commit 74cb65e45fbf3468cf6b522e4b4fa568d95f12c6) (cherry picked from commit e35435b0a11e6c61c8c43b0cf8dc65a563b4a670) (cherry picked from commit 1f71726206006ff18ea0f96b109faff37dcc48f2) (cherry picked from commit d05d968f28eee3b6b23a0cb870258821ff52cb6b) --- src/libsystemd/sd-device/test-sd-device.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/libsystemd/sd-device/test-sd-device.c b/src/libsystemd/sd-device/test-sd-device.c index 43376a2036..6c93f6b4bb 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -425,6 +425,8 @@ static void check_parent_match(sd_device_enumerator *e, sd_device *dev) { TEST(sd_device_enumerator_add_match_parent) { _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + /* Some devices have thousands of children. Avoid spending too much time in the double loop below. */ + unsigned iterations = 200; int r; assert_se(sd_device_enumerator_new(&e) >= 0); @@ -442,6 +444,9 @@ TEST(sd_device_enumerator_add_match_parent) { const char *syspath; sd_device *parent; + if (iterations-- == 0) + break; + assert_se(sd_device_get_syspath(dev, &syspath) >= 0); r = sd_device_get_parent(dev, &parent); @@ -470,6 +475,8 @@ TEST(sd_device_enumerator_add_match_parent) { TEST(sd_device_get_child) { _cleanup_(sd_device_enumerator_unrefp) sd_device_enumerator *e = NULL; + /* Some devices have thousands of children. Avoid spending too much time in the double loop below. */ + unsigned iterations = 3000; int r; assert_se(sd_device_enumerator_new(&e) >= 0); @@ -503,6 +510,9 @@ TEST(sd_device_get_child) { FOREACH_DEVICE_CHILD_WITH_SUFFIX(parent, child, suffix) { const char *s; + if (iterations-- == 0) + return; + assert_se(child); assert_se(suffix); From f4e5cb2d424d5139d0b1bce8660e0b3769bb2296 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 7 Apr 2025 20:55:41 +0100 Subject: [PATCH 23/48] test: switch to new config keyword for bind9 >= 9.21 bind9 9.21 removed the deprecated 'managed-keys', swap it with 'trust-anchors' if the version is 9.21 or newer [ 20.654086] TEST-75-RESOLVED.sh[1217]: + delv -a /etc/bind.keys @ns1.unsigned.test signed.test [ 20.654425] TEST-75-RESOLVED.sh[1218]: + tee /tmp/tmp.D4LNomAKqY [ 20.672599] TEST-75-RESOLVED.sh[1218]: ;; /etc/bind.keys:1: option 'managed-keys' no longer exists (cherry picked from commit 5f8e5297b4699922aa003353ac1db6559805301f) (cherry picked from commit 85df0981b27c59649fa75916ba1efb4fe820a4dd) (cherry picked from commit 80d4bc9577d8f3fda68e3eb25d4dba8cb8ba47f0) (cherry picked from commit 80d9d3778f788761e3f1821427dbc5e73dbb8deb) --- test/units/testsuite-75.sh | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/units/testsuite-75.sh b/test/units/testsuite-75.sh index e45c6112c7..45629c9c36 100755 --- a/test/units/testsuite-75.sh +++ b/test/units/testsuite-75.sh @@ -227,10 +227,13 @@ keymgr . generate algorithm=ECDSAP256SHA256 ksk=yes zsk=yes # Create a trust anchor for resolved with our root zone keymgr . ds | sed 's/ DS/ IN DS/g' >/etc/dnssec-trust-anchors.d/root.positive # Create a bind-compatible trust anchor (for delv) -# Note: the trust-anchors directive is relatively new, so use the original -# managed-keys one until it's widespread enough +# Note: managed-keys was removed in version 9.21, use the newer trust-anchors directive { - echo 'managed-keys {' + if systemd-analyze compare-versions "$(delv -v | awk '{print $2}')" ge 9.21; then + echo 'trust-anchors {' + else + echo 'managed-keys {' + fi keymgr . dnskey | sed -r 's/^\. DNSKEY ([0-9]+ [0-9]+ [0-9]+) (.+)$/. static-key \1 "\2";/g' echo '};' } >/etc/bind.keys From 9cb94a93728f237bac7e0f7fbdbe20f639d672c8 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Fri, 26 Jan 2024 00:47:23 +0800 Subject: [PATCH 24/48] fstab-generator: drop assertions for mount opts fstab_filter_options accepts NULL and (with later changes) might even return NULL. (cherry picked from commit c521ce42b43ad542a8e3c6e5e83ceb653ca6a71e) (cherry picked from commit ce22c05474b843cbdb474816af015f26cf8a99b8) --- src/fstab-generator/fstab-generator.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 2bd8aad1fd..4681380ab2 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -476,17 +476,20 @@ static int mandatory_mount_drop_unapplicable_options( assert(flags); assert(where); - assert(options); assert(ret_options); if (!(*flags & (MOUNT_NOAUTO|MOUNT_NOFAIL|MOUNT_AUTOMOUNT))) { - _cleanup_free_ char *opts = NULL; + if (options) { + _cleanup_free_ char *opts = NULL; - opts = strdup(options); - if (!opts) - return -ENOMEM; + opts = strdup(options); + if (!opts) + return -ENOMEM; + + *ret_options = TAKE_PTR(opts); + } else + *ret_options = NULL; - *ret_options = TAKE_PTR(opts); return 0; } @@ -522,7 +525,6 @@ static int add_mount( assert(what); assert(where); - assert(opts); assert(target_unit); assert(source); @@ -817,6 +819,9 @@ static int add_sysusr_sysroot_usr_bind_mount(const char *source) { static MountPointFlags fstab_options_to_flags(const char *options, bool is_swap) { MountPointFlags flags = 0; + if (isempty(options)) + return 0; + if (fstab_test_option(options, "x-systemd.makefs\0")) flags |= MOUNT_MAKEFS; if (fstab_test_option(options, "x-systemd.growfs\0")) @@ -892,7 +897,6 @@ static int parse_fstab_one( assert(what_original); assert(fstype); - assert(options); if (prefix_sysroot && !mount_in_initrd(where_original, options, accept_root)) return 0; From 072796e7eb8976843f124a66262ca274c4f8f01a Mon Sep 17 00:00:00 2001 From: Jules Lamur Date: Mon, 7 Apr 2025 18:49:26 +0200 Subject: [PATCH 25/48] fstab-generator: fix options in systemd.mount-extra= arg Fixes a bug introduced by 55365b0a233ae3024411fd0815ad930e20f6a3d6 (v254). The arguments `(rd.)systemd.mount-extra` take a value that looks like `WHAT:WHERE[:FSTYPE[:OPTIONS]]`. The `OPTIONS` were parsed into a nulstr where a comma-separated c-string was expected. This leads to a bug where only the first option was taken into account by the generator. For example, if you passed `systemd.mount-extra=/x:/y:baz:ro,defaults` to the kernel, `systemd-fstab-generator` would translate that into a nulstr: `ro\0defaults\0`. Since methods processing options in the generator expected a comma-separated c-string, they would only see the first option, `ro` in this case. (cherry picked from commit 06fadc4286fee6a7505a88659e5ae2e6f3ee60ba) (cherry picked from commit 0122eae1af270baed63b258852fa26396ea00fc8) (cherry picked from commit d255dc77811ad91965100aa4e59093e577ed056b) (cherry picked from commit c19df38f3c6ee1a4282e650c5bec606b7ecf1240) --- src/fstab-generator/fstab-generator.c | 21 ++++--------------- .../hoge-withx20space.mount | 2 +- .../dev-sdy3.swap | 2 +- .../dev-sdy3.swap | 0 4 files changed, 6 insertions(+), 19 deletions(-) rename test/test-fstab-generator/test-20-swap-from-cmdline.expected/{swap.target.requires => swap.target.wants}/dev-sdy3.swap (100%) diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 4681380ab2..ca778ae99c 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -108,15 +108,15 @@ static int mount_array_add_internal( char *in_what, char *in_where, const char *in_fstype, - const char *in_options) { + char *in_options) { _cleanup_free_ char *what = NULL, *where = NULL, *fstype = NULL, *options = NULL; - int r; /* This takes what and where. */ what = ASSERT_PTR(in_what); where = in_where; + options = in_options; fstype = strdup(isempty(in_fstype) ? "auto" : in_fstype); if (!fstype) @@ -125,19 +125,6 @@ static int mount_array_add_internal( if (streq(fstype, "swap")) where = mfree(where); - if (!isempty(in_options)) { - _cleanup_strv_free_ char **options_strv = NULL; - - r = strv_split_full(&options_strv, in_options, ",", 0); - if (r < 0) - return r; - - r = strv_make_nulstr(options_strv, &options, NULL); - } else - r = strv_make_nulstr(STRV_MAKE("defaults"), &options, NULL); - if (r < 0) - return r; - if (!GREEDY_REALLOC(arg_mounts, arg_n_mounts + 1)) return -ENOMEM; @@ -167,7 +154,7 @@ static int mount_array_add(bool for_initrd, const char *str) { if (!isempty(str)) return -EINVAL; - return mount_array_add_internal(for_initrd, TAKE_PTR(what), TAKE_PTR(where), fstype, options); + return mount_array_add_internal(for_initrd, TAKE_PTR(what), TAKE_PTR(where), fstype, TAKE_PTR(options)); } static int mount_array_add_swap(bool for_initrd, const char *str) { @@ -185,7 +172,7 @@ static int mount_array_add_swap(bool for_initrd, const char *str) { if (!isempty(str)) return -EINVAL; - return mount_array_add_internal(for_initrd, TAKE_PTR(what), NULL, "swap", options); + return mount_array_add_internal(for_initrd, TAKE_PTR(what), NULL, "swap", TAKE_PTR(options)); } static int write_options(FILE *f, const char *options) { diff --git a/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount b/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount index e9ffb4bbd9..d3797c9706 100644 --- a/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount +++ b/test/test-fstab-generator/test-19-mounts-from-cmdline.expected/hoge-withx20space.mount @@ -9,4 +9,4 @@ Before=remote-fs.target What=//foo￾bar Where=/hoge/with space Type=cifs -Options=rw +Options=rw,seclabel diff --git a/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap b/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap index 3b6563d216..1b4b53c9b8 100644 --- a/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap +++ b/test/test-fstab-generator/test-20-swap-from-cmdline.expected/dev-sdy3.swap @@ -7,4 +7,4 @@ After=blockdev@dev-sdy3.target [Swap] What=/dev/sdy3 -Options=x-systemd.makefs +Options=x-systemd.makefs,nofail diff --git a/test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.requires/dev-sdy3.swap b/test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.wants/dev-sdy3.swap similarity index 100% rename from test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.requires/dev-sdy3.swap rename to test/test-fstab-generator/test-20-swap-from-cmdline.expected/swap.target.wants/dev-sdy3.swap From 8807d79f41d27b02859abf80212e75db93ec21e7 Mon Sep 17 00:00:00 2001 From: kmeaw Date: Sun, 30 Mar 2025 13:08:38 +0100 Subject: [PATCH 26/48] shared/calendarspec: fix normalization when DST is negative When trying to calculate the next firing of 'hourly', we'd lose the tm_isdst value on the next iteration. On most systems in Europe/Dublin it would cause a 100% cpu hang due to timers restarting. This happens in Europe/Dublin because Ireland defines the Irish Standard Time as UTC+1, so winter time is encoded in tzdata as negative 1 hour of daylight saving. Before this patch: $ env TZ=IST-1GMT-0,M10.5.0/1,M3.5.0/1 systemd-analyze calendar --base-time='Sat 2025-03-29 22:00:00 UTC' --iterations=5 'hourly' Original form: hourly Normalized form: *-*-* *:00:00 Next elapse: Sat 2025-03-29 23:00:00 GMT (in UTC): Sat 2025-03-29 23:00:00 UTC From now: 13h ago Iteration #2: Sun 2025-03-30 00:00:00 GMT (in UTC): Sun 2025-03-30 00:00:00 UTC From now: 12h ago Iteration #3: Sun 2025-03-30 00:00:00 GMT <-- note every next iteration having the same firing time (in UTC): Sun 2025-03-30 00:00:00 UTC From now: 12h ago ... With this patch: $ env TZ=IST-1GMT-0,M10.5.0/1,M3.5.0/1 systemd-analyze calendar --base-time='Sat 2025-03-29 22:00:00 UTC' --iterations=5 'hourly' Original form: hourly Normalized form: *-*-* *:00:00 Next elapse: Sat 2025-03-29 23:00:00 GMT (in UTC): Sat 2025-03-29 23:00:00 UTC From now: 13h ago Iteration #2: Sun 2025-03-30 00:00:00 GMT (in UTC): Sun 2025-03-30 00:00:00 UTC From now: 12h ago Iteration #3: Sun 2025-03-30 02:00:00 IST <-- the expected 1 hour jump (in UTC): Sun 2025-03-30 01:00:00 UTC From now: 11h ago ... This bug isn't reproduced on Debian and Ubuntu because they mitigate it by using the rearguard version of tzdata. ArchLinux and NixOS don't, so it would cause pid1 to spin during DST transition. This is how the affected tzdata looks like: $ zdump -V -c 2024,2025 Europe/Dublin Europe/Dublin Sun Mar 31 00:59:59 2024 UT = Sun Mar 31 00:59:59 2024 GMT isdst=1 gmtoff=0 Europe/Dublin Sun Mar 31 01:00:00 2024 UT = Sun Mar 31 02:00:00 2024 IST isdst=0 gmtoff=3600 Europe/Dublin Sun Oct 27 00:59:59 2024 UT = Sun Oct 27 01:59:59 2024 IST isdst=0 gmtoff=3600 Europe/Dublin Sun Oct 27 01:00:00 2024 UT = Sun Oct 27 01:00:00 2024 GMT isdst=1 gmtoff=0 Compare it to Europe/London: $ zdump -V -c 2024,2025 Europe/London Europe/London Sun Mar 31 00:59:59 2024 UT = Sun Mar 31 00:59:59 2024 GMT isdst=0 gmtoff=0 Europe/London Sun Mar 31 01:00:00 2024 UT = Sun Mar 31 02:00:00 2024 BST isdst=1 gmtoff=3600 Europe/London Sun Oct 27 00:59:59 2024 UT = Sun Oct 27 01:59:59 2024 BST isdst=1 gmtoff=3600 Europe/London Sun Oct 27 01:00:00 2024 UT = Sun Oct 27 01:00:00 2024 GMT isdst=0 gmtoff=0 Fixes #32039. (cherry picked from commit e4bb033e2fcea504f7496df90be7a3556fcea44b) (cherry picked from commit 07c01efc82d4a239ef0d14da54d36053294ad203) There were some conflicts related to the skipping of 6f5cf41570776f489967d1a7de18260b2bc9acf9, but the tests pass with and the example output above also looks good, so I think the backport is correct. (cherry picked from commit 1568dea89ebb84ed2c9cf8c45aaf90c07858cbc0) (cherry picked from commit f3dc34ec87344f796836ef3b4a98d5e2e099fa14) --- src/shared/calendarspec.c | 48 +++++++++++++++++++++++++++++++++--- src/test/test-calendarspec.c | 4 ++- 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/src/shared/calendarspec.c b/src/shared/calendarspec.c index 2665930209..b2fca08374 100644 --- a/src/shared/calendarspec.c +++ b/src/shared/calendarspec.c @@ -1229,14 +1229,43 @@ static bool matches_weekday(int weekdays_bits, const struct tm *tm, bool utc) { return (weekdays_bits & (1 << k)); } +static int tm_compare(const struct tm *t1, const struct tm *t2) { + int r; + + assert(t1); + assert(t2); + + r = CMP(t1->tm_year, t2->tm_year); + if (r != 0) + return r; + + r = CMP(t1->tm_mon, t2->tm_mon); + if (r != 0) + return r; + + r = CMP(t1->tm_mday, t2->tm_mday); + if (r != 0) + return r; + + r = CMP(t1->tm_hour, t2->tm_hour); + if (r != 0) + return r; + + r = CMP(t1->tm_min, t2->tm_min); + if (r != 0) + return r; + + return CMP(t1->tm_sec, t2->tm_sec); +} + /* A safety valve: if we get stuck in the calculation, return an error. * C.f. https://bugzilla.redhat.com/show_bug.cgi?id=1941335. */ #define MAX_CALENDAR_ITERATIONS 1000 static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { struct tm c; - int tm_usec; - int r; + int tm_usec, r; + bool invalidate_dst = false; /* Returns -ENOENT if the expression is not going to elapse anymore */ @@ -1249,7 +1278,8 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { for (unsigned iteration = 0; iteration < MAX_CALENDAR_ITERATIONS; iteration++) { /* Normalize the current date */ (void) mktime_or_timegm(&c, spec->utc); - c.tm_isdst = spec->dst; + if (!invalidate_dst) + c.tm_isdst = spec->dst; c.tm_year += 1900; r = find_matching_component(spec, spec->year, &c, &c.tm_year); @@ -1339,6 +1369,18 @@ static int find_next(const CalendarSpec *spec, struct tm *tm, usec_t *usec) { if (r == 0) continue; + r = tm_compare(tm, &c); + if (r == 0) { + assert(tm_usec + 1 <= 1000000); + r = CMP(*usec, (usec_t) tm_usec + 1); + } + if (r >= 0) { + /* We're stuck - advance, let mktime determine DST transition and try again. */ + invalidate_dst = true; + c.tm_hour++; + continue; + } + *tm = c; *usec = tm_usec; return 0; diff --git a/src/test/test-calendarspec.c b/src/test/test-calendarspec.c index eee621f2a0..f323438bcb 100644 --- a/src/test/test-calendarspec.c +++ b/src/test/test-calendarspec.c @@ -47,7 +47,7 @@ static void _test_next(int line, const char *input, const char *new_tz, usec_t a if (old_tz) old_tz = strdupa_safe(old_tz); - if (!isempty(new_tz)) + if (!isempty(new_tz) && !strchr(new_tz, ',')) new_tz = strjoina(":", new_tz); assert_se(set_unset_env("TZ", new_tz, true) == 0); @@ -219,6 +219,8 @@ TEST(calendar_spec_next) { /* Check that we don't start looping if mktime() moves us backwards */ test_next("Sun *-*-* 01:00:00 Europe/Dublin", "", 1616412478000000, 1617494400000000); test_next("Sun *-*-* 01:00:00 Europe/Dublin", "IST", 1616412478000000, 1617494400000000); + /* Europe/Dublin TZ that moves DST backwards */ + test_next("hourly", "IST-1GMT-0,M10.5.0/1,M3.5.0/1", 1743292800000000, 1743296400000000); } TEST(calendar_spec_from_string) { From 3606a9647de476da7e59c455ce26de04873d06b1 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 Apr 2025 09:11:05 +0900 Subject: [PATCH 27/48] locale-util: fix argument for munmap() (cherry picked from commit 90abb64fd508e8efd937178b3379a62ac97b49ec) (cherry picked from commit 445b4931807089bb7c7b12a8b09f3a580f63f643) (cherry picked from commit 7aba5ce344592df9bb59c36695a35fcab580df34) (cherry picked from commit 4c4d6537539d60254d8fcee5f20072a1485b3209) --- src/basic/locale-util.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/basic/locale-util.c b/src/basic/locale-util.c index 84ad7a9dc1..595244dca8 100644 --- a/src/basic/locale-util.c +++ b/src/basic/locale-util.c @@ -97,7 +97,6 @@ static int add_locales_from_archive(Set *locales) { const struct namehashent *e; const void *p = MAP_FAILED; _cleanup_close_ int fd = -EBADF; - size_t sz = 0; struct stat st; int r; @@ -154,9 +153,9 @@ static int add_locales_from_archive(Set *locales) { r = 0; - finish: +finish: if (p != MAP_FAILED) - munmap((void*) p, sz); + munmap((void*) p, st.st_size); return r; } From 8d8b46459dcdd519be9f5de68c511e99ccc273b5 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Apr 2025 14:39:34 +0200 Subject: [PATCH 28/48] shutdown: handle gracefully if a device disappears while we detach it Let's gracefully handle cases where a device disappears in the time we between our discovery and when we want to detach it, due to "auto-clear" or a similar logic. The loopback case already handled this quite OK, do the same for MD and swap too. Switch to ERRNO_IS_DEVICE_ABSENT() for all checks, just in case. Also improve debug logging for all these cases, so we know exactly what is going on. This is inspired by #37160, but shouldn't really fix anything there, I am pretty sure the ENODEV seen in that output stems from the STOP_ARRAY call, not from the open(). Note that this does not change anything for the device mapper case, because the DM subsystem does not return useful error codes to userspace, hence everything is a complete mess there. (cherry picked from commit 2791b2bc3d84efe674d05e45fa85333eea05ad6f) (cherry picked from commit 4f0a4976dfe64399bc5a3c6b8f00675e2548b067) (cherry picked from commit fc1d80f5b31f629ee03cfd0c0cabaa67aa646dd8) (cherry picked from commit 9ffa0a596cd3ecde490def862adc8bcf3ad804c9) --- src/shutdown/detach-loopback.c | 9 +++++++-- src/shutdown/detach-md.c | 18 ++++++++++++++---- src/shutdown/detach-swap.c | 14 +++++++++----- 3 files changed, 30 insertions(+), 11 deletions(-) diff --git a/src/shutdown/detach-loopback.c b/src/shutdown/detach-loopback.c index 8778a9e0c4..25288af221 100644 --- a/src/shutdown/detach-loopback.c +++ b/src/shutdown/detach-loopback.c @@ -17,6 +17,7 @@ #include "blockdev-util.h" #include "detach-loopback.h" #include "device-util.h" +#include "errno-util.h" #include "fd-util.h" #include "shutdown.h" @@ -106,8 +107,12 @@ static int delete_loopback(const char *device) { fd = open(device, O_RDONLY|O_CLOEXEC); if (fd < 0) { - log_debug_errno(errno, "Failed to open loopback device %s: %m", device); - return errno == ENOENT ? 0 : -errno; + if (ERRNO_IS_DEVICE_ABSENT(errno)) { + log_debug_errno(errno, "Tried to open loopback device '%s', but device disappeared by now, ignoring: %m", device); + return 0; + } + + return log_debug_errno(errno, "Failed to open loopback device '%s': %m", device); } /* Loopback block devices don't sync in-flight blocks when we clear the fd, hence sync explicitly diff --git a/src/shutdown/detach-md.c b/src/shutdown/detach-md.c index 513bbdcef1..d66ecfacd5 100644 --- a/src/shutdown/detach-md.c +++ b/src/shutdown/detach-md.c @@ -131,12 +131,21 @@ static int delete_md(RaidDevice *m) { assert(m->path); fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL); - if (fd < 0) - return -errno; + if (fd < 0) { + if (ERRNO_IS_DEVICE_ABSENT(errno)) { + log_debug_errno(errno, "Tried to open MD device '%s', but device disappeared by now, ignoring: %m", m->path); + return 0; + } + + return log_debug_errno(errno, "Failed to open MD device '%s': %m", m->path); + } (void) sync_with_progress(fd); - return RET_NERRNO(ioctl(fd, STOP_ARRAY, NULL)); + if (ioctl(fd, STOP_ARRAY, NULL) < 0) + return log_debug_errno(errno, "Failed to issue STOP_ARRAY on MD device '%s': %m", m->path); + + return 1; } static int md_points_list_detach(RaidDevice **head, bool *changed, bool last_try) { @@ -164,8 +173,9 @@ static int md_points_list_detach(RaidDevice **head, bool *changed, bool last_try n_failed++; continue; } + if (r > 0) + *changed = true; - *changed = true; raid_device_free(head, m); } diff --git a/src/shutdown/detach-swap.c b/src/shutdown/detach-swap.c index fd7dcdf943..7147fc34a5 100644 --- a/src/shutdown/detach-swap.c +++ b/src/shutdown/detach-swap.c @@ -7,6 +7,7 @@ #include "alloc-util.h" #include "detach-swap.h" +#include "errno-util.h" #include "libmount-util.h" static void swap_device_free(SwapDevice **head, SwapDevice *m) { @@ -74,20 +75,23 @@ int swap_list_get(const char *swaps, SwapDevice **head) { } static int swap_points_list_off(SwapDevice **head, bool *changed) { - int n_failed = 0; + int n_failed = 0, r; assert(head); assert(changed); LIST_FOREACH(swap_device, m, *head) { log_info("Deactivating swap %s.", m->path); - if (swapoff(m->path) < 0) { - log_warning_errno(errno, "Could not deactivate swap %s: %m", m->path); + r = RET_NERRNO(swapoff(m->path)); + if (ERRNO_IS_DEVICE_ABSENT(r)) + log_debug_errno(r, "Tried to deactivate swap '%s', but swap disappeared by now, ignoring: %m", m->path); + else if (r < 0) { + log_warning_errno(r, "Could not deactivate swap %s: %m", m->path); n_failed++; continue; - } + } else + *changed = true; - *changed = true; swap_device_free(head, m); } From 6a9dcd5a1d0bb7c14c951aeab3b67701494cc913 Mon Sep 17 00:00:00 2001 From: Alexander Kurtz Date: Sun, 20 Apr 2025 10:31:22 +0200 Subject: [PATCH 29/48] docs/MEMORY_PRESSURE: Replace incorrect "packages" with correct "pages" (cherry picked from commit e8939ebcd376da4ab90f8840e8eaa4db5bd83210) (cherry picked from commit 8acffbf0abfcaa4de82a81e62d0acee7b896f122) (cherry picked from commit acb447f2c389a6cf0d2cd454e43b89498a174c8c) (cherry picked from commit 46543e57eac679b2f32e60e8ae00a7a6669be149) --- docs/MEMORY_PRESSURE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/MEMORY_PRESSURE.md b/docs/MEMORY_PRESSURE.md index 38f1c645c9..204a42e59a 100644 --- a/docs/MEMORY_PRESSURE.md +++ b/docs/MEMORY_PRESSURE.md @@ -16,7 +16,7 @@ it can attempt various things to make more memory available again ("reclaim"): pages are the many memory mapped executable files and shared libraries on disk, among others. -* The kernel can flush out memory packages not backed by files on disk +* The kernel can flush out memory pages not backed by files on disk ("anonymous" memory, i.e. memory allocated via `malloc()` and similar calls, or `tmpfs` file system contents) if there's swap to write it to. From 3b8ea8f136634da1bd569bf7ee3fba2037afe379 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 20 Apr 2025 16:14:23 +0100 Subject: [PATCH 30/48] man/sd_bus_emit_signal: Fix extra const for strv functions The functions `sd_bus_emit_interfaces_added_strv`, `sd_bus_emit_interfaces_removed_strv` and `sd_bus_emit_properties_changed_strv` take an `char **` not `const char **` as last argument. See `src/systemd/sd-bus.h` for the function definition. (cherry picked from commit 3f75684028da5e5e035e51bde773b77e135be26a) (cherry picked from commit 196a1c3ccb81033e1b54076ba984bfbbbe0dd9de) (cherry picked from commit 62a63713776037a1e054be1c7bd4aa1e7de4fa3d) (cherry picked from commit 26ef8b8daacca365d37998ccdc80a3a1b303ad0d) --- man/sd_bus_emit_signal.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/man/sd_bus_emit_signal.xml b/man/sd_bus_emit_signal.xml index ec2a7976fd..432fec07a4 100644 --- a/man/sd_bus_emit_signal.xml +++ b/man/sd_bus_emit_signal.xml @@ -91,7 +91,7 @@ int sd_bus_emit_interfaces_added_strv sd_bus *bus const char *path - const char **interfaces + char **interfaces @@ -106,7 +106,7 @@ int sd_bus_emit_interfaces_removed_strv sd_bus *bus const char *path - const char **interfaces + char **interfaces @@ -123,7 +123,7 @@ sd_bus *bus const char *path const char *interface - const char **names + char **names From 9be424694fb250988111ddba8f1e697add3baa36 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 21 Apr 2025 05:30:09 +0900 Subject: [PATCH 31/48] man/systemctl: list-sockets command sorts the result This updates the example output of list-sockets command. (cherry picked from commit f7586abfe0ea4c0fa63819148a770851d84506c8) (cherry picked from commit fc078eda7b0a53e0bac3450101c2a6027a6220f5) (cherry picked from commit f3b35f7daa52038cdcaadb227d8a8e4927f96556) (cherry picked from commit e648626a6dc77d2ef502be4ecaa62b34ef8c5024) --- man/systemctl.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 4918c82d8b..d02595e70b 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -159,10 +159,9 @@ PATH CONDITION UNIT shown. Produces output similar to LISTEN UNIT ACTIVATES -/dev/initctl systemd-initctl.socket systemd-initctl.service -… -[::]:22 sshd.socket sshd.service kobject-uevent 1 systemd-udevd-kernel.socket systemd-udevd.service +/dev/rfkill systemd-rfkill.socket systemd-rfkill.service +… 5 sockets listed. Note: because the addresses might contains spaces, this output From 13036d13a217a17aa74e013cc1748d8d5cfdf83f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 21 Apr 2025 10:50:57 +0900 Subject: [PATCH 32/48] man/systemd: fix mapping from SysV runlevel to actual target name See runlevel_to_target() in src/shared/unit-file.c. (cherry picked from commit 70fd998c40649c898b98b413517c142991a29657) (cherry picked from commit 9e2a25fad629dd9d676c829b8b15e76bda6b5460) (cherry picked from commit 8fc23b469004a8e03d40c613d32dff14d3ad016a) (cherry picked from commit 0f566598ec67ec0b48a593550879d2ffa5b4bb78) --- man/systemd.xml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/man/systemd.xml b/man/systemd.xml index 09527de2cb..fe7b1f479b 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -1005,12 +1005,9 @@ 5 Boot into the specified legacy SysV runlevel. - These are equivalent to - systemd.unit=runlevel2.target, - systemd.unit=runlevel3.target, - systemd.unit=runlevel4.target, and - systemd.unit=runlevel5.target, - respectively, and provided for compatibility reasons and to be + 2, 3, and 4 are equivalent to + systemd.unit=multi-user.target; and 5 is equivalent to + systemd.unit=graphical.target, and provided for compatibility reasons and to be easier to type. From 2e8ca82a6213f9711f737ccf9ccdd370d80b0eed Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Apr 2025 09:24:39 +0900 Subject: [PATCH 33/48] test-specifier: replace /dev/initctl with /dev/fd To make the test work even when systemd is built without SysV compat. (cherry picked from commit b4d51152648fe9c1cd89b04ab84806756f453084) (cherry picked from commit 094865105c10534d6bda3003ffbbea02c00794fd) (cherry picked from commit 1efc8390517000f4ba24bfb706bb236bf59025c2) (cherry picked from commit 33fb4f34365785d84657a49ffaad66e0bf4a39ad) --- src/test/test-specifier.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/src/test/test-specifier.c b/src/test/test-specifier.c index d6a8b79aa4..952cf34b57 100644 --- a/src/test/test-specifier.c +++ b/src/test/test-specifier.c @@ -3,7 +3,9 @@ #include "sd-id128.h" #include "alloc-util.h" +#include "format-util.h" #include "log.h" +#include "process-util.h" #include "specifier.h" #include "stat-util.h" #include "stdio-util.h" @@ -89,25 +91,27 @@ TEST(specifier_printf) { TEST(specifier_real_path) { static const Specifier table[] = { - { 'p', specifier_string, "/dev/initctl" }, - { 'y', specifier_real_path, "/dev/initctl" }, - { 'Y', specifier_real_directory, "/dev/initctl" }, + { 'p', specifier_string, "/dev/fd" }, + { 'y', specifier_real_path, "/dev/fd" }, + { 'Y', specifier_real_directory, "/dev/fd" }, { 'w', specifier_real_path, "/dev/tty" }, { 'W', specifier_real_directory, "/dev/tty" }, {} }; - _cleanup_free_ char *w = NULL; + _cleanup_free_ char *w = NULL, *expected = NULL; int r; r = specifier_printf("p=%p y=%y Y=%Y w=%w W=%W", SIZE_MAX, table, NULL, NULL, &w); - assert_se(r >= 0 || r == -ENOENT); - assert_se(w || r == -ENOENT); - puts(strnull(w)); + if (r < 0) { + assert_se(r == -ENOENT); + return (void) log_tests_skipped_errno(r, "/dev/fd and/or /dev/tty do not exist"); + } - /* /dev/initctl should normally be a symlink to /run/initctl */ - if (inode_same("/dev/initctl", "/run/initctl", 0) > 0) - assert_se(streq(w, "p=/dev/initctl y=/run/initctl Y=/run w=/dev/tty W=/dev")); + assert_se(asprintf(&expected, + "p=/dev/fd y=/proc/"PID_FMT"/fd Y=/proc/"PID_FMT" w=/dev/tty W=/dev", + getpid_cached(), getpid_cached()) >= 0); + assert_se(streq(w, expected)); } TEST(specifier_real_path_missing_file) { From 2ab241ce2949baf04ea40ead7a5ef3c425588ab1 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Sat, 26 Apr 2025 17:39:56 +0200 Subject: [PATCH 34/48] man/sd_bus_slot_set_floating: Improve wording around b parameter (cherry picked from commit d93292bc599311d07e2b86d048a6a01b96d3e27d) (cherry picked from commit df3529008ef31b4312b7c7e6fab39868f6499a5a) (cherry picked from commit f71d4856a21ba5fe926f7207aacbfed36b6b0799) (cherry picked from commit c6aaa7e62557c3db847ad0fff1414f99035df42c) --- man/sd_bus_slot_set_floating.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/man/sd_bus_slot_set_floating.xml b/man/sd_bus_slot_set_floating.xml index 3309147847..e60dc6bacb 100644 --- a/man/sd_bus_slot_set_floating.xml +++ b/man/sd_bus_slot_set_floating.xml @@ -51,8 +51,8 @@ referenced bus slot object around. The floating state hence controls the direction of referencing between the bus object and the bus slot objects: if floating the bus pins the bus slot, and otherwise the bus slot pins the bus objects. Use sd_bus_slot_set_floating() to switch between both modes: if the - b parameter is zero, the slot object is considered floating, otherwise it is made a regular - (non-floating) slot object. + b parameter is zero, the slot object is made into a regular (non-floating) slot object, + otherwise it is made into a floating slot object. Bus slot objects may be allocated with calls such as sd_bus_add_match3. If the From b5ba79f9cc9d5ba6bee34b6c613f40fbb551ab60 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Nov 2024 11:18:29 +0100 Subject: [PATCH 35/48] sd-daemon: add fd array size safety check to sd_notify_with_fds() The previous commit removed the UINT_MAX check for the fd array. Let's now re-add one, but at a better place, and with a more useful limit. As it turns out the kernel does not allow passing more than 253 fds at the same time, hence use that as limit. And do so immediately before calculating the control buffer size, so that we catch multiplication overflows. (cherry picked from commit cb42df5310e701b751331ae62432e3fb0df2f660) (cherry picked from commit 3fe78b02280d11746afc979dfed561dbc3fc2554) (cherry picked from commit 67347ca20c17c695786d42e3f754b25b02d5c0fc) --- man/sd_notify.xml | 20 ++++++++++++++++++++ src/basic/missing_socket.h | 7 +++++++ src/libsystemd/sd-daemon/sd-daemon.c | 6 ++++++ src/notify/notify.c | 2 ++ 4 files changed, 35 insertions(+) diff --git a/man/sd_notify.xml b/man/sd_notify.xml index 8df94b1d7d..13fc5c94d7 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -405,6 +405,26 @@ successfully. Specifically, no error is returned when a file descriptor is attempted to be stored using FDSTORE=1 but the service is not actually configured to permit storing of file descriptors (see above). + + + Errors + + Returned errors may indicate the following problems: + + + + -E2BIG + + More file descriptors passed at once than the system allows. On Linux the number of + file descriptors that may be passed across AF_UNIX sockets at once is 253, see + unix7 for + details. + + + + + diff --git a/src/basic/missing_socket.h b/src/basic/missing_socket.h index 30ac297e17..c4b124c8dd 100644 --- a/src/basic/missing_socket.h +++ b/src/basic/missing_socket.h @@ -79,3 +79,10 @@ struct sockaddr_vm { #ifndef SIOCGSKNS #define SIOCGSKNS 0x894C #endif + +/* The maximum number of fds that SCM_RIGHTS accepts. This is an internal kernel constant, but very much + * useful for userspace too. It's documented in unix(7) these days, hence should be fairly reliable to define + * here. */ +#ifndef SCM_MAX_FD +#define SCM_MAX_FD 253U +#endif diff --git a/src/libsystemd/sd-daemon/sd-daemon.c b/src/libsystemd/sd-daemon/sd-daemon.c index 191a7e310d..a9e6b61fe2 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -475,6 +475,12 @@ static int pid_notify_with_fds_internal( if (n_fds > 0 && !fds) return -EINVAL; + /* Let's make sure the multiplications below don't overflow, and also return a recognizable error in + * case the caller tries to send more fds than the kernel limit. The kernel would return EINVAL which + * is not too useful I'd say. */ + if (n_fds > SCM_MAX_FD) + return -E2BIG; + e = getenv("NOTIFY_SOCKET"); if (!e) return 0; diff --git a/src/notify/notify.c b/src/notify/notify.c index f63ec8b355..8dfd2ac285 100644 --- a/src/notify/notify.c +++ b/src/notify/notify.c @@ -433,6 +433,8 @@ static int run(int argc, char* argv[]) { r = sd_pid_notify_with_fds(source_pid, /* unset_environment= */ false, n, a, k); } + if (r == -E2BIG) + return log_error_errno(r, "Too many file descriptors passed."); if (r < 0) return log_error_errno(r, "Failed to notify init system: %m"); if (r == 0) From 60e7591f33aacb1f320437b423e96beffc40090f Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 25 Apr 2025 19:58:22 +0200 Subject: [PATCH 36/48] sd-varlink: refuse accepting more than 253 fds to send along with a Varlink message 253 is the max number of fds one can send at once on a Linux AF_UNIX socket. Hence refuse to send more early. (cherry picked from commit 92c52a9ba6eea2d3bbb6289a512eeca083ec2578) (cherry picked from commit d80f2b149cb282c9a0737a6cdf847be2ee81bfeb) (cherry picked from commit 9916985d8dc9d725aa2855327a49649e405deb7d) (cherry picked from commit 27719eb872db3bbef454766cb1007eec282eabc3) --- src/shared/varlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/varlink.c b/src/shared/varlink.c index 9c27ebf2dd..6d55d67319 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -2294,8 +2294,8 @@ int varlink_push_fd(Varlink *v, int fd) { if (!v->allow_fd_passing_output) return -EPERM; - if (v->n_pushed_fds >= INT_MAX) - return -ENOMEM; + if (v->n_pushed_fds >= SCM_MAX_FD) /* Kernel doesn't support more than 253 fds per message, refuse early hence */ + return -ENOBUFS; if (!GREEDY_REALLOC(v->pushed_fds, v->n_pushed_fds + 1)) return -ENOMEM; From d569b209bac3cef1f8e3f00005dc7f14b9d00269 Mon Sep 17 00:00:00 2001 From: Tim Small Date: Sun, 27 Apr 2025 12:47:53 +0100 Subject: [PATCH 37/48] man/network: clarify SR-IOV section description and usage Document effect of the SR-IOV section in .link vs .network files and restructure the SR-IOV section introduction for clarity. (cherry picked from commit 8e24558e611e2ef66552b1da0b62b7ee1220e255) (cherry picked from commit 3a668aae1398762438b9ffee75622e552f9d7f11) (cherry picked from commit f930bd1c74cc49dacf6d99e2ec4eff550f92d0ca) (cherry picked from commit 21a05392ff349cd57b9161a9c0404c7766c0784f) --- man/systemd.link.xml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 293aba2c88..5fca6e9b76 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -977,11 +977,18 @@ [SR-IOV] Section Options - The [SR-IOV] section accepts the following keys. Specify several [SR-IOV] sections to - configure several SR-IOVs. SR-IOV provides the ability to partition a single physical PCI resource - into virtual PCI functions which can then be injected into a VM. In the case of network VFs, SR-IOV - improves north-south network performance (that is, traffic with endpoints outside the host machine) - by allowing traffic to bypass the host machine’s network stack. + SR-IOV provides the ability to partition a single physical PCI resource into virtual PCI + functions which can then be e.g. injected into a VM. In the case of network VFs, SR-IOV reduces + latency and CPU utilisation for north-south network traffic (that is, traffic with endpoints + outside the host machine), by allowing traffic to bypass the host machine’s network stack. + + + The presence of an [SR-IOV] section in a .link file will cause the creation and + configuration of the specified virtual function. Within a .network file, the specified virtual + function will be configured, but must already exist. Specify several [SR-IOV] sections to + configure several SR-IOVs. + + The [SR-IOV] section accepts the following keys. From d85eeba739e5a4f04e1c17544f465fc62fb70002 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 30 Apr 2025 15:24:20 +0100 Subject: [PATCH 38/48] busctl: validate argvs on get-property/set-property too Otherwise passing invalid data means asserts get hit instead of handling it gracefully. Other verbs already do the same checks. busctl get-property org.freedesktop.systemd1 '*' org.freedesktop.systemd1.Manager Version Assertion 'object_path_is_valid(path)' failed at src/libsystemd/sd-bus/bus-message.c:562, function sd_bus_message_new_method_call(). Aborting. Aborted (core dumped) (cherry picked from commit b16e6fd76788e74ce7424404445e822655abd6c9) (cherry picked from commit 6961d8ac6e0cc8d81c20c7de07595834ffabd556) (cherry picked from commit da7c0fc714a015dd9d7e8c1d622aa10f2f016111) (cherry picked from commit e26ba16ed64c43dd310fc9deaa86a0205eaaffc0) --- src/busctl/busctl.c | 14 ++++++++++++++ test/units/testsuite-74.busctl.sh | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/src/busctl/busctl.c b/src/busctl/busctl.c index 941b1efd44..a506836d14 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -2157,6 +2157,13 @@ static int get_property(int argc, char **argv, void *userdata) { _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; int r; + if (!service_name_is_valid(argv[1])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name: %s", argv[1]); + if (!object_path_is_valid(argv[2])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid object path: %s", argv[2]); + if (!interface_name_is_valid(argv[3])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid interface name: %s", argv[3]); + r = acquire_bus(false, &bus); if (r < 0) return r; @@ -2226,6 +2233,13 @@ static int set_property(int argc, char **argv, void *userdata) { char **p; int r; + if (!service_name_is_valid(argv[1])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid service name: %s", argv[1]); + if (!object_path_is_valid(argv[2])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid object path: %s", argv[2]); + if (!interface_name_is_valid(argv[3])) + return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid interface name: %s", argv[3]); + r = acquire_bus(false, &bus); if (r < 0) return r; diff --git a/test/units/testsuite-74.busctl.sh b/test/units/testsuite-74.busctl.sh index aaf96d08c1..b0afcd7069 100755 --- a/test/units/testsuite-74.busctl.sh +++ b/test/units/testsuite-74.busctl.sh @@ -108,3 +108,12 @@ busctl get-property -j \ # Invalid argument (! busctl set-property org.freedesktop.systemd1 /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager \ KExecWatchdogUSec t "foo") + +# Invalid destination +(! busctl get-property '*' /org/freedesktop/systemd1 org.freedesktop.systemd1.Manager Version) + +# Invalid object +(! busctl get-property org.freedesktop.systemd1 '*' org.freedesktop.systemd1.Manager Version) + +# Invalid interface +(! busctl get-property org.freedesktop.systemd1 /org/freedesktop/systemd1 '*' Version) From 5bf1457dcffb96b04b408354d1103d67b78881a7 Mon Sep 17 00:00:00 2001 From: Tim Small Date: Fri, 2 May 2025 13:40:00 +0100 Subject: [PATCH 39/48] man/network: Note .link early boot caveat, and .network .netdev usage. Document .link .network and .netdev file type distinctions in early introductory text, and document distro-specific need to sync link files with early-boot copies, see Debian bug 1005282: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=1005282 for an example. (cherry picked from commit a50fa2a40f4a91d49503d3588a3dd29ea05e559b) (cherry picked from commit 1f654739f8a05110b68461cf483d5c07b2ef7723) (cherry picked from commit 1e96e999377b03e052a0379223e40255aa767df8) (cherry picked from commit 798a835f8b4840bc7620e673b129def71dd23e2d) --- man/systemd-networkd.service.xml | 24 ++++++++++++++---------- man/systemd.link.xml | 5 +++++ man/systemd.network.xml | 8 ++++++++ 3 files changed, 27 insertions(+), 10 deletions(-) diff --git a/man/systemd-networkd.service.xml b/man/systemd-networkd.service.xml index 12cd4c331b..ed886c8aa7 100644 --- a/man/systemd-networkd.service.xml +++ b/man/systemd-networkd.service.xml @@ -33,12 +33,16 @@ manages networks. It detects and configures network devices as they appear, as well as creating virtual network devices. - To configure low-level link settings independently of - networks, see - systemd.link5. - - systemd-networkd will create network devices based - on the configuration in + Certain low-level settings of physical network devices (e.g. device + names and altnames) as well as the creation of SR-IOV virtual functions on + physical network interfaces may be managed by + systemd-udevd8 + according to the contents of + systemd.link5 + files. + + systemd-networkd will create "virtual" network + devices (e.g. bridges and tunnels) based on the configuration in systemd.netdev5 files, respecting the [Match] sections in those files. @@ -47,10 +51,10 @@ with an appropriate [Match] section, see systemd.network5. For those links, it will flush existing network addresses and routes when - bringing up the device. Any links not matched by one of the - .network files will be ignored. It is also possible to - explicitly tell systemd-networkd to ignore a link by - using Unmanaged=yes option, see + bringing up the device (except when directed not to). Any links not matched + by one of the .network files will be ignored. It is + also possible to explicitly tell systemd-networkd to + ignore a link by using the Unmanaged=yes option, see systemd.network5. diff --git a/man/systemd.link.xml b/man/systemd.link.xml index 5fca6e9b76..c81aa5b8af 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -33,6 +33,11 @@ systemd.syntax7 for a general description of the syntax. + Note that some distributions may incorporate .link files in their early boot + facilities (e.g. by including copies of the .link files in initramfs). As such it + may be necessary to take manual steps to ensure that any local changes are consistent with early-boot + storage facilities. The relevant distribution-specific documentation should be consulted. + The .link files are read from the files located in the system network directory /usr/lib/systemd/network and /usr/local/lib/systemd/network, the volatile runtime network directory diff --git a/man/systemd.network.xml b/man/systemd.network.xml index d0e52cff42..47f0921518 100644 --- a/man/systemd.network.xml +++ b/man/systemd.network.xml @@ -37,6 +37,14 @@ The main network file must have the extension .network; other extensions are ignored. Networks are applied to links whenever the links appear. + Note that not all settings and configurations can be made with .network + files, and that it may be necessary to use + systemd.link5) + or + systemd.netdev5) + files in conjuction with .network files when working with physical and virtual + network devices respectively. + The .network files are read from the files located in the system network directories /usr/lib/systemd/network and /usr/local/lib/systemd/network, the volatile runtime network directory From 0b9a8e244ac2bd73f2ee01a11bc4a8811edce830 Mon Sep 17 00:00:00 2001 From: Alexander Stepchenko Date: Mon, 5 May 2025 13:48:30 +0300 Subject: [PATCH 40/48] man/systemctl: add preposition for clarity (cherry picked from commit 0cf03a36f287ef898679868a5bc828b17faf797e) (cherry picked from commit e76121a0d2eb288ea02c61b9359b86053fd6ee5f) (cherry picked from commit a5fb520700e0501d9480336b1101578ca02e67ff) (cherry picked from commit 5f33bb32399ef6c27a4f074423e485b38c21e453) --- man/systemctl.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index d02595e70b..86a2e5f2f3 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -889,7 +889,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err preset UNIT - Reset the enable/disable status one or more unit files, as specified on + Reset the enable/disable status of one or more unit files, as specified on the command line, to the defaults configured in the preset policy files. This has the same effect as disable or enable, depending how the unit is listed in the preset From f6d2733a6f06827e02482406847a73ee7525db6b Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Fri, 2 May 2025 21:08:55 +0200 Subject: [PATCH 41/48] meson: Ensure that distribution packages own systemenvgeneratordir Currently, Fedora's systemd RPM doesn't own systemenvgeneratordir (ie., /usr/lib/systemd/system-environment-generators) [1] because it's not created when systemd is installed. In contrast, userenvgeneratordir (ie., /usr/lib/systemd/user-environment-generators) is created, unless the environment-d Meson option is explicitly disabled. While this can be worked around elsewhere, it's better if the upstream build system created the directories consistently. It will avoid repetition, and prevent silly bugs or deviations from creeping in. [1] https://bugzilla.redhat.com/show_bug.cgi?id=2284085 (cherry picked from commit ab46feb3e28eee0b9be3dece49f5e4c63f21dc37) (cherry picked from commit bd27edd3de9b3b30f7225994a799e46fba930568) (cherry picked from commit f38abc546d09f99eb011b2bfe8605ac7259baf02) (cherry picked from commit 03e38fbc877e58637a0da7d948b4c18442ed97d0) --- src/core/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/meson.build b/src/core/meson.build index 91477afc9c..43a65c01f1 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -173,9 +173,11 @@ install_data('org.freedesktop.systemd1.conf', install_data('org.freedesktop.systemd1.service', install_dir : dbussystemservicedir) +meson.add_install_script('sh', '-c', mkdir_p.format(systemenvgeneratordir)) meson.add_install_script('sh', '-c', mkdir_p.format(systemshutdowndir)) meson.add_install_script('sh', '-c', mkdir_p.format(systemsleepdir)) meson.add_install_script('sh', '-c', mkdir_p.format(systemgeneratordir)) +meson.add_install_script('sh', '-c', mkdir_p.format(userenvgeneratordir)) meson.add_install_script('sh', '-c', mkdir_p.format(usergeneratordir)) if install_sysconfdir From 8fd07e102ba0371ff1046a2def50ef89021d1b88 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 6 May 2025 16:39:14 -0600 Subject: [PATCH 42/48] flush_ports: flush POSIX message queues properly On Linux, read() on a message queue descriptor returns the message queue statistics, not the actual message queue data. We need to use mq_receive() to drain the queues instead. Fixes a problem where a POSIX message queue socket unit with messages in the queue at shutdown time could result in a hang on reboot/shutdown. (cherry picked from commit ffb6adb76367d5ab7d43937ccaac5947717b5b78) (cherry picked from commit 4ab235b029f2107ed53f6580a7b57a48b63b4035) (cherry picked from commit 5ac9982bda6429bceb64358f84f5174d4dd0a1b8) (cherry picked from commit c1581f686244313ead56b0be8aa5d3567437265d) --- src/basic/socket-util.c | 49 +++++++++++++++++++++++++++++++++++++++++ src/basic/socket-util.h | 1 + src/core/socket.c | 8 +++++-- 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/basic/socket-util.c b/src/basic/socket-util.c index 6951c12c9b..446ba95867 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -1157,6 +1158,54 @@ int flush_accept(int fd) { } } +ssize_t flush_mqueue(int fd) { + _cleanup_free_ char *buf = NULL; + struct mq_attr attr; + ssize_t count = 0; + int r; + + assert(fd >= 0); + + /* Similar to flush_fd() but flushes all messages from a POSIX message queue. */ + + for (;;) { + ssize_t l; + + r = fd_wait_for_event(fd, POLLIN, /* timeout= */ 0); + if (r < 0) { + if (r == -EINTR) + continue; + + return r; + } + if (r == 0) + return count; + + if (!buf) { + /* Buffer must be at least as large as mq_msgsize. */ + if (mq_getattr(fd, &attr) < 0) + return -errno; + + buf = malloc(attr.mq_msgsize); + if (!buf) + return -ENOMEM; + } + + l = mq_receive(fd, buf, attr.mq_msgsize, /* msg_prio = */ NULL); + if (l < 0) { + if (errno == EINTR) + continue; + + if (errno == EAGAIN) + return count; + + return -errno; + } + + count += l; + } +} + struct cmsghdr* cmsg_find(struct msghdr *mh, int level, int type, socklen_t length) { struct cmsghdr *cmsg; diff --git a/src/basic/socket-util.h b/src/basic/socket-util.h index 9c4c95bd3a..17ec943a92 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -171,6 +171,7 @@ int receive_one_fd(int transport_fd, int flags); ssize_t next_datagram_size_fd(int fd); int flush_accept(int fd); +ssize_t flush_mqueue(int fd); #define CMSG_FOREACH(cmsg, mh) \ for ((cmsg) = CMSG_FIRSTHDR(mh); (cmsg); (cmsg) = CMSG_NXTHDR((mh), (cmsg))) diff --git a/src/core/socket.c b/src/core/socket.c index 75034ac357..d18bd977b7 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2289,8 +2289,12 @@ static void flush_ports(Socket *s) { if (p->fd < 0) continue; - (void) flush_accept(p->fd); - (void) flush_fd(p->fd); + if (p->type == SOCKET_MQUEUE) + (void) flush_mqueue(p->fd); + else { + (void) flush_accept(p->fd); + (void) flush_fd(p->fd); + } } } From c9a84b7505875b23fb6d44a5990d545d1986bb85 Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Mon, 12 May 2025 15:26:32 +0200 Subject: [PATCH 43/48] log: fix declaration of log_dispatch_internal() (cherry picked from commit 0425fc5eb72d8a66e3c2634f0d61e50ef2c53e41) (cherry picked from commit 764be0a316a5a8ac1cb46aa748c12c70e23355cb) (cherry picked from commit 0c6309e8e48fd541faf9489e551787506e3ed125) (cherry picked from commit e0d06115d1a5cf4a553d05d17cc56e3eb6118dcf) --- src/basic/log.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basic/log.h b/src/basic/log.h index 76c188dcd3..115fbec302 100644 --- a/src/basic/log.h +++ b/src/basic/log.h @@ -97,8 +97,8 @@ int log_dispatch_internal( const char *func, const char *object_field, const char *object, - const char *extra, const char *extra_field, + const char *extra, char *buffer); int log_internal( From 6d74cec62c0daada98d5d2e5aa23367bb1b15b5f Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Tue, 13 May 2025 09:04:52 +0900 Subject: [PATCH 44/48] shell-completion: fix completion of `systemctl --user unset-environment` (#37409) Co-authored-by: Eisuke Kawashima (cherry picked from commit 6d07d23b022d48898d9a2e7181ab6493d3d61c43) (cherry picked from commit 11c16d414ebbcb13e39971d90ece4a1e0db183d2) (cherry picked from commit 003a0bb9e3bfef9ab99ce409ea08d6fb544440d0) (cherry picked from commit bd47958cdc0d9e9158cbf934efbf96289c631bdd) --- shell-completion/zsh/_systemctl.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell-completion/zsh/_systemctl.in b/shell-completion/zsh/_systemctl.in index 2306cbf6b0..822dd339db 100644 --- a/shell-completion/zsh/_systemctl.in +++ b/shell-completion/zsh/_systemctl.in @@ -412,7 +412,7 @@ for fun in set-environment unset-environment ; do suf='-S=' fi _wanted systemd-environment expl 'environment variable' \ - compadd "$@" ${suf} - ${${(f)"$(systemctl show-environment)"}%%=*} + compadd "$@" ${suf} - ${${(f)"$(systemctl "$_sys_service_mgr" show-environment)"}%%=*} } done From 49401f3d483b8b6991bb2d72c2b45b1cdbda8669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 May 2025 11:14:10 +0200 Subject: [PATCH 45/48] man: reword the description of "secure pager" handling The existing description was not *wrong*, but it was a bit muddled. Let's reorder the text to give a short intro and then describe what the options actually do and the clear "true" and "false" cases first, and then describe autodetection. Related to https://yeswehack.com/vulnerability-center/reports/346802. (cherry picked from commit 718dbdb2ca4458cf91711cd9a7de3a972e46658e) (cherry picked from commit d8659058f40186f07799bc2a8e624aece33412ac) (cherry picked from commit f75ad1137ef43bb7a65fd598c807945476631411) (cherry picked from commit 521215222c29ba957c7d0fe37772019443d95cf5) --- man/common-variables.xml | 58 ++++++++++++++++++++++++++-------------- 1 file changed, 38 insertions(+), 20 deletions(-) diff --git a/man/common-variables.xml b/man/common-variables.xml index 1aa31e1363..cdb02d4241 100644 --- a/man/common-variables.xml +++ b/man/common-variables.xml @@ -158,28 +158,46 @@ $SYSTEMD_PAGERSECURE - Takes a boolean argument. When true, the "secure" mode of the pager is enabled; if - false, disabled. If $SYSTEMD_PAGERSECURE is not set at all, secure mode is enabled - if the effective UID is not the same as the owner of the login session, see - geteuid2 - and sd_pid_get_owner_uid3. - In secure mode, will be set when invoking the pager, and the pager shall - disable commands that open or create new files or start new subprocesses. When - $SYSTEMD_PAGERSECURE is not set at all, pagers which are not known to implement - secure mode will not be used. (Currently only - less1 - implements secure mode.) - - Note: when commands are invoked with elevated privileges, for example under + Common pager commands like less1, in + addition to "paging", i.e. scrolling through the output, support opening of or writing to other files + and running arbitrary shell commands. When commands are invoked with elevated privileges, for example + under sudo8 or pkexec1, care - must be taken to ensure that unintended interactive features are not enabled. "Secure" mode for the - pager may be enabled automatically as describe above. Setting SYSTEMD_PAGERSECURE=0 - or not removing it from the inherited environment allows the user to invoke arbitrary commands. Note - that if the $SYSTEMD_PAGER or $PAGER variables are to be - honoured, $SYSTEMD_PAGERSECURE must be set too. It might be reasonable to completely - disable the pager using instead. + project='die-net'>pkexec1, the + pager becomes a security boundary. Care must be taken that only programs with strictly limited + functionality are used as pagers, and unintended interactive features like opening or creation of new + files or starting of subprocesses are not allowed. "Secure mode" for the pager may be enabled as + described below, if the pager supports that (most pagers are not written in a way + that takes this into consideration). It is recommended to either explicitly enable "secure mode" or to + completely disable the pager using or PAGER=cat when + allowing untrusted users to execute commands with elevated privileges. + + This option takes a boolean argument. When set to true, the "secure mode" of the pager is + enabled. In "secure mode", will be set when invoking the pager, which + instructs the pager to disable commands that open or create new files or start new subprocesses. + Currently only less1 is known + to understand this variable and implement "secure mode". + + When set to false, no limitation is placed on the pager. Setting + SYSTEMD_PAGERSECURE=0 or not removing it from the inherited environment may allow + the user to invoke arbitrary commands. + + When $SYSTEMD_PAGERSECURE is not set, systemd tools attempt to automatically + figure out if "secure mode" should be enabled and whether the pager supports it. "Secure mode" is + enabled if the effective UID is not the same as the owner of the login session, see + geteuid2 + and + sd_pid_get_owner_uid3. + In this case, SYSTEMD_PAGERSECURE=1 will be set and pagers which are not known to + implement "secure mode" will not be used at all. + + Note that if the $SYSTEMD_PAGER or $PAGER variables are to + be honoured, $SYSTEMD_PAGERSECURE must be set too. + From cabc6b155d47870eae19ec564740a2f836d54b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 May 2025 11:37:26 +0200 Subject: [PATCH 46/48] man: rework the description of $SYSTEMD_PAGER and $PAGER $PAGER wasn't documented, but actually we treat it same as $SYSTEMD_PAGER, except for lower priority. And the two variables can be used to disable the pager, even if $SYSTEMD_PAGERSECURE is not set. Behaviour is (obviously) not changed by this patch, it intentionally just updates the docs to match the code. (cherry picked from commit b6b78170e17727ca0ec320d5703b36d0597d0cc9) (cherry picked from commit affb45d6b2dfdb3a87da2e0241be8c5c5c9a9d8f) (cherry picked from commit ab19d19d3e89a270e40b9b9cff845581d3d9e3a4) (cherry picked from commit 946f7b70d5fae6caf932a8c65786366441a8114d) --- man/common-variables.xml | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/man/common-variables.xml b/man/common-variables.xml index cdb02d4241..0b13cebb14 100644 --- a/man/common-variables.xml +++ b/man/common-variables.xml @@ -91,17 +91,22 @@ $SYSTEMD_PAGER + $PAGER - Pager to use when is not given; overrides - $PAGER. If neither $SYSTEMD_PAGER nor $PAGER are set, a - set of well-known pager implementations are tried in turn, including - less1 and - more1, until one is found. If - no pager implementation is discovered no pager is invoked. Setting this environment variable to an empty string - or the value cat is equivalent to passing . + Pager to use when is not given. + $SYSTEMD_PAGER is used if set; otherwise $PAGER is used. + If neither $SYSTEMD_PAGER nor $PAGER are set, a set of well-known + pager implementations is tried in turn, including + less1 + and + more1, + until one is found. If no pager implementation is discovered, no pager is invoked. Setting those + environment variables to an empty string or the value cat is equivalent to passing + . Note: if $SYSTEMD_PAGERSECURE is not set, $SYSTEMD_PAGER - (as well as $PAGER) will be silently ignored. + and $PAGER can only be used to disable the pager (with cat or + ), and are otherwise ignored. @@ -196,8 +201,8 @@ implement "secure mode" will not be used at all. Note that if the $SYSTEMD_PAGER or $PAGER variables are to - be honoured, $SYSTEMD_PAGERSECURE must be set too. - + be honoured, other than to disable the pager, $SYSTEMD_PAGERSECURE must be set + too. From 68aebca32ca8fede3475f316d01830d75c95ef83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 May 2025 14:29:02 +0200 Subject: [PATCH 47/48] pager: also check for $SUDO_UID MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This returns to the original approach proposed in https://github.com/systemd/systemd/pull/17270. After review, the approach was changed to use sd_pid_get_owner_uid() instead. Back then, when running in a typical graphical session, sd_pid_get_owner_uid() would usually return the user UID, and when running under sudo, geteuid() would return 0, so we'd trigger the secure path. sudo may allocate a new session if is invoked outside of a session (depending on the PAM config). Since nowadays desktop environments usually start the user shell through user units, the typical shell in a terminal emulator is not part of a session, and when sudo is invoked, a new session is allocated, and sd_pid_get_owner_uid() returns 0 too. Technically, the code still works as documented in the man page, but in the common case, it doesn't do the expected thing. $ build/test-sd-login |& rg 'get_(owner_uid|cgroup|session)' sd_pid_get_session(0) → No data available sd_pid_get_owner_uid(0) → 1000 sd_pid_get_cgroup(0) → /user.slice/user-1000.slice/user@1000.service/app.slice/app-ghostty-transient-5088.scope/surfaces/556FAF50BA40.scope $ sudo build/test-sd-login |& rg 'get_(owner_uid|cgroup|session)' sd_pid_get_session(0) → c289 sd_pid_get_owner_uid(0) → 0 sd_pid_get_cgroup(0) → /user.slice/user-0.slice/session-c289.scope I think it's worth checking for sudo because it is a common case used by users. There obviously are other mechanims, so the man page is extended to say that only some common mechanisms are supported, and to (again) recommend setting SYSTEMD_LESSSECURE explicitly. The other option would be to set "secure mode" by default. But this would create an inconvenience for users doing the right thing, running systemctl and other tools directly, because then they can't run privileged commands from the pager, e.g. to save the output to a file. (Or the user would need to explicitly set SYSTEMD_LESSSECURE. One option would be to set it always in the environment and to rely on sudo and other tools stripping it from the environment before running privileged code. But that is also fairly fragile and it obviously relies on the user doing a complicated setup to support a fairly common use case. I think this decreases usability of the system quite a bit. I don't think we should build solutions that work in priniciple, but are painfully inconvenient in common cases.) Fixes https://yeswehack.com/vulnerability-center/reports/346802. Also see https://github.com/polkit-org/polkit/pull/562, which adds support for $SUDO_UID/$SUDO_GID to pkexec. (cherry picked from commit cd93478af8b9dc69478d5667f113b67d175090fa) (cherry picked from commit b93f53c122124582fa80ae246343791063d65074) (cherry picked from commit f3a13eca4ed6b4852153179a2197ee797bbbe898) (cherry picked from commit df9bf670237083bdd434766f1fa61000dbbf7164) --- man/common-variables.xml | 13 ++++++++++--- src/shared/pager.c | 29 +++++++++++++++++++---------- 2 files changed, 29 insertions(+), 13 deletions(-) diff --git a/man/common-variables.xml b/man/common-variables.xml index 0b13cebb14..37930781ab 100644 --- a/man/common-variables.xml +++ b/man/common-variables.xml @@ -196,9 +196,16 @@ enabled if the effective UID is not the same as the owner of the login session, see geteuid2 and - sd_pid_get_owner_uid3. - In this case, SYSTEMD_PAGERSECURE=1 will be set and pagers which are not known to - implement "secure mode" will not be used at all. + sd_pid_get_owner_uid3, + or when running under + sudo8 or similar + tools ($SUDO_UID is set + It is recommended for other tools to set and check $SUDO_UID as appropriate, + treating it is a common interface.). In those cases, + SYSTEMD_PAGERSECURE=1 will be set and pagers which are not known to implement + "secure mode" will not be used at all. Note that this autodetection only covers the most common + mechanisms to elevate privileges and is intended as convenience. It is recommended to explicitly set + $SYSTEMD_PAGERSECURE or disable the pager. Note that if the $SYSTEMD_PAGER or $PAGER variables are to be honoured, other than to disable the pager, $SYSTEMD_PAGERSECURE must be set diff --git a/src/shared/pager.c b/src/shared/pager.c index 7bede85752..23ff961b32 100644 --- a/src/shared/pager.c +++ b/src/shared/pager.c @@ -82,6 +82,22 @@ static int no_quit_on_interrupt(int exe_name_fd, const char *less_opts) { return r; } +static bool running_with_escalated_privileges(void) { + int r; + + if (getenv("SUDO_UID")) + return true; + + uid_t uid; + r = sd_pid_get_owner_uid(0, &uid); + if (r < 0) { + log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); + return true; + } + + return uid != geteuid(); +} + void pager_open(PagerFlags flags) { _cleanup_close_pair_ int fd[2] = PIPE_EBADF, exe_name_pipe[2] = PIPE_EBADF; _cleanup_strv_free_ char **pager_args = NULL; @@ -177,16 +193,9 @@ void pager_open(PagerFlags flags) { * know to be good. */ int use_secure_mode = getenv_bool_secure("SYSTEMD_PAGERSECURE"); bool trust_pager = use_secure_mode >= 0; - if (use_secure_mode == -ENXIO) { - uid_t uid; - - r = sd_pid_get_owner_uid(0, &uid); - if (r < 0) - log_debug_errno(r, "sd_pid_get_owner_uid() failed, enabling pager secure mode: %m"); - - use_secure_mode = r < 0 || uid != geteuid(); - - } else if (use_secure_mode < 0) { + if (use_secure_mode == -ENXIO) + use_secure_mode = running_with_escalated_privileges(); + else if (use_secure_mode < 0) { log_warning_errno(use_secure_mode, "Unable to parse $SYSTEMD_PAGERSECURE, assuming true: %m"); use_secure_mode = true; } From 95aacac36550b47d3621ed7fdd410f65c94d462e Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sun, 18 May 2025 13:28:02 +0100 Subject: [PATCH 48/48] CI: undo mkosi.yml overwrite of systemd tools from main The tools from main are no longer compatible with images built in this stable branch. Ubuntu 24.04 ships with v255 which is good enough, so restore those binaries. (cherry picked from commit 92df356fe184fb5ddbe0b1276555271001c196db) --- .github/workflows/mkosi.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/mkosi.yml b/.github/workflows/mkosi.yml index bb6e1cecde..5c53cb8f4a 100644 --- a/.github/workflows/mkosi.yml +++ b/.github/workflows/mkosi.yml @@ -82,6 +82,9 @@ jobs: - name: Configure run: | + # mkosi GHA clones and builds from main but tools are not compatible with this branch, 24.04 ships 255 which is enough + sudo apt install --reinstall systemd systemd-container systemd-boot systemd-ukify + tee mkosi.conf <<- EOF [Distribution] Distribution=${{ matrix.distro }} @@ -138,8 +141,6 @@ jobs: ExecStart=false EOF cp mkosi.presets/10-initrd/mkosi.extra/usr/lib/systemd/system/emergency.service.d/poweroff.conf mkosi.presets/20-final/mkosi.extra/usr/lib/systemd/system/emergency.service.d/poweroff.conf - sudo ln -svf "$(dirname "$(readlink /usr/bin/bootctl)")/systemd-keyutil" /usr/lib/systemd/systemd-keyutil - /usr/lib/systemd/systemd-keyutil --version - name: Generate secure boot key run: sudo mkosi --debug genkey