From 9b3774f03624b9889be2b36f8067ccf551179c03 Mon Sep 17 00:00:00 2001 From: CentOS Sources Date: Aug 29 2022 14:39:07 +0000 Subject: import systemd-239-67.el8 --- diff --git a/SOURCES/0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch b/SOURCES/0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch new file mode 100644 index 0000000..bea238f --- /dev/null +++ b/SOURCES/0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch @@ -0,0 +1,292 @@ +From c7532112a37ffdd3cc9851ae04fdcb543b99ed1c Mon Sep 17 00:00:00 2001 +From: Hubert Kario +Date: Sun, 20 Sep 2020 18:59:58 +0200 +Subject: [PATCH] Try stopping MD RAID devices in shutdown too + +Currently the systemd-shutdown command attempts to stop swaps, DM +(crypt, LVM2) and loop devices, but it doesn't attempt to stop MD +RAID devices, which means that if the RAID is set up on crypt, +loop, etc. device, it won't be able to stop those underlying devices. + +This code extends the shutdown application to also attempt stopping +the MD RAID devices. + +Signed-off-by: Hubert Kario +(cherry picked from commit 0b220a5f2a31844eaa1f5426bab02d41d54f471c) + +Resolves: #1817706 +--- + src/core/shutdown.c | 37 +++++++++---- + src/core/umount.c | 125 ++++++++++++++++++++++++++++++++++++++++++++ + src/core/umount.h | 2 + + 3 files changed, 154 insertions(+), 10 deletions(-) + +diff --git a/src/core/shutdown.c b/src/core/shutdown.c +index 038345b752..b8a983986a 100644 +--- a/src/core/shutdown.c ++++ b/src/core/shutdown.c +@@ -251,7 +251,7 @@ static void sync_with_progress(void) { + } + + int main(int argc, char *argv[]) { +- bool need_umount, need_swapoff, need_loop_detach, need_dm_detach; ++ bool need_umount, need_swapoff, need_loop_detach, need_dm_detach, need_md_detach; + bool in_container, use_watchdog = false, can_initrd; + _cleanup_free_ char *cgroup = NULL; + char *arguments[3]; +@@ -331,6 +331,7 @@ int main(int argc, char *argv[]) { + need_swapoff = !in_container; + need_loop_detach = !in_container; + need_dm_detach = !in_container; ++ need_md_detach = !in_container; + can_initrd = !in_container && !in_initrd() && access("/run/initramfs/shutdown", X_OK) == 0; + + /* Unmount all mountpoints, swaps, and loopback devices */ +@@ -383,6 +384,18 @@ int main(int argc, char *argv[]) { + log_error_errno(r, "Failed to detach loop devices: %m"); + } + ++ if (need_md_detach) { ++ log_info("Stopping MD devices."); ++ r = md_detach_all(&changed, umount_log_level); ++ if (r == 0) { ++ need_md_detach = false; ++ log_info("All MD devices stopped."); ++ } else if (r > 0) ++ log_info("Not all MD devices stopped, %d left.", r); ++ else ++ log_error_errno(r, "Failed to stop MD devices: %m"); ++ } ++ + if (need_dm_detach) { + log_info("Detaching DM devices."); + r = dm_detach_all(&changed, umount_log_level); +@@ -395,8 +408,9 @@ int main(int argc, char *argv[]) { + log_error_errno(r, "Failed to detach DM devices: %m"); + } + +- if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach) { +- log_info("All filesystems, swaps, loop devices and DM devices detached."); ++ if (!need_umount && !need_swapoff && !need_loop_detach && !need_dm_detach ++ && !need_md_detach) { ++ log_info("All filesystems, swaps, loop devices, MD devices and DM devices detached."); + /* Yay, done */ + break; + } +@@ -414,19 +428,21 @@ int main(int argc, char *argv[]) { + /* If in this iteration we didn't manage to + * unmount/deactivate anything, we simply give up */ + if (!changed) { +- log_info("Cannot finalize remaining%s%s%s%s continuing.", ++ log_info("Cannot finalize remaining%s%s%s%s%s continuing.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", +- need_dm_detach ? " DM devices," : ""); ++ need_dm_detach ? " DM devices," : "", ++ need_md_detach ? " MD devices," : ""); + break; + } + +- log_debug("Couldn't finalize remaining %s%s%s%s trying again.", ++ log_debug("Couldn't finalize remaining %s%s%s%s%s trying again.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", +- need_dm_detach ? " DM devices," : ""); ++ need_dm_detach ? " DM devices," : "", ++ need_md_detach ? " MD devices," : ""); + } + + /* We're done with the watchdog. */ +@@ -455,12 +471,13 @@ int main(int argc, char *argv[]) { + + } + +- if (need_umount || need_swapoff || need_loop_detach || need_dm_detach) +- log_error("Failed to finalize %s%s%s%s ignoring", ++ if (need_umount || need_swapoff || need_loop_detach || need_dm_detach || need_md_detach) ++ log_error("Failed to finalize%s%s%s%s%s ignoring.", + need_umount ? " file systems," : "", + need_swapoff ? " swap devices," : "", + need_loop_detach ? " loop devices," : "", +- need_dm_detach ? " DM devices," : ""); ++ need_dm_detach ? " DM devices," : "", ++ need_md_detach ? " MD devices," : ""); + + /* The kernel will automatically flush ATA disks and suchlike on reboot(), but the file systems need to be + * sync'ed explicitly in advance. So let's do this here, but not needlessly slow down containers. Note that we +diff --git a/src/core/umount.c b/src/core/umount.c +index 3f02bf141a..ed90c6b1fc 100644 +--- a/src/core/umount.c ++++ b/src/core/umount.c +@@ -5,6 +5,8 @@ + + #include + #include ++#include ++#include + #include + #include + #include +@@ -332,6 +334,66 @@ static int dm_list_get(MountPoint **head) { + return 0; + } + ++static int md_list_get(MountPoint **head) { ++ _cleanup_(udev_enumerate_unrefp) struct udev_enumerate *e = NULL; ++ struct udev_list_entry *item = NULL, *first = NULL; ++ _cleanup_(udev_unrefp) struct udev *udev = NULL; ++ int r; ++ ++ assert(head); ++ ++ udev = udev_new(); ++ if (!udev) ++ return -ENOMEM; ++ ++ e = udev_enumerate_new(udev); ++ if (!e) ++ return -ENOMEM; ++ ++ r = udev_enumerate_add_match_subsystem(e, "block"); ++ if (r < 0) ++ return r; ++ ++ r = udev_enumerate_add_match_sysname(e, "md*"); ++ if (r < 0) ++ return r; ++ ++ first = udev_enumerate_get_list_entry(e); ++ udev_list_entry_foreach(item, first) { ++ _cleanup_(udev_device_unrefp) struct udev_device *d; ++ _cleanup_free_ char *p = NULL; ++ const char *dn; ++ MountPoint *m; ++ dev_t devnum; ++ ++ d = udev_device_new_from_syspath(udev, udev_list_entry_get_name(item)); ++ if (!d) ++ return -ENOMEM; ++ ++ devnum = udev_device_get_devnum(d); ++ dn = udev_device_get_devnode(d); ++ if (major(devnum) == 0 || !dn) ++ continue; ++ ++ p = strdup(dn); ++ if (!p) ++ return -ENOMEM; ++ ++ m = new(MountPoint, 1); ++ if (!m) ++ return -ENOMEM; ++ ++ *m = (MountPoint) { ++ .path = TAKE_PTR(p), ++ .devnum = devnum, ++ }; ++ ++ LIST_PREPEND(mount_point, *head, m); ++ } ++ ++ return 0; ++} ++ + static int delete_loopback(const char *device) { + _cleanup_close_ int fd = -1; + int r; +@@ -379,6 +441,23 @@ static int delete_dm(dev_t devnum) { + return 0; + } + ++static int delete_md(MountPoint *m) { ++ ++ _cleanup_close_ int fd = -1; ++ ++ assert(major(m->devnum) != 0); ++ assert(m->path != 0); ++ ++ fd = open(m->path, O_RDONLY|O_CLOEXEC|O_EXCL); ++ if (fd < 0) ++ return -errno; ++ ++ if (ioctl(fd, STOP_ARRAY, NULL) < 0) ++ return -errno; ++ ++ return 0; ++} ++ + static bool nonunmountable_path(const char *path) { + return path_equal(path, "/") + #if ! HAVE_SPLIT_USR +@@ -618,6 +697,37 @@ static int dm_points_list_detach(MountPoint **head, bool *changed, int umount_lo + return n_failed; + } + ++static int md_points_list_detach(MountPoint **head, bool *changed, int umount_log_level) { ++ MountPoint *m, *n; ++ int n_failed = 0, r; ++ dev_t rootdev = 0; ++ ++ assert(head); ++ assert(changed); ++ ++ (void) get_block_device("/", &rootdev); ++ ++ LIST_FOREACH_SAFE(mount_point, m, n, *head) { ++ if (major(rootdev) != 0 && rootdev == m->devnum) { ++ n_failed ++; ++ continue; ++ } ++ ++ log_info("Stopping MD %s (%u:%u).", m->path, major(m->devnum), minor(m->devnum)); ++ r = delete_md(m); ++ if (r < 0) { ++ log_full_errno(umount_log_level, r, "Could not stop MD %s: %m", m->path); ++ n_failed++; ++ continue; ++ } ++ ++ *changed = true; ++ mount_point_free(head, m); ++ } ++ ++ return n_failed; ++} ++ + static int umount_all_once(bool *changed, int umount_log_level) { + int r; + _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, mp_list_head); +@@ -696,3 +806,18 @@ int dm_detach_all(bool *changed, int umount_log_level) { + + return dm_points_list_detach(&dm_list_head, changed, umount_log_level); + } ++ ++int md_detach_all(bool *changed, int umount_log_level) { ++ _cleanup_(mount_points_list_free) LIST_HEAD(MountPoint, md_list_head); ++ int r; ++ ++ assert(changed); ++ ++ LIST_HEAD_INIT(md_list_head); ++ ++ r = md_list_get(&md_list_head); ++ if (r < 0) ++ return r; ++ ++ return md_points_list_detach(&md_list_head, changed, umount_log_level); ++} +diff --git a/src/core/umount.h b/src/core/umount.h +index 6f2b24d195..b01062484f 100644 +--- a/src/core/umount.h ++++ b/src/core/umount.h +@@ -15,6 +15,8 @@ int loopback_detach_all(bool *changed, int umount_log_level); + + int dm_detach_all(bool *changed, int umount_log_level); + ++int md_detach_all(bool *changed, int umount_log_level); ++ + /* This is exported just for testing */ + typedef struct MountPoint { + char *path; diff --git a/SOURCES/0822-shutdown-get-only-active-md-arrays.patch b/SOURCES/0822-shutdown-get-only-active-md-arrays.patch new file mode 100644 index 0000000..9bd3ce2 --- /dev/null +++ b/SOURCES/0822-shutdown-get-only-active-md-arrays.patch @@ -0,0 +1,70 @@ +From ebb3e759bba99ea85b3be9608258d6a5bb7e907a Mon Sep 17 00:00:00 2001 +From: Mariusz Tkaczyk +Date: Tue, 29 Mar 2022 12:49:54 +0200 +Subject: [PATCH] shutdown: get only active md arrays. + +Current md_list_get() implementation filters all block devices, started from +"md*". This is ambiguous because list could contain: +- partitions created upon md device (mdXpY) +- external metadata container- specific type of md array. + +For partitions there is no issue, because they aren't handle STOP_ARRAY +ioctl sent later. It generates misleading errors only. + +Second case is more problematic because containers are not locked in kernel. +They are stopped even if container member array is active. For that reason +reboot or shutdown flow could be blocked because metadata manager cannot be +restarted after switch root on shutdown. + +Add filters to remove partitions and containers from md_list. Partitions +can be excluded by DEVTYPE. Containers are determined by MD_LEVEL +property, we are excluding all with "container" value. + +Signed-off-by: Mariusz Tkaczyk +(cherry picked from commit 3a3b022d2cc112803ea7b9beea98bbcad110368a) + +Related: #1817706 +--- + src/core/umount.c | 18 +++++++++++++++++- + 1 file changed, 17 insertions(+), 1 deletion(-) + +diff --git a/src/core/umount.c b/src/core/umount.c +index ed90c6b1fc..b513e91c4d 100644 +--- a/src/core/umount.c ++++ b/src/core/umount.c +@@ -358,11 +358,16 @@ static int md_list_get(MountPoint **head) { + if (r < 0) + return r; + ++ /* Filter out partitions. */ ++ r = udev_enumerate_add_match_property(e, "DEVTYPE", "disk"); ++ if (r < 0) ++ return r; ++ + first = udev_enumerate_get_list_entry(e); + udev_list_entry_foreach(item, first) { + _cleanup_(udev_device_unrefp) struct udev_device *d; + _cleanup_free_ char *p = NULL; +- const char *dn; ++ const char *dn, *md_level; + MountPoint *m; + dev_t devnum; + +@@ -375,6 +380,17 @@ static int md_list_get(MountPoint **head) { + if (major(devnum) == 0 || !dn) + continue; + ++ md_level = udev_device_get_property_value(d, "MD_LEVEL"); ++ if (!m) { ++ log_warning("Failed to get MD_LEVEL property for %s, ignoring", dn); ++ continue; ++ } ++ ++ /* MD "containers" are a special type of MD devices, used for external metadata. ++ * Since it doesn't provide RAID functionality in itself we don't need to stop it. */ ++ if (streq(md_level, "container")) ++ continue; ++ + p = strdup(dn); + if (!p) + return -ENOMEM; diff --git a/SOURCES/0823-scope-allow-unprivileged-delegation-on-scopes.patch b/SOURCES/0823-scope-allow-unprivileged-delegation-on-scopes.patch new file mode 100644 index 0000000..a62f3bc --- /dev/null +++ b/SOURCES/0823-scope-allow-unprivileged-delegation-on-scopes.patch @@ -0,0 +1,347 @@ +From 5b5571de21d1ddf9a00511a6b2f25d630a903f05 Mon Sep 17 00:00:00 2001 +From: Michal Sekletar +Date: Wed, 1 Jun 2022 10:15:06 +0200 +Subject: [PATCH] scope: allow unprivileged delegation on scopes + +Previously it was possible to set delegate property for scope, but you +were not able to allow unprivileged process to manage the scope's cgroup +hierarchy. This is useful when launching manager process that will run +unprivileged but is supposed to manage its own (scope) sub-hierarchy. + +Fixes #21683 + +(cherry picked from commit 03860190fefce8bbea3a6f0e77919b882ade517c) + +Resolves: #2068575 +--- + src/basic/unit-def.c | 1 + + src/basic/unit-def.h | 1 + + src/core/dbus-scope.c | 6 ++ + src/core/scope.c | 135 +++++++++++++++++++++++++---- + src/core/scope.h | 3 + + src/shared/bus-unit-util.c | 5 ++ + test/TEST-19-DELEGATE/testsuite.sh | 13 +++ + 7 files changed, 145 insertions(+), 19 deletions(-) + +diff --git a/src/basic/unit-def.c b/src/basic/unit-def.c +index e79cc73dd3..16c4d38d41 100644 +--- a/src/basic/unit-def.c ++++ b/src/basic/unit-def.c +@@ -160,6 +160,7 @@ DEFINE_STRING_TABLE_LOOKUP(path_state, PathState); + + static const char* const scope_state_table[_SCOPE_STATE_MAX] = { + [SCOPE_DEAD] = "dead", ++ [SCOPE_START_CHOWN] = "start-chown", + [SCOPE_RUNNING] = "running", + [SCOPE_ABANDONED] = "abandoned", + [SCOPE_STOP_SIGTERM] = "stop-sigterm", +diff --git a/src/basic/unit-def.h b/src/basic/unit-def.h +index 8eea379a6d..03d151ec19 100644 +--- a/src/basic/unit-def.h ++++ b/src/basic/unit-def.h +@@ -99,6 +99,7 @@ typedef enum PathState { + + typedef enum ScopeState { + SCOPE_DEAD, ++ SCOPE_START_CHOWN, + SCOPE_RUNNING, + SCOPE_ABANDONED, + SCOPE_STOP_SIGTERM, +diff --git a/src/core/dbus-scope.c b/src/core/dbus-scope.c +index 0bbf64fff1..534302d188 100644 +--- a/src/core/dbus-scope.c ++++ b/src/core/dbus-scope.c +@@ -178,6 +178,12 @@ int bus_scope_set_property( + r = bus_kill_context_set_transient_property(u, &s->kill_context, name, message, flags, error); + if (r != 0) + return r; ++ ++ if (streq(name, "User")) ++ return bus_set_transient_user_relaxed(u, name, &s->user, message, flags, error); ++ ++ if (streq(name, "Group")) ++ return bus_set_transient_user_relaxed(u, name, &s->group, message, flags, error); + } + + return 0; +diff --git a/src/core/scope.c b/src/core/scope.c +index 5a595c65a6..9cc5f89099 100644 +--- a/src/core/scope.c ++++ b/src/core/scope.c +@@ -5,6 +5,8 @@ + + #include "alloc-util.h" + #include "dbus-scope.h" ++#include "dbus-unit.h" ++#include "exit-status.h" + #include "load-dropin.h" + #include "log.h" + #include "scope.h" +@@ -14,9 +16,11 @@ + #include "strv.h" + #include "unit-name.h" + #include "unit.h" ++#include "user-util.h" + + static const UnitActiveState state_translation_table[_SCOPE_STATE_MAX] = { + [SCOPE_DEAD] = UNIT_INACTIVE, ++ [SCOPE_START_CHOWN] = UNIT_ACTIVATING, + [SCOPE_RUNNING] = UNIT_ACTIVE, + [SCOPE_ABANDONED] = UNIT_ACTIVE, + [SCOPE_STOP_SIGTERM] = UNIT_DEACTIVATING, +@@ -34,6 +38,7 @@ static void scope_init(Unit *u) { + + s->timeout_stop_usec = u->manager->default_timeout_stop_usec; + u->ignore_on_isolate = true; ++ s->user = s->group = NULL; + } + + static void scope_done(Unit *u) { +@@ -45,6 +50,9 @@ static void scope_done(Unit *u) { + s->controller_track = sd_bus_track_unref(s->controller_track); + + s->timer_event_source = sd_event_source_unref(s->timer_event_source); ++ ++ s->user = mfree(s->user); ++ s->group = mfree(s->group); + } + + static int scope_arm_timer(Scope *s, usec_t usec) { +@@ -84,7 +92,7 @@ static void scope_set_state(Scope *s, ScopeState state) { + old_state = s->state; + s->state = state; + +- if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) ++ if (!IN_SET(state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL, SCOPE_START_CHOWN)) + s->timer_event_source = sd_event_source_unref(s->timer_event_source); + + if (IN_SET(state, SCOPE_DEAD, SCOPE_FAILED)) { +@@ -301,26 +309,72 @@ fail: + scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); + } + +-static int scope_start(Unit *u) { +- Scope *s = SCOPE(u); ++static int scope_enter_start_chown(Scope *s) { ++ Unit *u = UNIT(s); ++ pid_t pid; + int r; + + assert(s); ++ assert(s->user); + +- if (unit_has_name(u, SPECIAL_INIT_SCOPE)) +- return -EPERM; ++ r = scope_arm_timer(s, usec_add(now(CLOCK_MONOTONIC), u->manager->default_timeout_start_usec)); ++ if (r < 0) ++ return r; + +- if (s->state == SCOPE_FAILED) +- return -EPERM; ++ r = unit_fork_helper_process(u, "(sd-chown-cgroup)", &pid); ++ if (r < 0) ++ goto fail; + +- /* We can't fulfill this right now, please try again later */ +- if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) +- return -EAGAIN; ++ if (r == 0) { ++ uid_t uid = UID_INVALID; ++ gid_t gid = GID_INVALID; + +- assert(s->state == SCOPE_DEAD); ++ if (!isempty(s->user)) { ++ const char *user = s->user; + +- if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) +- return -ENOENT; ++ r = get_user_creds(&user, &uid, &gid, NULL, NULL); ++ if (r < 0) { ++ log_unit_error_errno(UNIT(s), r, "Failed to resolve user \"%s\": %m", user); ++ _exit(EXIT_USER); ++ } ++ } ++ ++ if (!isempty(s->group)) { ++ const char *group = s->group; ++ ++ r = get_group_creds(&group, &gid); ++ if (r < 0) { ++ log_unit_error_errno(UNIT(s), r, "Failed to resolve group \"%s\": %m", group); ++ _exit(EXIT_GROUP); ++ } ++ } ++ ++ r = cg_set_access(SYSTEMD_CGROUP_CONTROLLER, u->cgroup_path, uid, gid); ++ if (r < 0) { ++ log_unit_error_errno(UNIT(s), r, "Failed to adjust control group access: %m"); ++ _exit(EXIT_CGROUP); ++ } ++ ++ _exit(EXIT_SUCCESS); ++ } ++ ++ r = unit_watch_pid(UNIT(s), pid, true); ++ if (r < 0) ++ goto fail; ++ ++ scope_set_state(s, SCOPE_START_CHOWN); ++ ++ return 1; ++fail: ++ s->timer_event_source = sd_event_source_disable_unref(s->timer_event_source); ++ return r; ++} ++ ++static int scope_enter_running(Scope *s) { ++ Unit *u = UNIT(s); ++ int r; ++ ++ assert(s); + + (void) bus_scope_track_controller(s); + +@@ -328,11 +382,7 @@ static int scope_start(Unit *u) { + if (r < 0) + return r; + +- (void) unit_realize_cgroup(u); +- (void) unit_reset_cpu_accounting(u); +- (void) unit_reset_ip_accounting(u); +- +- unit_export_state_files(UNIT(s)); ++ unit_export_state_files(u); + + r = unit_attach_pids_to_cgroup(u, UNIT(s)->pids, NULL); + if (r < 0) { +@@ -350,6 +400,38 @@ static int scope_start(Unit *u) { + return 1; + } + ++static int scope_start(Unit *u) { ++ Scope *s = SCOPE(u); ++ ++ assert(s); ++ ++ if (unit_has_name(u, SPECIAL_INIT_SCOPE)) ++ return -EPERM; ++ ++ if (s->state == SCOPE_FAILED) ++ return -EPERM; ++ ++ /* We can't fulfill this right now, please try again later */ ++ if (IN_SET(s->state, SCOPE_STOP_SIGTERM, SCOPE_STOP_SIGKILL)) ++ return -EAGAIN; ++ ++ assert(s->state == SCOPE_DEAD); ++ ++ if (!u->transient && !MANAGER_IS_RELOADING(u->manager)) ++ return -ENOENT; ++ ++ (void) unit_realize_cgroup(u); ++ (void) unit_reset_cpu_accounting(u); ++ (void) unit_reset_ip_accounting(u); ++ ++ /* We check only for User= option to keep behavior consistent with logic for service units, ++ * i.e. having 'Delegate=true Group=foo' w/o specifing User= has no effect. */ ++ if (s->user && unit_cgroup_delegate(u)) ++ return scope_enter_start_chown(s); ++ ++ return scope_enter_running(s); ++} ++ + static int scope_stop(Unit *u) { + Scope *s = SCOPE(u); + +@@ -462,7 +544,17 @@ static void scope_notify_cgroup_empty_event(Unit *u) { + } + + static void scope_sigchld_event(Unit *u, pid_t pid, int code, int status) { +- assert(u); ++ Scope *s = SCOPE(u); ++ ++ assert(s); ++ ++ if (s->state == SCOPE_START_CHOWN) { ++ if (!is_clean_exit(code, status, EXIT_CLEAN_COMMAND, NULL)) ++ scope_enter_dead(s, SCOPE_FAILURE_RESOURCES); ++ else ++ scope_enter_running(s); ++ return; ++ } + + /* If we get a SIGCHLD event for one of the processes we were interested in, then we look for others to + * watch, under the assumption that we'll sooner or later get a SIGCHLD for them, as the original +@@ -495,6 +587,11 @@ static int scope_dispatch_timer(sd_event_source *source, usec_t usec, void *user + scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); + break; + ++ case SCOPE_START_CHOWN: ++ log_unit_warning(UNIT(s), "User lookup timed out. Entering failed state."); ++ scope_enter_dead(s, SCOPE_FAILURE_TIMEOUT); ++ break; ++ + default: + assert_not_reached("Timeout at wrong time."); + } +diff --git a/src/core/scope.h b/src/core/scope.h +index c38afb5e5d..7bed3eed9e 100644 +--- a/src/core/scope.h ++++ b/src/core/scope.h +@@ -32,6 +32,9 @@ struct Scope { + bool was_abandoned; + + sd_event_source *timer_event_source; ++ ++ char *user; ++ char *group; + }; + + extern const UnitVTable scope_vtable; +diff --git a/src/shared/bus-unit-util.c b/src/shared/bus-unit-util.c +index 3910dfa812..c475bbafe0 100644 +--- a/src/shared/bus-unit-util.c ++++ b/src/shared/bus-unit-util.c +@@ -1615,6 +1615,11 @@ static int bus_append_unit_property(sd_bus_message *m, const char *field, const + + return bus_append_parse_sec_rename(m, field, eq); + ++ /* Scope units don't have execution context but we still want to allow setting these two, ++ * so let's handle them separately. */ ++ if (STR_IN_SET(field, "User", "Group")) ++ return bus_append_string(m, field, eq); ++ + if (streq(field, "StartLimitBurst")) + + return bus_append_safe_atou(m, field, eq); +diff --git a/test/TEST-19-DELEGATE/testsuite.sh b/test/TEST-19-DELEGATE/testsuite.sh +index c738bea10e..c4c948cc11 100755 +--- a/test/TEST-19-DELEGATE/testsuite.sh ++++ b/test/TEST-19-DELEGATE/testsuite.sh +@@ -4,6 +4,16 @@ + set -ex + set -o pipefail + ++test_scope_unpriv_delegation() { ++ useradd test ||: ++ trap "userdel -r test" RETURN ++ ++ systemd-run --uid=test -p User=test -p Delegate=yes --slice workload.slice --unit workload0.scope --scope \ ++ test -w /sys/fs/cgroup/workload.slice/workload0.scope -a \ ++ -w /sys/fs/cgroup/workload.slice/workload0.scope/cgroup.procs -a \ ++ -w /sys/fs/cgroup/workload.slice/workload0.scope/cgroup.subtree_control ++} ++ + if grep -q cgroup2 /proc/filesystems ; then + systemd-run --wait --unit=test0.service -p "DynamicUser=1" -p "Delegate=" \ + test -w /sys/fs/cgroup/system.slice/test0.service/ -a \ +@@ -15,6 +25,9 @@ if grep -q cgroup2 /proc/filesystems ; then + + systemd-run --wait --unit=test2.service -p "DynamicUser=1" -p "Delegate=memory pids" \ + grep pids /sys/fs/cgroup/system.slice/test2.service/cgroup.controllers ++ ++ # Check that unprivileged delegation works for scopes ++ test_scope_unpriv_delegation + else + echo "Skipping TEST-19-DELEGATE, as the kernel doesn't actually support cgroupsv2" >&2 + fi diff --git a/SOURCES/0824-resolved-pin-stream-while-calling-callbacks-for-it.patch b/SOURCES/0824-resolved-pin-stream-while-calling-callbacks-for-it.patch new file mode 100644 index 0000000..9b60e51 --- /dev/null +++ b/SOURCES/0824-resolved-pin-stream-while-calling-callbacks-for-it.patch @@ -0,0 +1,39 @@ +From 3f3b00c8753fb591a4cd7b770ce069d455dcc4d6 Mon Sep 17 00:00:00 2001 +From: Lennart Poettering +Date: Tue, 4 Dec 2018 22:13:39 +0100 +Subject: [PATCH] resolved: pin stream while calling callbacks for it + +These callbacks might unref the stream, but we still have to access it, +let's hence ref it explicitly. + +Maybe fixes: #10725 + +(cherry picked from commit d973d94dec349fb676fdd844f6fe2ada3538f27c) + +Resolves: #2110549 +--- + src/resolve/resolved-dns-stream.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/resolve/resolved-dns-stream.c b/src/resolve/resolved-dns-stream.c +index 555e200a23..ca0313d1d7 100644 +--- a/src/resolve/resolved-dns-stream.c ++++ b/src/resolve/resolved-dns-stream.c +@@ -42,6 +42,8 @@ static int dns_stream_update_io(DnsStream *s) { + } + + static int dns_stream_complete(DnsStream *s, int error) { ++ _cleanup_(dns_stream_unrefp) _unused_ DnsStream *ref = dns_stream_ref(s); /* Protect stream while we process it */ ++ + assert(s); + + #if ENABLE_DNS_OVER_TLS +@@ -316,7 +318,7 @@ static int on_stream_timeout(sd_event_source *es, usec_t usec, void *userdata) { + } + + static int on_stream_io(sd_event_source *es, int fd, uint32_t revents, void *userdata) { +- DnsStream *s = userdata; ++ _cleanup_(dns_stream_unrefp) DnsStream *s = dns_stream_ref(userdata); /* Protect stream while we process it */ + int r; + + assert(s); diff --git a/SOURCES/0825-ci-functions-Add-useradd-and-userdel.patch b/SOURCES/0825-ci-functions-Add-useradd-and-userdel.patch new file mode 100644 index 0000000..a483ce3 --- /dev/null +++ b/SOURCES/0825-ci-functions-Add-useradd-and-userdel.patch @@ -0,0 +1,28 @@ +From 10758905f159bbe87a10f185f7e9afefbbd21fd4 Mon Sep 17 00:00:00 2001 +From: Jan Macku +Date: Fri, 26 Aug 2022 13:06:42 +0200 +Subject: [PATCH] ci(functions): Add `useradd` and `userdel` + +Inspired by upstream commit: +https://github.com/systemd/systemd/commit/9c94ab0f6ff22da4278a6e9a93ddc480607c55ac + +RHEL-only + +Related: #2110549 +--- + test/test-functions | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/test/test-functions b/test/test-functions +index ed8ab98173..19363be858 100644 +--- a/test/test-functions ++++ b/test/test-functions +@@ -23,7 +23,7 @@ fi + + PATH_TO_INIT=$ROOTLIBDIR/systemd + +-BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint" ++BASICTOOLS="test sh bash setsid loadkeys setfont login sulogin gzip sleep echo mount umount cryptsetup date dmsetup modprobe sed cmp tee rm true false chmod chown ln xargs env mktemp mountpoint useradd userdel" + DEBUGTOOLS="df free ls stty cat ps ln ip route dmesg dhclient mkdir cp ping dhclient strace less grep id tty touch du sort hostname find" + + STATEDIR="${BUILD_DIR:-.}/test/$(basename $(dirname $(realpath $0)))" diff --git a/SPECS/systemd.spec b/SPECS/systemd.spec index a3255fa..079c082 100644 --- a/SPECS/systemd.spec +++ b/SPECS/systemd.spec @@ -13,7 +13,7 @@ Name: systemd Url: http://www.freedesktop.org/wiki/Software/systemd Version: 239 -Release: 65%{?dist} +Release: 67%{?dist} # For a breakdown of the licensing, see README License: LGPLv2+ and MIT and GPLv2+ Summary: System and Service Manager @@ -870,6 +870,11 @@ Patch0817: 0817-seccomp-tighten-checking-of-seccomp-filter-creation.patch Patch0818: 0818-shared-seccomp-util-added-functionality-to-make-list.patch Patch0819: 0819-nspawn-return-ENOSYS-by-default-EPERM-for-known-call.patch Patch0820: 0820-test-procfs-util-skip-test-on-certain-errors.patch +Patch0821: 0821-Try-stopping-MD-RAID-devices-in-shutdown-too.patch +Patch0822: 0822-shutdown-get-only-active-md-arrays.patch +Patch0823: 0823-scope-allow-unprivileged-delegation-on-scopes.patch +Patch0824: 0824-resolved-pin-stream-while-calling-callbacks-for-it.patch +Patch0825: 0825-ci-functions-Add-useradd-and-userdel.patch %ifarch %{ix86} x86_64 aarch64 %global have_gnu_efi 1 @@ -1499,6 +1504,15 @@ fi %files tests -f .file-list-tests %changelog +* Fri Aug 26 2022 systemd maintenance team - 239-67 +- resolved: pin stream while calling callbacks for it (#2110549) +- ci(functions): Add `useradd` and `userdel` (#2110549) + +* Thu Aug 25 2022 systemd maintenance team - 239-66 +- Try stopping MD RAID devices in shutdown too (#1817706) +- shutdown: get only active md arrays. (#1817706) +- scope: allow unprivileged delegation on scopes (#2068575) + * Fri Aug 19 2022 systemd maintenance team - 239-65 - test-procfs-util: skip test on certain errors (#2087152)