From: Yu Watanabe Date: Wed, 15 Jan 2025 20:07:41 +0000 (+0900) Subject: udev: split out legacy control socket handling to udev-manager-ctrl.c X-Git-Tag: v258-rc1~1553^2~3 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=ac440e47c51bf7ffea2e19f57bf30b16d2610dfb;p=thirdparty%2Fsystemd.git udev: split out legacy control socket handling to udev-manager-ctrl.c Mostly no functional change, except for that now the socket for device monitor is determined by its name. --- diff --git a/src/udev/meson.build b/src/udev/meson.build index f008ea1f665..fdd042aefa3 100644 --- a/src/udev/meson.build +++ b/src/udev/meson.build @@ -34,6 +34,7 @@ libudevd_core_sources = files( 'udev-event.c', 'udev-format.c', 'udev-manager.c', + 'udev-manager-ctrl.c', 'udev-node.c', 'udev-rules.c', 'udev-spawn.c', diff --git a/src/udev/udev-manager-ctrl.c b/src/udev/udev-manager-ctrl.c new file mode 100644 index 00000000000..b39af06927e --- /dev/null +++ b/src/udev/udev-manager-ctrl.c @@ -0,0 +1,132 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#include "sd-daemon.h" +#include "sd-event.h" + +#include "syslog-util.h" +#include "udev-ctrl.h" +#include "udev-manager.h" +#include "udev-manager-ctrl.h" + +/* receive the udevd message from userspace */ +static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) { + Manager *manager = ASSERT_PTR(userdata); + + assert(value); + + switch (type) { + case UDEV_CTRL_SET_LOG_LEVEL: + if (!log_level_is_valid(value->intval)) { + log_debug("Received invalid udev control message (SET_LOG_LEVEL, %i), ignoring.", value->intval); + break; + } + + log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval); + + manager_set_log_level(manager, value->intval); + break; + case UDEV_CTRL_STOP_EXEC_QUEUE: + log_debug("Received udev control message (STOP_EXEC_QUEUE)"); + manager->stop_exec_queue = true; + break; + case UDEV_CTRL_START_EXEC_QUEUE: + log_debug("Received udev control message (START_EXEC_QUEUE)"); + manager->stop_exec_queue = false; + /* It is not necessary to call event_queue_start() here, as it will be called in on_post() if necessary. */ + break; + case UDEV_CTRL_RELOAD: + log_debug("Received udev control message (RELOAD)"); + manager_reload(manager, /* force = */ true); + break; + case UDEV_CTRL_SET_ENV: + if (!udev_property_assignment_is_valid(value->buf)) { + log_debug("Received invalid udev control message(SET_ENV, %s), ignoring.", value->buf); + break; + } + + log_debug("Received udev control message(SET_ENV, %s)", value->buf); + manager_set_environment(manager, STRV_MAKE(value->buf)); + break; + case UDEV_CTRL_SET_CHILDREN_MAX: + if (value->intval < 0) { + log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval); + return 0; + } + + log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval); + + manager_set_children_max(manager, value->intval); + break; + case UDEV_CTRL_PING: + log_debug("Received udev control message (PING)"); + break; + case UDEV_CTRL_EXIT: + log_debug("Received udev control message (EXIT)"); + manager_exit(manager); + break; + default: + log_debug("Received unknown udev control message, ignoring"); + } + + return 1; +} + +int manager_init_ctrl(Manager *manager, int fd) { + int r; + + assert(manager); + + /* This takes passed file descriptor on success. */ + + if (fd >= 0) { + if (manager->ctrl) + return log_warning_errno(SYNTHETIC_ERRNO(EALREADY), "Received multiple control socket (%i), ignoring.", fd); + + r = sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1); + if (r < 0) + return log_warning_errno(r, "Failed to verify socket type of %i, ignoring: %m", fd); + if (r == 0) + return log_warning_errno(SYNTHETIC_ERRNO(EINVAL), "Received invalid control socket (%i), ignoring.", fd); + } else { + if (manager->ctrl) + return 0; + } + + r = udev_ctrl_new_from_fd(&manager->ctrl, fd); + if (r < 0) + return log_error_errno(r, "Failed to initialize udev control socket: %m"); + + return 0; +} + +int manager_start_ctrl(Manager *manager) { + int r; + + assert(manager); + assert(manager->event); + + r = manager_init_ctrl(manager, -EBADF); + if (r < 0) + return r; + + r = udev_ctrl_enable_receiving(manager->ctrl); + if (r < 0) + return log_error_errno(r, "Failed to bind udev control socket: %m"); + + r = udev_ctrl_attach_event(manager->ctrl, manager->event); + if (r < 0) + return log_error_errno(r, "Failed to attach event to udev control: %m"); + + r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager); + if (r < 0) + return log_error_errno(r, "Failed to start udev control: %m"); + + /* This needs to be after the inotify and uevent handling, to make sure that the ping is send back + * after fully processing the pending uevents (including the synthetic ones we may create due to + * inotify events). */ + r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE); + if (r < 0) + return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m"); + + return 0; +} diff --git a/src/udev/udev-manager-ctrl.h b/src/udev/udev-manager-ctrl.h new file mode 100644 index 00000000000..507072ce278 --- /dev/null +++ b/src/udev/udev-manager-ctrl.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ +#pragma once + +typedef struct Manager Manager; + +int manager_init_ctrl(Manager *manager, int fd); +int manager_start_ctrl(Manager *manager); diff --git a/src/udev/udev-manager.c b/src/udev/udev-manager.c index caa43797597..59a04c6f441 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -27,6 +27,7 @@ #include "udev-ctrl.h" #include "udev-event.h" #include "udev-manager.h" +#include "udev-manager-ctrl.h" #include "udev-node.h" #include "udev-rules.h" #include "udev-spawn.h" @@ -843,69 +844,6 @@ static int on_worker(sd_event_source *s, int fd, uint32_t revents, void *userdat return 1; } -/* receive the udevd message from userspace */ -static int on_ctrl_msg(UdevCtrl *uctrl, UdevCtrlMessageType type, const UdevCtrlMessageValue *value, void *userdata) { - Manager *manager = ASSERT_PTR(userdata); - - assert(value); - - switch (type) { - case UDEV_CTRL_SET_LOG_LEVEL: - if (!log_level_is_valid(value->intval)) { - log_debug("Received invalid udev control message (SET_LOG_LEVEL, %i), ignoring.", value->intval); - break; - } - - log_debug("Received udev control message (SET_LOG_LEVEL), setting log_level=%i", value->intval); - - manager_set_log_level(manager, value->intval); - break; - case UDEV_CTRL_STOP_EXEC_QUEUE: - log_debug("Received udev control message (STOP_EXEC_QUEUE)"); - manager->stop_exec_queue = true; - break; - case UDEV_CTRL_START_EXEC_QUEUE: - log_debug("Received udev control message (START_EXEC_QUEUE)"); - manager->stop_exec_queue = false; - /* It is not necessary to call event_queue_start() here, as it will be called in on_post() if necessary. */ - break; - case UDEV_CTRL_RELOAD: - log_debug("Received udev control message (RELOAD)"); - manager_reload(manager, /* force = */ true); - break; - case UDEV_CTRL_SET_ENV: - if (!udev_property_assignment_is_valid(value->buf)) { - log_debug("Received invalid udev control message(SET_ENV, %s), ignoring.", value->buf); - break; - } - - log_debug("Received udev control message(SET_ENV, %s)", value->buf); - manager_set_environment(manager, STRV_MAKE(value->buf)); - break; - case UDEV_CTRL_SET_CHILDREN_MAX: - if (value->intval < 0) { - log_debug("Received invalid udev control message (SET_MAX_CHILDREN, %i), ignoring.", value->intval); - return 0; - } - - log_debug("Received udev control message (SET_MAX_CHILDREN), setting children_max=%i", value->intval); - - manager_set_children_max(manager, value->intval); - break; - case UDEV_CTRL_PING: - log_debug("Received udev control message (PING)"); - break; - case UDEV_CTRL_EXIT: - log_debug("Received udev control message (EXIT)"); - manager_exit(manager); - break; - default: - log_debug("Received unknown udev control message, ignoring"); - } - - return 1; -} - static int synthesize_change_one(sd_device *dev, sd_device *target) { int r; @@ -1135,11 +1073,12 @@ Manager* manager_new(void) { return manager; } -static int listen_fds(int *ret_ctrl, int *ret_netlink) { +static int manager_listen_fds(Manager *manager, int *ret_netlink) { _cleanup_strv_free_ char **names = NULL; - _cleanup_close_ int ctrl_fd = -EBADF, netlink_fd = -EBADF; + _cleanup_close_ int netlink_fd = -EBADF; + int r; - assert(ret_ctrl); + assert(manager); assert(ret_netlink); int n = sd_listen_fds_with_names(/* unset_environment = */ true, &names); @@ -1152,19 +1091,6 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) { for (int i = 0; i < n; i++) { int fd = SD_LISTEN_FDS_START + i; - if (streq(names[i], "varlink")) - continue; /* The fd will be handled by sd_varlink_server_listen_auto(). */ - - if (sd_is_socket(fd, AF_UNIX, SOCK_SEQPACKET, -1) > 0) { - if (ctrl_fd >= 0) { - log_debug("Received multiple seqpacket socket (%s), ignoring.", names[i]); - goto unused; - } - - ctrl_fd = fd; - continue; - } - if (sd_is_socket(fd, AF_NETLINK, SOCK_RAW, -1) > 0) { if (netlink_fd >= 0) { log_debug("Received multiple netlink socket (%s), ignoring.", names[i]); @@ -1175,39 +1101,24 @@ static int listen_fds(int *ret_ctrl, int *ret_netlink) { continue; } - log_debug("Received unexpected fd (%s), ignoring.", names[i]); + if (streq(names[i], "varlink")) + r = 0; /* The fd will be handled by sd_varlink_server_listen_auto(). */ + else if (streq(names[i], "systemd-udevd-control.socket")) + r = manager_init_ctrl(manager, fd); + else + r = log_debug_errno(SYNTHETIC_ERRNO(EINVAL), + "Received unexpected fd (%s), ignoring.", names[i]); + if (r < 0) + goto unused; unused: close_and_notify_warn(fd, names[i]); } - *ret_ctrl = TAKE_FD(ctrl_fd); *ret_netlink = TAKE_FD(netlink_fd); return 0; } -static int manager_init_ctrl(Manager *manager, int fd_ctrl) { - _cleanup_(udev_ctrl_unrefp) UdevCtrl *ctrl = NULL; - _cleanup_close_ int fd = fd_ctrl; - int r; - - assert(manager); - - /* This consumes passed file descriptor. */ - - r = udev_ctrl_new_from_fd(&ctrl, fd); - if (r < 0) - return log_error_errno(r, "Failed to initialize udev control socket: %m"); - TAKE_FD(fd); - - r = udev_ctrl_enable_receiving(ctrl); - if (r < 0) - return log_error_errno(r, "Failed to bind udev control socket: %m"); - - manager->ctrl = TAKE_PTR(ctrl); - return 0; -} - static int manager_init_device_monitor(Manager *manager, int fd_uevent) { _cleanup_(sd_device_monitor_unrefp) sd_device_monitor *monitor = NULL; _cleanup_close_ int fd = fd_uevent; @@ -1229,20 +1140,16 @@ static int manager_init_device_monitor(Manager *manager, int fd_uevent) { } int manager_init(Manager *manager) { - _cleanup_close_ int fd_ctrl = -EBADF, fd_uevent = -EBADF; + _cleanup_close_ int fd_uevent = -EBADF; _cleanup_free_ char *cgroup = NULL; int r; assert(manager); - r = listen_fds(&fd_ctrl, &fd_uevent); + r = manager_listen_fds(manager, &fd_uevent); if (r < 0) return log_error_errno(r, "Failed to listen on fds: %m"); - r = manager_init_ctrl(manager, TAKE_FD(fd_ctrl)); - if (r < 0) - return r; - r = manager_init_device_monitor(manager, TAKE_FD(fd_uevent)); if (r < 0) return r; @@ -1258,30 +1165,6 @@ int manager_init(Manager *manager) { return 0; } -static int manager_start_ctrl(Manager *manager) { - int r; - - assert(manager); - assert(manager->ctrl); - - r = udev_ctrl_attach_event(manager->ctrl, manager->event); - if (r < 0) - return log_error_errno(r, "Failed to attach event to udev control: %m"); - - r = udev_ctrl_start(manager->ctrl, on_ctrl_msg, manager); - if (r < 0) - return log_error_errno(r, "Failed to start udev control: %m"); - - /* This needs to be after the inotify and uevent handling, to make sure that the ping is send back - * after fully processing the pending uevents (including the synthetic ones we may create due to - * inotify events). */ - r = sd_event_source_set_priority(udev_ctrl_get_event_source(manager->ctrl), SD_EVENT_PRIORITY_IDLE); - if (r < 0) - return log_error_errno(r, "Failed to set IDLE event priority for udev control event source: %m"); - - return 0; -} - static int manager_start_device_monitor(Manager *manager) { int r;