From fb7f2c9b781924bd0c457909a020615511ae828c Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 8 Mar 2025 20:04:17 +0100 Subject: [PATCH 01/61] core/main: log about save_env() error (cherry picked from commit eda75b2cb27f171130191d1613c04c9d5e929efd) (cherry picked from commit 551aee593050ef9219466db05e8d7ba195d19f9b) (cherry picked from commit cc0ef08a48e0cf775c45d0f88c6be7b4fa30cb14) --- 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 8373a156cb..8d88432e01 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2788,7 +2788,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 680b2d78cf9054d6e64b7e87f9c25694aa85bf33 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 5 Mar 2025 18:22:19 +0100 Subject: [PATCH 02/61] 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) --- 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 8d88432e01..35c78273ab 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2902,7 +2902,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; } @@ -2977,7 +2978,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 70decf5779fb23ed273f48c8f945db415ed874a9 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Sat, 8 Mar 2025 20:09:58 +0100 Subject: [PATCH 03/61] core/main: preemptively check existence of init only if we're switching root Follow-up for aaa27e2e21c04339914f26b7125789087eb51166 The commit described about system potentially becoming undebuggable after switching into broken root or whatnot. But notably we can never activate emergency.target after do_reexecute() failure, since the Manager has been destructed. Plus, for a normal reexecution the fallback shell logic triggered on non-existent /sbin/init is kinda useful. Let's hence guard the extra check behind switch-root. Also, move the check below /run/nextroot/ detection. (cherry picked from commit 93e19483dc9fae94d713d036ecee669450bd002d) (cherry picked from commit 1df135924796cf6790ec3f7848527349a5b760cc) (cherry picked from commit ce4495819fbb3ef0bc4df87e9acd7c5e62e82874) --- src/core/main.c | 71 +++++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 32 deletions(-) diff --git a/src/core/main.c b/src/core/main.c index 35c78273ab..8a9721293c 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -1798,37 +1798,10 @@ static int do_reexecute( assert(saved_rlimit_memlock); assert(ret_error_message); - if (switch_root_init) { - r = chase(switch_root_init, switch_root_dir, CHASE_PREFIX_ROOT, NULL, NULL); - if (r < 0) - log_warning_errno(r, "Failed to chase configured init %s/%s: %m", - strempty(switch_root_dir), switch_root_init); - } else { - r = chase(SYSTEMD_BINARY_PATH, switch_root_dir, CHASE_PREFIX_ROOT, NULL, NULL); - if (r < 0) - log_debug_errno(r, "Failed to chase our own binary %s/%s: %m", - strempty(switch_root_dir), SYSTEMD_BINARY_PATH); - } - - if (r < 0) { - r = chase("/sbin/init", switch_root_dir, CHASE_PREFIX_ROOT, NULL, NULL); - if (r < 0) - return log_error_errno(r, "Failed to chase %s/sbin/init", strempty(switch_root_dir)); - } - /* Close and disarm the watchdog, so that the new instance can reinitialize it, but doesn't get * rebooted while we do that */ watchdog_close(true); - /* Reset RLIMIT_NOFILE + RLIMIT_MEMLOCK back to the kernel defaults, so that the new systemd can pass - * the kernel default to its child processes */ - if (saved_rlimit_nofile->rlim_cur != 0) - (void) setrlimit(RLIMIT_NOFILE, saved_rlimit_nofile); - if (saved_rlimit_memlock->rlim_cur != RLIM_INFINITY) - (void) setrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock); - - finish_remaining_processes(objective); - if (!switch_root_dir && objective == MANAGER_SOFT_REBOOT) { /* If no switch root dir is specified, then check if /run/nextroot/ qualifies and use that */ r = path_is_os_tree("/run/nextroot"); @@ -1838,6 +1811,39 @@ static int do_reexecute( switch_root_dir = "/run/nextroot"; } + if (switch_root_dir) { + /* If we're supposed to switch root, preemptively check the existence of a usable init. + * Otherwise the system might end up in a completely undebuggable state afterwards. */ + if (switch_root_init) { + r = chase_and_access(switch_root_init, switch_root_dir, CHASE_PREFIX_ROOT, X_OK, /* ret_path = */ NULL); + if (r < 0) + log_warning_errno(r, "Failed to chase configured init %s/%s: %m", + switch_root_dir, switch_root_init); + } else { + r = chase_and_access(SYSTEMD_BINARY_PATH, switch_root_dir, CHASE_PREFIX_ROOT, X_OK, /* ret_path = */ NULL); + if (r < 0) + log_debug_errno(r, "Failed to chase our own binary %s/%s: %m", + switch_root_dir, SYSTEMD_BINARY_PATH); + } + + if (r < 0) { + r = chase_and_access("/sbin/init", switch_root_dir, CHASE_PREFIX_ROOT, X_OK, /* ret_path = */ NULL); + if (r < 0) { + *ret_error_message = "Switch root target contains no usable init"; + return log_error_errno(r, "Failed to chase %s/sbin/init", switch_root_dir); + } + } + } + + /* Reset RLIMIT_NOFILE + RLIMIT_MEMLOCK back to the kernel defaults, so that the new systemd can pass + * the kernel default to its child processes */ + if (saved_rlimit_nofile->rlim_cur != 0) + (void) setrlimit(RLIMIT_NOFILE, saved_rlimit_nofile); + if (saved_rlimit_memlock->rlim_cur != RLIM_INFINITY) + (void) setrlimit(RLIMIT_MEMLOCK, saved_rlimit_memlock); + + finish_remaining_processes(objective); + if (switch_root_dir) { r = switch_root(/* new_root= */ switch_root_dir, /* old_root_after= */ NULL, @@ -1929,16 +1935,17 @@ static int do_reexecute( ANSI_HIGHLIGHT_RED " !! " ANSI_NORMAL, "Failed to execute /sbin/init"); - *ret_error_message = "Failed to execute fallback shell"; if (r == -ENOENT) { - log_warning("No /sbin/init, trying fallback"); + log_warning_errno(r, "No /sbin/init, trying fallback shell"); args[0] = "/bin/sh"; args[1] = NULL; (void) execve(args[0], (char* const*) args, saved_env); - return log_error_errno(errno, "Failed to execute /bin/sh, giving up: %m"); - } else - return log_error_errno(r, "Failed to execute /sbin/init, giving up: %m"); + r = -errno; + } + + *ret_error_message = "Failed to execute fallback shell"; + return log_error_errno(r, "Failed to execute /bin/sh, giving up: %m"); } static int invoke_main_loop( From 34898e9c5c5d344c5214dfce72bf35e72770b20f Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Wed, 5 Mar 2025 18:35:50 +0100 Subject: [PATCH 04/61] 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) --- 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 8a9721293c..364dc895d1 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -2031,7 +2031,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; @@ -2054,7 +2054,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); @@ -2074,7 +2074,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 0fa0eea02c6d0c1faea931859f396c8b01597fef Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Mon, 10 Mar 2025 12:21:26 +0100 Subject: [PATCH 05/61] 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) --- 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 1a9b99d761..08067067af 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 b979c0743678c09f09032ac6bef4486451f8bd48 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Mar 2025 11:43:46 +0100 Subject: [PATCH 06/61] 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) --- 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 5cac0e2b06..a678952432 100644 --- a/src/core/core-varlink.c +++ b/src/core/core-varlink.c @@ -506,7 +506,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 3874586ebd..447515e346 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -320,7 +320,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) @@ -1008,7 +1008,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) @@ -1090,7 +1090,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); @@ -1922,11 +1921,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 80aaf29570104648126643cb001262da0b34f2ee Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 12 Mar 2025 18:19:34 +0100 Subject: [PATCH 07/61] 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) --- src/core/manager.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/core/manager.c b/src/core/manager.c index 447515e346..9448cde372 100644 --- a/src/core/manager.c +++ b/src/core/manager.c @@ -1845,6 +1845,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 e0dfa23d564ca12842d55aa731a29e57c211df42 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 13 Mar 2025 11:49:13 +0100 Subject: [PATCH 08/61] 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) --- 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 6fc383ca1b..ab5aaf79db 100644 --- a/src/test/test-execute.c +++ b/src/test/test-execute.c @@ -1373,9 +1373,10 @@ static void run_tests(RuntimeScope scope, char **patterns) { start = now(CLOCK_MONOTONIC); 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); finish = now(CLOCK_MONOTONIC); From 23088523512dee01fb9201d4972d4ddd25d9b25e Mon Sep 17 00:00:00 2001 From: Franck Bui Date: Wed, 12 Mar 2025 17:51:39 +0100 Subject: [PATCH 09/61] 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) --- 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 7486118365..6267fd7c08 100644 --- a/src/getty-generator/getty-generator.c +++ b/src/getty-generator/getty-generator.c @@ -271,17 +271,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 7be89c8e68cd910da8c6ce49671bfa29bc885654 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 14 Mar 2025 11:43:07 +0100 Subject: [PATCH 10/61] 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) --- 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 532bb02d2d131509e514b029b2a8856b0eb523ff Mon Sep 17 00:00:00 2001 From: Daan De Meyer Date: Mon, 17 Mar 2025 12:28:37 +0100 Subject: [PATCH 11/61] 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) --- 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 8befc97460..b32cd6c6a0 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 e66658a1f7d96937aa81f1eb1ba36418c373cf96 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 19 Mar 2025 01:32:12 +0900 Subject: [PATCH 12/61] 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) --- 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 737e1736a684b5b4a4f93e3d76821733c30bc645 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 19 Mar 2025 01:33:09 +0900 Subject: [PATCH 13/61] sd-varlink: fix overwrite of loop count Fixes a bug introduced by 206504a594492f4b97259bbe345dde4e520df7dc (v255). (cherry picked from commit a65d2de6d163daae715aa2a05869dbe65d2a0f01) (cherry picked from commit 201f94c154163ce6de61172de1353989974fad38) (cherry picked from commit c2f159b406bd4ef4fa31930aedbf3eba5be3bf0f) --- src/shared/varlink.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/shared/varlink.c b/src/shared/varlink.c index d3373266bc..b8a861f5aa 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -3221,7 +3221,7 @@ int varlink_server_listen_address(VarlinkServer *s, const char *address, mode_t int varlink_server_listen_auto(VarlinkServer *s) { _cleanup_strv_free_ char **names = NULL; - int r, n = 0; + int r, m, n = 0; assert_return(s, -EINVAL); @@ -3231,11 +3231,11 @@ int varlink_server_listen_auto(VarlinkServer *s) { * See https://varlink.org/#activation for the environment variables this is backed by and the * recommended "varlink" identifier in $LISTEN_FDNAMES. */ - r = sd_listen_fds_with_names(/* unset_environment= */ false, &names); - if (r < 0) - return r; + m = sd_listen_fds_with_names(/* unset_environment= */ false, &names); + if (m < 0) + return m; - for (int i = 0; i < r; i++) { + for (int i = 0; i < m; i++) { int b, fd; socklen_t l = sizeof(b); From 4c29b9b9679bd5af3d46ca37916fd5712a8d8a64 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Wed, 19 Mar 2025 16:54:27 +0100 Subject: [PATCH 14/61] 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) --- 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 61539afdbf..d398655b0a 100644 --- a/src/core/cgroup.c +++ b/src/core/cgroup.c @@ -52,6 +52,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 cgroup_tasks_max_resolve(const CGroupTasksMax *tasks_max) { if (tasks_max->scale == 0) return tasks_max->value; @@ -2674,6 +2676,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. */ } } @@ -2682,8 +2688,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 5efe6b5cd05effc63961f6fccfe18260a268180b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Thu, 13 Mar 2025 12:11:40 +0900 Subject: [PATCH 15/61] 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) --- 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 a53997e9c3d539b1b1292d68eb772c15e58b7bd3 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Mar 2025 17:38:26 +0100 Subject: [PATCH 16/61] core: fix C type handler for ExitCode property (cherry picked from commit 0b0cb6f33d0c1256e8cc2b77ab361b55ac911105) (cherry picked from commit aba08e3edb180b620e5152cdbc2bd8922adc8680) (cherry picked from commit 6300dc3179a9f5657b755e38e2ddc96d9499a4dc) --- 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 12d54351f8..c7372ca033 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -3016,7 +3016,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, defaults.timer_accuracy_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStartUSec", "t", bus_property_get_usec, offsetof(Manager, defaults.timeout_start_usec), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("DefaultTimeoutStopUSec", "t", bus_property_get_usec, offsetof(Manager, defaults.timeout_stop_usec), SD_BUS_VTABLE_PROPERTY_CONST), From 3c725b923d11d7754be29e486d9f455790cb20de Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 21 Mar 2025 17:51:18 +0100 Subject: [PATCH 17/61] 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) --- 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 2d05ba7e1d..71b07a6ec1 100644 --- a/src/core/dbus-execute.c +++ b/src/core/dbus-execute.c @@ -942,6 +942,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), @@ -1019,8 +1036,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 06a6a67605ba4c703fd3a64fe4638ab76b8e2e88 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 24 Mar 2025 20:43:53 +0900 Subject: [PATCH 18/61] man/timedatectl: add reference to systemd.time(7) Closes #36839. (cherry picked from commit dadaad157edda8d9a659c04c60cbc1c603c1c586) (cherry picked from commit 1c56f9ec438944ff46d1e3849b30d6ad6cbba237) (cherry picked from commit db50b5e50ed1e9fa1b70daafd23f1ce2538c5696) --- man/timedatectl.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/man/timedatectl.xml b/man/timedatectl.xml index f06441bfbe..df9719cb23 100644 --- a/man/timedatectl.xml +++ b/man/timedatectl.xml @@ -78,10 +78,10 @@ set-time [TIME] - Set the system clock to the specified time. - This will also update the RTC time accordingly. The time may - be specified in the format "2012-10-30 - 18:17:16". + Set the system clock to the specified timestamp. This will also update the RTC time + accordingly. The timestamp may be specified in the format 2012-10-30 18:17:16. See + systemd.time7 + for more details about acceptable timestamp format. From 77d20e19ad6bf24608d5109ce810f1aafcbfc5b9 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 24 Mar 2025 18:25:29 +0000 Subject: [PATCH 19/61] man: fix typo in org.freedesktop.systemd1.xml (cherry picked from commit b065ff03b1e9a6409d0e4fec10e3b802cc067e8b) (cherry picked from commit 694aa0115d77e41dbda80891d8a4b766313adfae) (cherry picked from commit 00e48cb057cff5caa84ba532e67004faa25310fe) --- 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 e1aee5a6a1..19bf7a4d60 100644 --- a/man/org.freedesktop.systemd1.xml +++ b/man/org.freedesktop.systemd1.xml @@ -8658,7 +8658,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 cd3e41d9ff324f1697c2b9893d2bada81a55f458 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 20/61] man/systemd-remount-fs: fix grammar (cherry picked from commit 7a468f277b217b8bf25fca89706364afa99e376c) (cherry picked from commit 2a35f220477ca655d1f49f119348e3f216405d54) (cherry picked from commit 47315320d5e165437eb63570c22557c72e09079b) --- 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 ff50506f8306ae0f0987de96e418c041b8990524 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 21/61] 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) --- 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 1c019b26d8..edbd2dcb6a 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 81cb18e06e6a178012662d706962bf269294eaf2 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 31 Mar 2025 11:51:38 +0200 Subject: [PATCH 22/61] homed: don't log error we don't have (cherry picked from commit 521b6bb1177b534db6cab28c889e6550680517c4) (cherry picked from commit 03605d767ffcd446da876a97de967d4d8b56272c) (cherry picked from commit 92d03c858c59b94d13049ff04da2135c1f22c4dd) --- 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 e37660a61b..4f3bfee063 100644 --- a/src/home/homed-manager.c +++ b/src/home/homed-manager.c @@ -555,7 +555,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 2e192c64aacf628fc3581b836c9c434d1c19bc30 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 1 Apr 2025 15:39:37 +0900 Subject: [PATCH 23/61] udev: update log messages (cherry picked from commit 6941bf6b7736f1151862ac36e70c846e3ce0398a) (cherry picked from commit 287ebf79ce6f13f0ee19baefd84be029d6e64315) (cherry picked from commit 85c0915904cdf7408429d132f6d1c3eccc0c2671) --- src/udev/udev-manager.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index 8077e51055..a1cbab5b99 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -302,7 +302,7 @@ static void manager_reload(Manager *manager, bool force) { static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userdata) { Manager *manager = ASSERT_PTR(userdata); - log_debug("Cleanup idle workers"); + log_debug("Cleaning up idle workers."); manager_kill_workers(manager, false); return 1; @@ -1154,7 +1154,7 @@ static int on_post(sd_event_source *s, void *userdata) { if (errno != ENOENT) log_warning_errno(errno, "Failed to unlink /run/udev/queue, ignoring: %m"); } else - log_debug("No events are queued, removing /run/udev/queue."); + log_debug("No events are queued, removed /run/udev/queue."); if (!hashmap_isempty(manager->workers)) { /* There are idle workers */ From e7cf9768e61311860cb98589057fdf59c0452145 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 31 Mar 2025 15:44:11 +0100 Subject: [PATCH 24/61] test: pass verbose option to nvme-cli When the test fails due to nvme-cli/kernel issues it's hard to report it upstream as there's not enough details, add verbose flags (cherry picked from commit ebc0514a6507d51e536b269e30a036a7992beeb7) (cherry picked from commit b87f618a30cb664326d2211d8dd7b30a442318b4) (cherry picked from commit 3747d200cc187a3365ef8b875b7f45cf6a5023d5) --- test/units/testsuite-84.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/units/testsuite-84.sh b/test/units/testsuite-84.sh index c5cb898902..89de113186 100755 --- a/test/units/testsuite-84.sh +++ b/test/units/testsuite-84.sh @@ -22,7 +22,7 @@ NVME_UUID="$(cat /proc/sys/kernel/random/uuid)" systemd-run -u teststoragetm.service -p Type=notify -p "Environment=SYSTEMD_NVME_UUID=${NVME_UUID:?}" /usr/lib/systemd/systemd-storagetm /var/tmp/storagetm.test --nqn=quux NVME_DEVICE="/dev/disk/by-id/nvme-uuid.${NVME_UUID:?}" -nvme connect-all -t tcp -a 127.0.0.1 -s 16858 --hostid="$(cat /proc/sys/kernel/random/uuid)" +nvme connect-all -vv -t tcp -a 127.0.0.1 -s 16858 --hostid="$(cat /proc/sys/kernel/random/uuid)" udevadm wait --settle "$NVME_DEVICE" dd if="$NVME_DEVICE" bs=1024 | cmp /var/tmp/storagetm.test - From c9a3ac2cf413577ff60b96f0e7b0b55c1221192b Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 1 Apr 2025 19:00:50 +0900 Subject: [PATCH 25/61] test: replace deprecated --hostid= with --hostnqn= Fixes #36908. (cherry picked from commit c70a113a6c2b02f667498c8385bedd1a873edb2c) (cherry picked from commit c4eeb99c2192e9318566d045af985712dfd3d02c) (cherry picked from commit 38f3c44762f67f633494c0a134968a22f2745e99) --- test/units/testsuite-84.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/units/testsuite-84.sh b/test/units/testsuite-84.sh index 89de113186..ddc107560e 100755 --- a/test/units/testsuite-84.sh +++ b/test/units/testsuite-84.sh @@ -22,7 +22,7 @@ NVME_UUID="$(cat /proc/sys/kernel/random/uuid)" systemd-run -u teststoragetm.service -p Type=notify -p "Environment=SYSTEMD_NVME_UUID=${NVME_UUID:?}" /usr/lib/systemd/systemd-storagetm /var/tmp/storagetm.test --nqn=quux NVME_DEVICE="/dev/disk/by-id/nvme-uuid.${NVME_UUID:?}" -nvme connect-all -vv -t tcp -a 127.0.0.1 -s 16858 --hostid="$(cat /proc/sys/kernel/random/uuid)" +nvme connect-all -vv -t tcp -a 127.0.0.1 -s 16858 --hostnqn="$(nvme gen-hostnqn)" udevadm wait --settle "$NVME_DEVICE" dd if="$NVME_DEVICE" bs=1024 | cmp /var/tmp/storagetm.test - From 8b0d9eac26b21c7b787e475c3768d33b95dfdb3a Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 29 Mar 2025 17:55:45 +0000 Subject: [PATCH 26/61] 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) --- 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 86d602d615..3307462608 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 ed008e5866e40df487c13a7548ed2f186556ea3c Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sat, 29 Mar 2025 17:56:04 +0000 Subject: [PATCH 27/61] 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) --- 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 bf49a6da68..62be9895ac 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 9e5fd06526..ba3af61f5e 100755 --- a/test/test-network/systemd-networkd-tests.py +++ b/test/test-network/systemd-networkd-tests.py @@ -6977,6 +6977,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 75ecac8a40d3053eb4bfd2240cd7fa9b2cfd5907 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 28/61] 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) --- 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 bce99b5518..a5212a804e 100644 --- a/src/libsystemd/sd-device/test-sd-device.c +++ b/src/libsystemd/sd-device/test-sd-device.c @@ -451,6 +451,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); @@ -468,6 +470,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); @@ -496,6 +501,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); @@ -529,6 +536,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 9356469e929c66752dfa4b0b052d9349585fea9c Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Tue, 8 Apr 2025 16:43:28 +0200 Subject: [PATCH 29/61] core/exec-invoke: never override acquired user cred with fallback one (cherry picked from commit 2fb438cc88826399f39305765a7881cbf63b5e49) (cherry picked from commit a9b4a0f3a56ffaa96d0e9824446bf15588ed6ff0) (cherry picked from commit f50eca199f37d87c27a18cc91d3059eb7b46ef6f) --- src/core/exec-invoke.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/exec-invoke.c b/src/core/exec-invoke.c index 22bc8d10c1..9d27280ed0 100644 --- a/src/core/exec-invoke.c +++ b/src/core/exec-invoke.c @@ -1900,7 +1900,9 @@ static int build_environment( * could cause problem for e.g. getty, since login doesn't override $HOME, and $LOGNAME and $SHELL don't * really make much sense since we're not logged in. Hence we conditionalize the three based on * SetLoginEnvironment= switch. */ - if (!c->user && !c->dynamic_user && p->runtime_scope == RUNTIME_SCOPE_SYSTEM) { + if (!username && !c->dynamic_user && p->runtime_scope == RUNTIME_SCOPE_SYSTEM) { + assert(!c->user); + r = get_fixed_user("root", &username, NULL, NULL, &home, &shell); if (r < 0) return log_exec_debug_errno(c, From f7c3a73cc799b394388f1fb6048f5034f3a09449 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 7 Apr 2025 20:55:41 +0100 Subject: [PATCH 30/61] 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) --- 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 3307462608..6829e598d7 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 a20f1f243706b053c3fb0d8310ba0818ce119bb8 Mon Sep 17 00:00:00 2001 From: Mike Yuan Date: Fri, 26 Jan 2024 00:47:23 +0800 Subject: [PATCH 31/61] 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) --- src/fstab-generator/fstab-generator.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/fstab-generator/fstab-generator.c b/src/fstab-generator/fstab-generator.c index 016f3baa7f..d373e2e59c 100644 --- a/src/fstab-generator/fstab-generator.c +++ b/src/fstab-generator/fstab-generator.c @@ -476,17 +476,13 @@ 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; - - opts = strdup(options); - if (!opts) - return -ENOMEM; + r = strdup_or_null(options, ret_options); + if (r < 0) + return r; - *ret_options = TAKE_PTR(opts); return 0; } @@ -522,7 +518,6 @@ static int add_mount( assert(what); assert(where); - assert(opts); assert(target_unit); assert(source); @@ -816,6 +811,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")) @@ -891,7 +889,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 549191209c6001248f224a4f28b0d92389d347c8 Mon Sep 17 00:00:00 2001 From: Jules Lamur Date: Mon, 7 Apr 2025 18:49:26 +0200 Subject: [PATCH 32/61] 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) --- 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 d373e2e59c..e7caf510ba 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 19d64697865e7dba20986b4631ed1ae33b349dd9 Mon Sep 17 00:00:00 2001 From: kmeaw Date: Sun, 30 Mar 2025 13:08:38 +0100 Subject: [PATCH 33/61] 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) --- 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 039080f052..d811de13de 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 934388d5f9740edbbf026bc4e561556bfe386502 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 Apr 2025 09:11:05 +0900 Subject: [PATCH 34/61] locale-util: fix argument for munmap() (cherry picked from commit 90abb64fd508e8efd937178b3379a62ac97b49ec) (cherry picked from commit 445b4931807089bb7c7b12a8b09f3a580f63f643) (cherry picked from commit 7aba5ce344592df9bb59c36695a35fcab580df34) --- 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 d3fef01feb..833cc18340 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 83f371eb759c8d66ffdfcae18f3c5fa48d738a52 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Thu, 17 Apr 2025 14:39:34 +0200 Subject: [PATCH 35/61] 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) --- 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..eafdc4341e 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_NEG_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 fe38ad9bd27f4fc53c6e214c0c8b3f8835d8d2eb Mon Sep 17 00:00:00 2001 From: Alexander Kurtz Date: Sun, 20 Apr 2025 10:31:22 +0200 Subject: [PATCH 36/61] docs/MEMORY_PRESSURE: Replace incorrect "packages" with correct "pages" (cherry picked from commit e8939ebcd376da4ab90f8840e8eaa4db5bd83210) (cherry picked from commit 8acffbf0abfcaa4de82a81e62d0acee7b896f122) (cherry picked from commit acb447f2c389a6cf0d2cd454e43b89498a174c8c) --- 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 20aee7cd73f1ec5c8d5fd1b0607be73df68a99d2 Mon Sep 17 00:00:00 2001 From: igo95862 Date: Sun, 20 Apr 2025 16:14:23 +0100 Subject: [PATCH 37/61] 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) --- 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 7444e1249c..10c1af165d 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 4723dfb4d829ee5339ea31ab7907d75d4685b816 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 21 Apr 2025 05:30:09 +0900 Subject: [PATCH 38/61] 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) --- man/systemctl.xml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 9d212e17e3..8e94288664 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -163,10 +163,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 da4e0ceb42f2353e26e751da0617a3394031674e Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 21 Apr 2025 10:50:57 +0900 Subject: [PATCH 39/61] 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) --- man/systemd.xml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/man/systemd.xml b/man/systemd.xml index 229ef0aa32..4205c09dd1 100644 --- a/man/systemd.xml +++ b/man/systemd.xml @@ -1055,12 +1055,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 dbb276189d49f4dcc02b6e89a45f97ec8e6a125a Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 22 Apr 2025 09:24:39 +0900 Subject: [PATCH 40/61] 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) --- 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 b9177cfac86ded90af8410a222f0b1ddde04e642 Mon Sep 17 00:00:00 2001 From: Jesper Nilsson Date: Sat, 26 Apr 2025 17:39:56 +0200 Subject: [PATCH 41/61] 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) --- 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 df2cbc6fba..bf0d089ef9 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 294d7411aceeb68b7ff659cbc256ebbc1ca93473 Mon Sep 17 00:00:00 2001 From: David Rheinsberg Date: Mon, 28 Apr 2025 13:13:10 +0200 Subject: [PATCH 42/61] basic/time-util: fix error handling of clock_nanosleep() `clock_nanosleep()` returns error codes directly, rather than using `errno`. Ensure that we use those codes, rather than checking for `<0`. (cherry picked from commit 81660754981ce66d194df9f1773edd22840f3daa) (cherry picked from commit b61ef0b632991b6083c1bb19a014f4925629d8f7) (cherry picked from commit 2629f2a4928725135432510735bb9f9f71cf3df2) --- src/basic/time-util.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basic/time-util.h b/src/basic/time-util.h index ed4c1aabd4..14f8e904a8 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -219,8 +219,8 @@ static inline int usleep_safe(usec_t usec) { * ⚠️ Note we are not using plain nanosleep() here, since that operates on CLOCK_REALTIME, not * CLOCK_MONOTONIC! */ - // FIXME: use RET_NERRNO() macro here. Currently, this header cannot include errno-util.h. - return clock_nanosleep(CLOCK_MONOTONIC, 0, TIMESPEC_STORE(usec), NULL) < 0 ? -errno : 0; + /* `clock_nanosleep()` does not use `errno`, but returns positive error codes. */ + return -clock_nanosleep(CLOCK_MONOTONIC, 0, TIMESPEC_STORE(usec), NULL); } /* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit From d48c841eb7821e5594b4291534acc8b016ea1103 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Mon, 4 Nov 2024 11:18:29 +0100 Subject: [PATCH 43/61] 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) --- 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 aa07599fd8..0afd30a23c 100644 --- a/man/sd_notify.xml +++ b/man/sd_notify.xml @@ -466,6 +466,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 b69a7c7224..fa3ef7ba9b 100644 --- a/src/libsystemd/sd-daemon/sd-daemon.c +++ b/src/libsystemd/sd-daemon/sd-daemon.c @@ -476,6 +476,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 aa5f3abe965d57414df244cac8ad8bb0f52622fb Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Fri, 25 Apr 2025 19:58:22 +0200 Subject: [PATCH 44/61] 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) --- 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 b8a861f5aa..8a99a6c3f1 100644 --- a/src/shared/varlink.c +++ b/src/shared/varlink.c @@ -2732,8 +2732,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 591409e16b01336a9b0079d1888d3e55c09f7295 Mon Sep 17 00:00:00 2001 From: Tim Small Date: Sun, 27 Apr 2025 12:47:53 +0100 Subject: [PATCH 45/61] 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) --- 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 063f8e3566..dc2377c2b8 100644 --- a/man/systemd.link.xml +++ b/man/systemd.link.xml @@ -1155,11 +1155,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 dbabd0de82662a495568f63f41a3ec0a45b492e3 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Wed, 30 Apr 2025 15:24:20 +0100 Subject: [PATCH 46/61] 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) --- 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 01cb896a44..794ef45f36 100644 --- a/src/busctl/busctl.c +++ b/src/busctl/busctl.c @@ -2161,6 +2161,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; @@ -2230,6 +2237,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 3a8b529ef71bb50dafdfe0ce2382295ae42a374e Mon Sep 17 00:00:00 2001 From: Tim Small Date: Fri, 2 May 2025 13:40:00 +0100 Subject: [PATCH 47/61] 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) --- 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 dc2377c2b8..30f69bee6c 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 7b72a1eba1..b529988635 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 19528bab387e7bc294da38e4feb9850c31774a14 Mon Sep 17 00:00:00 2001 From: Alexander Stepchenko Date: Mon, 5 May 2025 13:48:30 +0300 Subject: [PATCH 48/61] man/systemctl: add preposition for clarity (cherry picked from commit 0cf03a36f287ef898679868a5bc828b17faf797e) (cherry picked from commit e76121a0d2eb288ea02c61b9359b86053fd6ee5f) (cherry picked from commit a5fb520700e0501d9480336b1101578ca02e67ff) --- man/systemctl.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 8e94288664..dac8dd4644 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -938,7 +938,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 e1496eb24c82759b997ceed5f458f1a73818bf17 Mon Sep 17 00:00:00 2001 From: Debarshi Ray Date: Fri, 2 May 2025 21:08:55 +0200 Subject: [PATCH 49/61] 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) --- src/core/meson.build | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/core/meson.build b/src/core/meson.build index 439a88c5b2..cc47ae056a 100644 --- a/src/core/meson.build +++ b/src/core/meson.build @@ -246,9 +246,11 @@ install_data('org.freedesktop.systemd1.conf', install_data('org.freedesktop.systemd1.service', install_dir : dbussystemservicedir) +install_emptydir(systemenvgeneratordir) install_emptydir(systemshutdowndir) install_emptydir(systemsleepdir) install_emptydir(systemgeneratordir) +install_emptydir(userenvgeneratordir) install_emptydir(usergeneratordir) if install_sysconfdir From 3c9a4be8e36a4cf517a5327dc7a5735b84a87201 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 May 2025 21:04:00 +0200 Subject: [PATCH 50/61] man/systemd.exec: reword description of SystemCallFilter= The existing text grew organically as features were added and was not very organized. Reorder it and break into paragraphs grouped by topic. The description of the :errno syntax is replaced by a short reference to the SystemCallErrorNumber= setting. This makes the text shorter and makes it easier to explain how the two settings combine. (cherry picked from commit 802d23fcfbcacd3c33f421e0fb1bd372658beeef) (cherry picked from commit 0ff20b0486f39579c3296ff51c4f09515889a9f2) (cherry picked from commit 7e3a6097931f7e16e9d1c743fc34b4e0e4234d86) --- man/systemd.exec.xml | 66 +++++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 32 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index b75626f1d8..327a883633 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -2424,40 +2424,42 @@ RestrictNamespaces=~cgroup net SystemCallFilter= - Takes a space-separated list of system call names. If this setting is used, all - system calls executed by the unit processes except for the listed ones will result in immediate - process termination with the SIGSYS signal (allow-listing). (See - SystemCallErrorNumber= below for changing the default action). If the first - character of the list is ~, the effect is inverted: only the listed system calls - will result in immediate process termination (deny-listing). Deny-listed system calls and system call - groups may optionally be suffixed with a colon (:) and errno - error number (between 0 and 4095) or errno name such as EPERM, - EACCES or EUCLEAN (see errno3 for a - full list). This value will be returned when a deny-listed system call is triggered, instead of - terminating the processes immediately. Special setting kill can be used to - explicitly specify killing. This value takes precedence over the one given in - SystemCallErrorNumber=, see below. This feature makes use of the Secure Computing Mode 2 - interfaces of the kernel ('seccomp filtering') and is useful for enforcing a minimal sandboxing environment. - Note that the execve(), exit(), exit_group(), - getrlimit(), rt_sigreturn(), sigreturn() - system calls and the system calls for querying time and sleeping are implicitly allow-listed and do not - need to be listed explicitly. This option may be specified more than once, in which case the filter masks are + Takes a space-separated list of system call names or system call groups. If this + setting is used, system calls executed by the unit processes except for the listed ones will result + in the system call being denied (allow-listing). If the first character of the list is + ~, the effect is inverted: only the listed system calls will be denied + (deny-listing). This option may be specified more than once, in which case the filter masks are merged. If the empty string is assigned, the filter is reset, all prior assignments will have no - effect. This does not affect commands prefixed with +. - - Note that on systems supporting multiple ABIs (such as x86/x86-64) it is recommended to turn off - alternative ABIs for services, so that they cannot be used to circumvent the restrictions of this + effect. + + Commands prefixed with + are not subject to filtering. The + execve(), exit(), exit_group(), + getrlimit(), rt_sigreturn(), + sigreturn() system calls and the system calls for querying time and sleeping are + implicitly allow-listed and do not need to be listed explicitly. + + The default action when a system call is denied is to terminate the processes with a + SIGSYS signal. This can changed using SystemCallErrorNumber=, + see below. In addition, deny-listed system calls and system call groups may optionally be suffixed + with a colon (:) and an argument in the same format as + SystemCallErrorNumber=, to take this action when the matching system call is made. + This takes precedence over the action specified in SystemCallErrorNumber=. + + This feature makes use of the Secure Computing Mode 2 interfaces of the kernel ('seccomp + filtering') and is useful for enforcing a minimal sandboxing environment. + + Note that on systems supporting multiple ABIs (such as x86/x86-64) it is recommended to turn + off alternative ABIs for services, so that they cannot be used to circumvent the restrictions of this option. Specifically, it is recommended to combine this option with SystemCallArchitectures=native or similar. - Note that strict system call filters may impact execution and error handling code paths of the service - invocation. Specifically, access to the execve() system call is required for the execution - of the service binary — if it is blocked service invocation will necessarily fail. Also, if execution of the - service binary fails for some reason (for example: missing service executable), the error handling logic might - require access to an additional set of system calls in order to process and log this failure correctly. It - might be necessary to temporarily disable system call filters in order to simplify debugging of such - failures. + Note that strict system call filters may impact execution and error handling code paths of the + service invocation. Specifically, access to the execve() system call is required + for the execution of the service binary — if it is blocked service invocation will necessarily fail. + Also, if execution of the service binary fails for some reason (for example: missing service + executable), the error handling logic might require access to an additional set of system calls in + order to process and log this failure correctly. It might be necessary to temporarily disable system + call filters in order to allow debugging of such failures. If you specify both types of this option (i.e. allow-listing and deny-listing), the first encountered will take precedence and will dictate the default action (termination or approval of a @@ -2467,8 +2469,8 @@ RestrictNamespaces=~cgroup net write(), and right after it add a deny list rule for write(), then write() will be removed from the set.) - As the number of possible system calls is large, predefined sets of system calls are provided. A set - starts with @ character, followed by name of the set. + As the number of possible system calls is large, predefined groups of system calls are + provided. A group starts with @ character, followed by name of the set. Currently predefined system call sets From 1c21e05d17082ce1da6cace084a3e1f14735f485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= Date: Tue, 6 May 2025 20:59:59 +0200 Subject: [PATCH 51/61] man/systemd.exec: reword description of RestrictAddressFamilies= The text is reordered and broken into more paragraphs. A recommendation to combine RestrictAddressFamilies= with SystemCallFilter=@service is added. (cherry picked from commit 2dc4e87849e2ae2ea93e9ccf6365c44ad1602ac6) (cherry picked from commit 523197c2432b265275a3ec9ff76aa7f617e07eb7) (cherry picked from commit 5692ca2f5fdd51ff32bb27df0867cf3fde4c84bd) --- man/systemd.exec.xml | 44 ++++++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 18 deletions(-) diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml index 327a883633..7971951514 100644 --- a/man/systemd.exec.xml +++ b/man/systemd.exec.xml @@ -2094,28 +2094,36 @@ BindReadOnlyPaths=/var/lib/systemd allow-list, such as AF_UNIX, AF_INET or AF_INET6. When none is specified, then all address families will be denied. When prefixed with ~ the listed address - families will be applied as deny list, otherwise as allow list. Note that this restricts access - to the - socket2 + families will be applied as deny list, otherwise as allow list. + + By default, no restrictions apply, all address families are accessible to processes. If + assigned the empty string, any previous address family restriction changes are undone. This setting + does not affect commands prefixed with +. + + Use this option to limit exposure of processes to remote access, in particular via exotic and + sensitive network protocols, such as AF_PACKET. Note that in most cases, the + local AF_UNIX address family should be included in the configured allow list as + it is frequently used for local communication, including for + syslog2 + logging. + + Note that this restricts access to the socket2 system call only. Sockets passed into the process by other means (for example, by using socket activation with socket units, see systemd.socket5) are unaffected. Also, sockets created with socketpair() (which creates connected - AF_UNIX sockets only) are unaffected. Note that this option has no effect on 32-bit x86, s390, s390x, - mips, mips-le, ppc, ppc-le, ppc64, ppc64-le and is ignored (but works correctly on other ABIs, - including x86-64). Note that on systems supporting multiple ABIs (such as x86/x86-64) it is - recommended to turn off alternative ABIs for services, so that they cannot be used to circumvent the - restrictions of this option. Specifically, it is recommended to combine this option with - SystemCallArchitectures=native or similar. By default, no restrictions apply, all - address families are accessible to processes. If assigned the empty string, any previous address family - restriction changes are undone. This setting does not affect commands prefixed with +. - - Use this option to limit exposure of processes to remote access, in particular via exotic and sensitive - network protocols, such as AF_PACKET. Note that in most cases, the local - AF_UNIX address family should be included in the configured allow list as it is frequently - used for local communication, including for - syslog2 - logging. + AF_UNIX sockets) or the + io_uring7 + functions, are not affected. Thus, it is recommended to combined this setting with + SystemCallFilter=@service, to only allow a limited subset of system calls. + + Note that this option is limited to some ABIs, in particular x86-64, but currently has no + effect on 32-bit x86, s390, s390x, mips, mips-le, ppc, ppc-le, ppc64, or ppc64-le, and is ignored. On + systems supporting multiple ABIs (such as x86/x86-64) it is recommended to turn off alternative ABIs + for services, so that they cannot be used to circumvent the restrictions of this option. + Specifically, it is recommended to combine this option with + SystemCallArchitectures=native or similar. From 1272e7f2571055e07a5b75e18521d222503c4c40 Mon Sep 17 00:00:00 2001 From: "Todd C. Miller" Date: Tue, 6 May 2025 16:39:14 -0600 Subject: [PATCH 52/61] 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) --- 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 beb64d8e6c..ad75b3708b 100644 --- a/src/basic/socket-util.c +++ b/src/basic/socket-util.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -1281,6 +1282,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 9a11df834d..b3f2e3641a 100644 --- a/src/basic/socket-util.h +++ b/src/basic/socket-util.h @@ -195,6 +195,7 @@ int receive_many_fds(int transport_fd, int **ret_fds_array, size_t *ret_n_fds_ar 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 9adae16b00..23bc8ceb71 100644 --- a/src/core/socket.c +++ b/src/core/socket.c @@ -2269,8 +2269,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 2af207a1e21e822df3ce8c6ff0c2b705df608141 Mon Sep 17 00:00:00 2001 From: Antonio Alvarez Feijoo Date: Mon, 12 May 2025 15:26:32 +0200 Subject: [PATCH 53/61] log: fix declaration of log_dispatch_internal() (cherry picked from commit 0425fc5eb72d8a66e3c2634f0d61e50ef2c53e41) (cherry picked from commit 764be0a316a5a8ac1cb46aa748c12c70e23355cb) (cherry picked from commit 0c6309e8e48fd541faf9489e551787506e3ed125) --- 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 c3d8fb60cef7cf86dced2767822f4ff3ea4845f4 Mon Sep 17 00:00:00 2001 From: Eisuke Kawashima Date: Tue, 13 May 2025 09:04:52 +0900 Subject: [PATCH 54/61] 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) --- 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 54e34a1781..2924dd229d 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 c6c219b9ed5b79fc33cab53f6c227bcd0376b527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Behrmann?= Date: Tue, 13 May 2025 17:19:02 +0200 Subject: [PATCH 55/61] man: add missing fdstore in systemctl clean --what documentation (cherry picked from commit 5689365a909362d82ad4959d3fec9ebacfd5ec96) (cherry picked from commit cca8e2077f982e5cf636137a92eb7f177a0b4a29) (cherry picked from commit ae2226ba0d62f9e3132a75639d96211680b337c2) --- man/systemctl.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index dac8dd4644..6570d6c026 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -554,7 +554,7 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err clean PATTERN - Remove the configuration, state, cache, logs or runtime data of the specified units. Use + Remove the configuration, state, cache, logs, runtime or file descriptor store data of the specified units. Use to select which kind of resource to remove. For service units this may be used to remove the directories configured with ConfigurationDirectory=, StateDirectory=, CacheDirectory=, From 2d8cdb3fddc0747c8fd4aa651f6a4950d2d21e8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Behrmann?= Date: Tue, 13 May 2025 17:20:37 +0200 Subject: [PATCH 56/61] man: note for systemctl clean --what that commas separate values (cherry picked from commit 652e4dd7434d1603866c059aa8a67eaf8b73346f) (cherry picked from commit 2d5982e4f2c76e41fa1d5524fcbcdfcbecdf656c) (cherry picked from commit f768adde986f08372be45648d90a972f2d0b6b89) --- man/systemctl.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/man/systemctl.xml b/man/systemctl.xml index 6570d6c026..cedd3f9b63 100644 --- a/man/systemctl.xml +++ b/man/systemctl.xml @@ -569,7 +569,8 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err command only applies to units that use either of these settings. If is not specified, the cache and runtime data as well as the file descriptor store are removed (as these three types of resources are generally redundant and reproducible on the next invocation of - the unit). Note that the specified units must be stopped to invoke this operation. + the unit). Multiple values can be seperated by commas. Note that the specified units must be stopped + to invoke this operation. From 283754dfe8d997d04ab45f25e540e0f1be12dd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Behrmann?= Date: Tue, 13 May 2025 17:21:02 +0200 Subject: [PATCH 57/61] systemct: show all in output of systemctl clean --what=help (cherry picked from commit 68b6289a9e4a8a9cc3567f066f921388e99da9d9) (cherry picked from commit f9e68aa2b5dd14e0be29d13ea0c45f50bfe6b986) (cherry picked from commit bf275c73ee0e4293d710b90d467f693eb7d3581b) --- src/systemctl/systemctl.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/systemctl/systemctl.c b/src/systemctl/systemctl.c index dd6f6c9873..ddd20510c1 100644 --- a/src/systemctl/systemctl.c +++ b/src/systemctl/systemctl.c @@ -945,7 +945,8 @@ static int systemctl_parse_argv(int argc, char *argv[]) { "cache\n" "logs\n" "configuration\n" - "fdstore"); + "fdstore\n" + "all"); return 0; } From 65ad04c98088e91d13069b2c3927a90fdf26283a 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 58/61] 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) --- 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 92b660f02d5c4bc6bd9ec60fcb8572e8f0cf83ef 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 59/61] 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) --- 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 842f10c1a9c293a76b4495a06841de1c0891f163 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 60/61] 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) --- 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 19deefab56..41dd7bffdc 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] = EBADF_PAIR, exe_name_pipe[2] = EBADF_PAIR; _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 cf0b30035b245a93f5cb03722bf2628e915eae54 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Sun, 18 May 2025 13:28:02 +0100 Subject: [PATCH 61/61] 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. --- .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 c490854211..f3dba76158 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.local.conf <<- EOF [Distribution] Distribution=${{ matrix.distro }} @@ -128,8 +131,6 @@ jobs: ExecStart=false EOF cp mkosi.images/initrd/mkosi.extra/usr/lib/systemd/system/emergency.service.d/poweroff.conf mkosi.images/system/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: mkosi --debug genkey