From 3c03224757edb59f03585a6c6bda585ffbf8c6b9 Mon Sep 17 00:00:00 2001 From: yangmingtaip Date: Fri, 18 Mar 2022 11:56:07 +0800 Subject: [PATCH] fix systemctl reload systemd-udevd failed (cherry picked from commit f0ee1ce0db24d8d10f4f27afd955fb2054bef2ba) --- ...-type-name-e.g.-struct-worker-Worker.patch | 302 ++++++++++++++++++ ...n-process-workers-and-spawned-comman.patch | 176 ++++++++++ systemd.spec | 7 +- 3 files changed, 484 insertions(+), 1 deletion(-) create mode 100644 backport-udev-rename-type-name-e.g.-struct-worker-Worker.patch create mode 100644 backport-udev-run-the-main-process-workers-and-spawned-comman.patch diff --git a/backport-udev-rename-type-name-e.g.-struct-worker-Worker.patch b/backport-udev-rename-type-name-e.g.-struct-worker-Worker.patch new file mode 100644 index 0000000..eb573d7 --- /dev/null +++ b/backport-udev-rename-type-name-e.g.-struct-worker-Worker.patch @@ -0,0 +1,302 @@ +From d9239923c1de3f10f1598567e8bebcb798c4bd27 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 16 Jun 2021 19:05:39 +0900 +Subject: [PATCH] udev: rename type name e.g. struct worker -> Worker + +--- + src/udev/udevd.c | 97 +++++++++++++++++++++++++----------------------- + 1 file changed, 50 insertions(+), 47 deletions(-) + +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index 5a4657de14..6baedd2f2e 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -77,10 +77,13 @@ static usec_t arg_event_timeout_usec = 180 * USEC_PER_SEC; + static int arg_timeout_signal = SIGKILL; + static bool arg_blockdev_read_only = false; + ++typedef struct Event Event; ++typedef struct Worker Worker; ++ + typedef struct Manager { + sd_event *event; + Hashmap *workers; +- LIST_HEAD(struct event, events); ++ LIST_HEAD(Event, events); + const char *cgroup; + pid_t pid; /* the process that originally allocated the manager object */ + int log_level; +@@ -106,16 +109,16 @@ typedef struct Manager { + bool exit; + } Manager; + +-enum event_state { ++typedef enum EventState { + EVENT_UNDEF, + EVENT_QUEUED, + EVENT_RUNNING, +-}; ++} EventState; + +-struct event { ++typedef struct Event { + Manager *manager; +- struct worker *worker; +- enum event_state state; ++ Worker *worker; ++ EventState state; + + sd_device *dev; + sd_device *dev_kernel; /* clone of originally received device */ +@@ -126,32 +129,32 @@ struct event { + sd_event_source *timeout_warning_event; + sd_event_source *timeout_event; + +- LIST_FIELDS(struct event, event); +-}; ++ LIST_FIELDS(Event, event); ++} Event; + +-static void event_queue_cleanup(Manager *manager, enum event_state type); ++static void event_queue_cleanup(Manager *manager, EventState match_state); + +-enum worker_state { ++typedef enum WorkerState { + WORKER_UNDEF, + WORKER_RUNNING, + WORKER_IDLE, + WORKER_KILLED, + WORKER_KILLING, +-}; ++} WorkerState; + +-struct worker { ++typedef struct Worker { + Manager *manager; + pid_t pid; + sd_device_monitor *monitor; +- enum worker_state state; +- struct event *event; +-}; ++ WorkerState state; ++ Event *event; ++} Worker; + + /* passed from worker to main process */ +-struct worker_message { +-}; ++typedef struct WorkerMessage { ++} WorkerMessage; + +-static void event_free(struct event *event) { ++static void event_free(Event *event) { + if (!event) + return; + +@@ -176,7 +179,7 @@ static void event_free(struct event *event) { + free(event); + } + +-static struct worker* worker_free(struct worker *worker) { ++static Worker *worker_free(Worker *worker) { + if (!worker) + return NULL; + +@@ -189,11 +192,11 @@ static struct worker* worker_free(struct worker *worker) { + return mfree(worker); + } + +-DEFINE_TRIVIAL_CLEANUP_FUNC(struct worker *, worker_free); +-DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(worker_hash_op, void, trivial_hash_func, trivial_compare_func, struct worker, worker_free); ++DEFINE_TRIVIAL_CLEANUP_FUNC(Worker*, worker_free); ++DEFINE_PRIVATE_HASH_OPS_WITH_VALUE_DESTRUCTOR(worker_hash_op, void, trivial_hash_func, trivial_compare_func, Worker, worker_free); + +-static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) { +- _cleanup_(worker_freep) struct worker *worker = NULL; ++static int worker_new(Worker **ret, Manager *manager, sd_device_monitor *worker_monitor, pid_t pid) { ++ _cleanup_(worker_freep) Worker *worker = NULL; + int r; + + assert(ret); +@@ -204,11 +207,11 @@ static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor * + /* close monitor, but keep address around */ + device_monitor_disconnect(worker_monitor); + +- worker = new(struct worker, 1); ++ worker = new(Worker, 1); + if (!worker) + return -ENOMEM; + +- *worker = (struct worker) { ++ *worker = (Worker) { + .manager = manager, + .monitor = sd_device_monitor_ref(worker_monitor), + .pid = pid, +@@ -224,7 +227,7 @@ static int worker_new(struct worker **ret, Manager *manager, sd_device_monitor * + } + + static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) { +- struct event *event = userdata; ++ Event *event = userdata; + + assert(event); + assert(event->worker); +@@ -238,7 +241,7 @@ static int on_event_timeout(sd_event_source *s, uint64_t usec, void *userdata) { + } + + static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *userdata) { +- struct event *event = userdata; ++ Event *event = userdata; + + assert(event); + assert(event->worker); +@@ -248,7 +251,7 @@ static int on_event_timeout_warning(sd_event_source *s, uint64_t usec, void *use + return 1; + } + +-static void worker_attach_event(struct worker *worker, struct event *event) { ++static void worker_attach_event(Worker *worker, Event *event) { + sd_event *e; + + assert(worker); +@@ -315,7 +318,7 @@ static Manager* manager_free(Manager *manager) { + DEFINE_TRIVIAL_CLEANUP_FUNC(Manager*, manager_free); + + static int worker_send_message(int fd) { +- struct worker_message message = {}; ++ WorkerMessage message = {}; + + return loop_write(fd, &message, sizeof(message), false); + } +@@ -591,9 +594,9 @@ static int worker_main(Manager *_manager, sd_device_monitor *monitor, sd_device + return 0; + } + +-static int worker_spawn(Manager *manager, struct event *event) { ++static int worker_spawn(Manager *manager, Event *event) { + _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *worker_monitor = NULL; +- struct worker *worker; ++ Worker *worker; + pid_t pid; + int r; + +@@ -635,9 +638,9 @@ static int worker_spawn(Manager *manager, struct event *event) { + return 0; + } + +-static void event_run(Manager *manager, struct event *event) { ++static void event_run(Manager *manager, Event *event) { + static bool log_children_max_reached = true; +- struct worker *worker; ++ Worker *worker; + int r; + + assert(manager); +@@ -685,7 +688,7 @@ static void event_run(Manager *manager, struct event *event) { + + static int event_queue_insert(Manager *manager, sd_device *dev) { + _cleanup_(sd_device_unrefp) sd_device *clone = NULL; +- struct event *event; ++ Event *event; + uint64_t seqnum; + int r; + +@@ -709,11 +712,11 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { + if (r < 0) + return r; + +- event = new(struct event, 1); ++ event = new(Event, 1); + if (!event) + return -ENOMEM; + +- *event = (struct event) { ++ *event = (Event) { + .manager = manager, + .dev = sd_device_ref(dev), + .dev_kernel = TAKE_PTR(clone), +@@ -735,7 +738,7 @@ static int event_queue_insert(Manager *manager, sd_device *dev) { + } + + static void manager_kill_workers(Manager *manager, bool force) { +- struct worker *worker; ++ Worker *worker; + + assert(manager); + +@@ -754,10 +757,10 @@ static void manager_kill_workers(Manager *manager, bool force) { + } + + /* lookup event for identical, parent, child device */ +-static int is_device_busy(Manager *manager, struct event *event) { ++static int is_device_busy(Manager *manager, Event *event) { + const char *subsystem, *devpath, *devpath_old = NULL; + dev_t devnum = makedev(0, 0); +- struct event *loop_event; ++ Event *loop_event; + size_t devpath_len; + int r, ifindex = 0; + bool is_block; +@@ -916,7 +919,7 @@ static int on_kill_workers_event(sd_event_source *s, uint64_t usec, void *userda + } + + static void event_queue_start(Manager *manager) { +- struct event *event; ++ Event *event; + usec_t usec; + int r; + +@@ -963,11 +966,11 @@ static void event_queue_start(Manager *manager) { + } + } + +-static void event_queue_cleanup(Manager *manager, enum event_state match_type) { +- struct event *event, *tmp; ++static void event_queue_cleanup(Manager *manager, EventState match_state) { ++ Event *event, *tmp; + + LIST_FOREACH_SAFE(event, event, tmp, manager->events) { +- if (match_type != EVENT_UNDEF && match_type != event->state) ++ if (match_state != EVENT_UNDEF && match_state != event->state) + continue; + + event_free(event); +@@ -980,7 +983,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat + assert(manager); + + for (;;) { +- struct worker_message msg; ++ WorkerMessage msg; + struct iovec iovec = { + .iov_base = &msg, + .iov_len = sizeof(msg), +@@ -994,7 +997,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat + }; + ssize_t size; + struct ucred *ucred; +- struct worker *worker; ++ Worker *worker; + + size = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT); + if (size == -EINTR) +@@ -1007,7 +1010,7 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat + + cmsg_close_all(&msghdr); + +- if (size != sizeof(struct worker_message)) { ++ if (size != sizeof(WorkerMessage)) { + log_warning("Ignoring worker message with invalid size %zi bytes", size); + continue; + } +@@ -1357,7 +1360,7 @@ static int on_sigchld(sd_event_source *s, const struct signalfd_siginfo *si, voi + for (;;) { + pid_t pid; + int status; +- struct worker *worker; ++ Worker *worker; + + pid = waitpid(-1, &status, WNOHANG); + if (pid <= 0) +-- +2.27.0 + diff --git a/backport-udev-run-the-main-process-workers-and-spawned-comman.patch b/backport-udev-run-the-main-process-workers-and-spawned-comman.patch new file mode 100644 index 0000000..bc39fd9 --- /dev/null +++ b/backport-udev-run-the-main-process-workers-and-spawned-comman.patch @@ -0,0 +1,176 @@ +From a1f4fd387603673a79a84ca4e5ce25b439b85fe6 Mon Sep 17 00:00:00 2001 +From: Yu Watanabe +Date: Wed, 16 Mar 2022 20:46:49 +0900 +Subject: [PATCH] udev: run the main process, workers, and spawned commands in + /udev subcgroup + +And enable cgroup delegation for udevd. +Then, processes invoked through ExecReload= are assigned .control +subcgroup, and they are not killed by cg_kill(). + +Fixes #16867 and #22686. +--- + src/udev/udevd.c | 76 ++++++++++++++++++++++++++-------- + units/systemd-udevd.service.in | 1 + + 2 files changed, 59 insertions(+), 18 deletions(-) + +diff --git a/src/udev/udevd.c b/src/udev/udevd.c +index 8380d674c5..c6f6d945c8 100644 +--- a/src/udev/udevd.c ++++ b/src/udev/udevd.c +@@ -28,6 +28,7 @@ + #include "sd-event.h" + + #include "alloc-util.h" ++#include "cgroup-setup.h" + #include "cgroup-util.h" + #include "cpu-set-util.h" + #include "dev-setup.h" +@@ -48,6 +49,7 @@ + #include "mkdir.h" + #include "netlink-util.h" + #include "parse-util.h" ++#include "path-util.h" + #include "pretty-print.h" + #include "proc-cmdline.h" + #include "process-util.h" +@@ -85,7 +87,7 @@ typedef struct Manager { + sd_event *event; + Hashmap *workers; + LIST_HEAD(Event, events); +- const char *cgroup; ++ char *cgroup; + pid_t pid; /* the process that originally allocated the manager object */ + int log_level; + +@@ -238,6 +240,7 @@ static Manager* manager_free(Manager *manager) { + safe_close(manager->inotify_fd); + safe_close_pair(manager->worker_watch); + ++ free(manager->cgroup); + return mfree(manager); + } + +@@ -1722,12 +1725,63 @@ static int parse_argv(int argc, char *argv[]) { + return 1; + } + +-static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cgroup) { ++static int create_subcgroup(char **ret) { ++ _cleanup_free_ char *cgroup = NULL, *subcgroup = NULL; ++ int r; ++ ++ if (getppid() != 1) ++ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Not invoked by PID1."); ++ ++ r = sd_booted(); ++ if (r < 0) ++ return log_debug_errno(r, "Failed to check if systemd is running: %m"); ++ if (r == 0) ++ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "systemd is not running."); ++ ++ /* Get our own cgroup, we regularly kill everything udev has left behind. ++ * We only do this on systemd systems, and only if we are directly spawned ++ * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */ ++ ++ r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); ++ if (r < 0) { ++ if (IN_SET(r, -ENOENT, -ENOMEDIUM)) ++ return log_debug_errno(r, "Dedicated cgroup not found: %m"); ++ return log_debug_errno(r, "Failed to get cgroup: %m"); ++ } ++ ++ r = cg_get_xattr_bool(SYSTEMD_CGROUP_CONTROLLER, cgroup, "trusted.delegate"); ++ if (IN_SET(r, 0, -ENODATA)) ++ return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "The cgroup %s is not delegated to us.", cgroup); ++ if (r < 0) ++ return log_debug_errno(r, "Failed to read trusted.delegate attribute: %m"); ++ ++ /* We are invoked with our own delegated cgroup tree, let's move us one level down, so that we ++ * don't collide with the "no processes in inner nodes" rule of cgroups, when the service ++ * manager invokes the ExecReload= job in the .control/ subcgroup. */ ++ ++ subcgroup = path_join(cgroup, "/udev"); ++ if (!subcgroup) ++ return log_oom_debug(); ++ ++ r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, subcgroup, 0); ++ if (r < 0) ++ return log_debug_errno(r, "Failed to create %s subcgroup: %m", subcgroup); ++ ++ log_debug("Created %s subcgroup.", subcgroup); ++ if (ret) ++ *ret = TAKE_PTR(subcgroup); ++ return 0; ++} ++ ++static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent) { + _cleanup_(manager_freep) Manager *manager = NULL; ++ _cleanup_free_ char *cgroup = NULL; + int r; + + assert(ret); + ++ (void) create_subcgroup(&cgroup); ++ + manager = new(Manager, 1); + if (!manager) + return log_oom(); +@@ -1735,7 +1789,7 @@ static int manager_new(Manager **ret, int fd_ctrl, int fd_uevent, const char *cg + *manager = (Manager) { + .inotify_fd = -1, + .worker_watch = { -1, -1 }, +- .cgroup = cgroup, ++ .cgroup = TAKE_PTR(cgroup), + }; + + r = udev_ctrl_new_from_fd(&manager->ctrl, fd_ctrl); +@@ -1880,7 +1934,6 @@ static int main_loop(Manager *manager) { + } + + int run_udevd(int argc, char *argv[]) { +- _cleanup_free_ char *cgroup = NULL; + _cleanup_(manager_freep) Manager *manager = NULL; + int fd_ctrl = -1, fd_uevent = -1; + int r; +@@ -1937,24 +1990,11 @@ int run_udevd(int argc, char *argv[]) { + if (r < 0 && r != -EEXIST) + return log_error_errno(r, "Failed to create /run/udev: %m"); + +- if (getppid() == 1 && sd_booted() > 0) { +- /* Get our own cgroup, we regularly kill everything udev has left behind. +- * We only do this on systemd systems, and only if we are directly spawned +- * by PID1. Otherwise we are not guaranteed to have a dedicated cgroup. */ +- r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup); +- if (r < 0) { +- if (IN_SET(r, -ENOENT, -ENOMEDIUM)) +- log_debug_errno(r, "Dedicated cgroup not found: %m"); +- else +- log_warning_errno(r, "Failed to get cgroup: %m"); +- } +- } +- + r = listen_fds(&fd_ctrl, &fd_uevent); + if (r < 0) + return log_error_errno(r, "Failed to listen on fds: %m"); + +- r = manager_new(&manager, fd_ctrl, fd_uevent, cgroup); ++ r = manager_new(&manager, fd_ctrl, fd_uevent); + if (r < 0) + return log_error_errno(r, "Failed to create manager: %m"); + +diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in +index d042bfb0d3..9901198274 100644 +--- a/units/systemd-udevd.service.in ++++ b/units/systemd-udevd.service.in +@@ -16,6 +16,7 @@ Before=sysinit.target + ConditionPathIsReadWrite=/sys + + [Service] ++Delegate=pids + DeviceAllow=block-* rwm + DeviceAllow=char-* rwm + Type=notify +-- +2.27.0 + diff --git a/systemd.spec b/systemd.spec index 102242f..f58263d 100644 --- a/systemd.spec +++ b/systemd.spec @@ -20,7 +20,7 @@ Name: systemd Url: https://www.freedesktop.org/wiki/Software/systemd Version: 249 -Release: 14 +Release: 15 License: MIT and LGPLv2+ and GPLv2+ Summary: System and Service Manager @@ -85,6 +85,8 @@ Patch6014: backport-core-wrap-cgroup-path-with-empty_to_root-in-log-mess.pa Patch6015: backport-Bump-the-max-number-of-inodes-for-dev-to-a-million.patch Patch6016: backport-Bump-the-max-number-of-inodes-for-tmp-to-a-million-t.patch Patch6017: backport-unit-escape.patch +Patch6018: backport-udev-rename-type-name-e.g.-struct-worker-Worker.patch +Patch6019: backport-udev-run-the-main-process-workers-and-spawned-comman.patch BuildRequires: gcc, gcc-c++ BuildRequires: libcap-devel, libmount-devel, pam-devel, libselinux-devel @@ -1486,6 +1488,9 @@ fi %{_libdir}/security/pam_systemd.so %changelog +* Fri Mar 18 2022 yangmingtai - 249-15 +- fix systemctl reload systemd-udevd failed + * Thu Mar 17 2022 xujing - 249-14 - pid1 bump DefaultTasksMax to 80% of the kernel pid.max value