From dfe19f1350bf82d0499d3370179e963f74c9e3c7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 2 Jun 2026 11:32:26 +0900 Subject: [PATCH 1/7] namespace-util: introduce network_namespace_is_init() --- src/basic/namespace-util.c | 37 +++++++++++++++++++++++++++++++++++++ src/basic/namespace-util.h | 1 + src/test/test-namespace.c | 2 ++ 3 files changed, 40 insertions(+) diff --git a/src/basic/namespace-util.c b/src/basic/namespace-util.c index db95ab8627..72e7005c94 100644 --- a/src/basic/namespace-util.c +++ b/src/basic/namespace-util.c @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -410,12 +411,48 @@ int are_our_namespaces(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, return true; } +int network_namespace_is_init(int socket_fd) { + struct stat a, b; + int r; + + /* This works only when privileged. */ + + r = RET_NERRNO(stat(pid_namespace_path(1, NAMESPACE_NET), &a)); + if (r == -ENOENT) { + /* If the /proc/ns/ API is not around in /proc/ then ns is off in the kernel and we are in the init ns */ + r = proc_mounted(); + if (r < 0) + return -ENOENT; /* If we can't determine if /proc/ is mounted propagate original error */ + + return r ? true : -ENOSYS; + } + if (r < 0) + return r; + + if (socket_fd >= 0) { + _cleanup_close_ int netns = ioctl(socket_fd, SIOCGSKNS); + if (netns < 0) + return -errno; + + if (fstat(netns, &b) < 0) + return -errno; + } else { + if (stat(pid_namespace_path(0, NAMESPACE_NET), &b) < 0) + return -errno; + } + + return stat_inode_same(&a, &b); +} + int namespace_is_init(NamespaceType type) { int r; assert(type >= 0); assert(type < _NAMESPACE_TYPE_MAX); + if (type == NAMESPACE_NET) + return network_namespace_is_init(/* socket_fd= */ -EBADF); + if (namespace_info[type].root_inode == 0) return -EBADR; /* Cannot answer this question */ diff --git a/src/basic/namespace-util.h b/src/basic/namespace-util.h index b82efc826b..d0eff636a9 100644 --- a/src/basic/namespace-util.h +++ b/src/basic/namespace-util.h @@ -52,6 +52,7 @@ int fd_is_namespace(int fd, NamespaceType type); int is_our_namespace(int fd, NamespaceType type); int are_our_namespaces(int pidns_fd, int mntns_fd, int netns_fd, int userns_fd, int root_fd); +int network_namespace_is_init(int socket_fd); int namespace_is_init(NamespaceType type); int pidref_in_same_namespace(PidRef *pid1, PidRef *pid2, NamespaceType type); diff --git a/src/test/test-namespace.c b/src/test/test-namespace.c index b9f4e35f2e..7b95a59135 100644 --- a/src/test/test-namespace.c +++ b/src/test/test-namespace.c @@ -253,6 +253,8 @@ TEST(namespace_is_init) { r = namespace_is_init(t); if (r == -EBADR) log_info_errno(r, "In root namespace of type '%s': don't know", namespace_info[t].proc_name); + else if (t == NAMESPACE_NET && ERRNO_IS_NEG_PRIVILEGE(r)) + log_info_errno(r, "In root namespace of type '%s': no privilege: %m", namespace_info[t].proc_name); else { ASSERT_OK(r); log_info("In root namespace of type '%s': %s", namespace_info[t].proc_name, yes_no(r)); From 7f1ca24bb97d084dba009be72bd7a0b135548c41 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 2 Jun 2026 11:37:52 +0900 Subject: [PATCH 2/7] sd-device: use network_namespace_is_init() --- src/libsystemd/sd-device/device-monitor.c | 34 ++++------------------- 1 file changed, 6 insertions(+), 28 deletions(-) diff --git a/src/libsystemd/sd-device/device-monitor.c b/src/libsystemd/sd-device/device-monitor.c index 9799d9b4da..709d0e3d76 100644 --- a/src/libsystemd/sd-device/device-monitor.c +++ b/src/libsystemd/sd-device/device-monitor.c @@ -2,8 +2,6 @@ #include #include -#include -#include #include #include "sd-device.h" @@ -24,9 +22,9 @@ #include "log.h" #include "log-context.h" #include "mountpoint-util.h" +#include "namespace-util.h" #include "set.h" #include "socket-util.h" -#include "stat-util.h" #include "string-util.h" #include "uid-range.h" @@ -189,35 +187,15 @@ int device_monitor_new_full(sd_device_monitor **ret, MonitorNetlinkGroup group, } if (DEBUG_LOGGING) { - _cleanup_close_ int netns = -EBADF; - /* So here's the thing: only AF_NETLINK sockets from the main network namespace will get * hardware events. Let's check if ours is from there, and if not generate a debug message, * since we cannot possibly work correctly otherwise. This is just a safety check to make * things easier to debug. */ - - netns = ioctl(m->sock, SIOCGSKNS); - if (netns < 0) - log_monitor_errno(m, errno, "Unable to get network namespace of udev netlink socket, unable to determine if we are in host netns, ignoring: %m"); - else { - struct stat a, b; - - if (fstat(netns, &a) < 0) { - r = log_monitor_errno(m, errno, "Failed to stat netns of udev netlink socket: %m"); - goto fail; - } - - if (stat("/proc/1/ns/net", &b) < 0) { - if (ERRNO_IS_PRIVILEGE(errno)) - /* If we can't access PID1's netns info due to permissions, it's fine, this is a - * safety check only after all. */ - log_monitor_errno(m, errno, "No permission to stat PID1's netns, unable to determine if we are in host netns, ignoring: %m"); - else - log_monitor_errno(m, errno, "Failed to stat PID1's netns, ignoring: %m"); - - } else if (!stat_inode_same(&a, &b)) - log_monitor(m, "Netlink socket we listen on is not from host netns, we won't see device events."); - } + r = network_namespace_is_init(m->sock); + if (r < 0) + log_monitor_errno(m, r, "Failed to check if we are in the main network namespace, ignoring: %m"); + else if (r == 0) + log_monitor(m, "Netlink socket we listen on is not from the main network namespace, we won't see device events."); } /* Let's bump the receive buffer size, but only if we are not called via socket activation, as in From 14f934df35f7da168100786b0dd2c549d1e52743 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Tue, 2 Jun 2026 11:45:15 +0900 Subject: [PATCH 3/7] nspawn: do not try to connect udevd nspawn itself does not require to control udevd process. Only necessary points are - udevd is available, and - we are in the main network namespace. Let's check them explicitly. This also makes the check is skipped when we are talking to mountfsd, as the check is pointless in that case. --- src/nspawn/nspawn.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/src/nspawn/nspawn.c b/src/nspawn/nspawn.c index 959aef9b71..2617e249f3 100644 --- a/src/nspawn/nspawn.c +++ b/src/nspawn/nspawn.c @@ -128,6 +128,7 @@ #include "sysctl-util.h" #include "terminal-util.h" #include "tmpfile-util.h" +#include "udev-util.h" #include "uid-classification.h" #include "umask-util.h" #include "unit-name.h" @@ -6044,8 +6045,6 @@ static int initialize_rlimits(void) { } static int cant_be_in_netns(void) { - _cleanup_close_ int fd = -EBADF; - struct ucred ucred; int r; /* Check if we are in the same netns as udev. If we aren't, then device monitoring (and thus waiting @@ -6055,28 +6054,20 @@ static int cant_be_in_netns(void) { if (!arg_image) /* only matters if --image= us used, i.e. we actually need to use loopback devices */ return 0; - fd = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); - if (fd < 0) - return log_error_errno(errno, "Failed to allocate udev control socket: %m"); + if (arg_userns_mode == USER_NAMESPACE_MANAGED) + return 0; - r = connect_unix_path(fd, AT_FDCWD, "/run/udev/control"); - if (r == -ENOENT || ERRNO_IS_NEG_DISCONNECT(r)) + if (!udev_available()) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), - "Sorry, but --image= requires access to the host's /run/ hierarchy, since we need access to udev."); + "Sorry, but --image= requires that systemd-udevd is available."); + + r = namespace_is_init(NAMESPACE_NET); if (ERRNO_IS_NEG_PRIVILEGE(r)) { - log_debug_errno(r, "Can't connect to udev control socket, assuming we are in same netns."); + log_debug_errno(r, "Failed to check if we are in the main network namespace, assuming so, ignoring: %m"); return 0; } if (r < 0) - return log_error_errno(r, "Failed to connect socket to udev control socket: %m"); - - r = getpeercred(fd, &ucred); - if (r < 0) - return log_error_errno(r, "Failed to determine peer of udev control socket: %m"); - - r = in_same_namespace(ucred.pid, 0, NAMESPACE_NET); - if (r < 0) - return log_error_errno(r, "Failed to determine network namespace of udev: %m"); + return log_error_errno(r, "Failed to check if we are in the main network namespace: %m"); if (r == 0) return log_error_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Sorry, but --image= is only supported in the main network namespace, since we need access to udev/AF_NETLINK."); From 17e911ffc853c54f44edd11ead8b6edab72c1217 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Mon, 23 Feb 2026 01:01:45 +0900 Subject: [PATCH 4/7] udev: drop home-grown udev-ctrl socket Nowadays, varlink is used to control systemd-udevd. Let's drop the legacy socket. Note, the existence of /run/udev/control socket is widely used in both our code and external projects. Also, the dependency to systemd-udevd-control.socket is widely used in many projects. Hence, we need to create a symlink to the socket file and .socket unit file. --- man/rules/meson.build | 1 - man/systemd-udevd.service.xml | 2 - man/udevadm.xml | 2 +- src/test/test-unit-name.c | 1 - src/udev/meson.build | 2 - src/udev/udev-ctrl.c | 362 ----------------------------- src/udev/udev-ctrl.h | 72 ------ src/udev/udev-forward.h | 1 - src/udev/udev-manager-ctrl.c | 134 ----------- src/udev/udev-manager-ctrl.h | 7 - src/udev/udev-manager.c | 12 +- src/udev/udev-manager.h | 2 - src/udev/udev-varlink.c | 9 + src/udev/udevadm-control.c | 70 ------ src/udev/udevadm-settle.c | 4 +- src/udev/udevadm-trigger.c | 3 +- src/udev/udevadm-util.c | 34 +-- src/udev/udevadm-util.h | 2 +- units/meson.build | 7 +- units/systemd-udev-trigger.service | 2 +- units/systemd-udevd-control.socket | 23 -- units/systemd-udevd-varlink.socket | 2 +- units/systemd-udevd.service.in | 2 +- 23 files changed, 21 insertions(+), 735 deletions(-) delete mode 100644 src/udev/udev-ctrl.c delete mode 100644 src/udev/udev-ctrl.h delete mode 100644 src/udev/udev-manager-ctrl.c delete mode 100644 src/udev/udev-manager-ctrl.h delete mode 100644 units/systemd-udevd-control.socket diff --git a/man/rules/meson.build b/man/rules/meson.build index eac4465769..d3cb5e4292 100644 --- a/man/rules/meson.build +++ b/man/rules/meson.build @@ -1319,7 +1319,6 @@ manpages = [ ['systemd-udevd.service', '8', ['systemd-udevd', - 'systemd-udevd-control.socket', 'systemd-udevd-kernel.socket', 'systemd-udevd-varlink.socket'], ''], diff --git a/man/systemd-udevd.service.xml b/man/systemd-udevd.service.xml index ab50fb65a2..f367288bbe 100644 --- a/man/systemd-udevd.service.xml +++ b/man/systemd-udevd.service.xml @@ -18,7 +18,6 @@ systemd-udevd.service - systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket systemd-udevd @@ -27,7 +26,6 @@ systemd-udevd.service - systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket diff --git a/man/udevadm.xml b/man/udevadm.xml index 2a9963cd14..e13ff9842b 100644 --- a/man/udevadm.xml +++ b/man/udevadm.xml @@ -713,7 +713,7 @@ Note that systemd-udevd.service contains and so as a result, this option restarts systemd-udevd. If you want to stop systemd-udevd.service, please use the following: - systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket systemd-udevd.service + systemctl stop systemd-udevd-kernel.socket systemd-udevd-varlink.socket systemd-udevd.service diff --git a/src/test/test-unit-name.c b/src/test/test-unit-name.c index c218e015fa..4621d899ae 100644 --- a/src/test/test-unit-name.c +++ b/src/test/test-unit-name.c @@ -996,7 +996,6 @@ TEST(unit_name_from_dbus_path) { test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2ddev_2eservice", 0, "systemd-tmpfiles-setup-dev.service"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dtmpfiles_2dsetup_2eservice", 0, "systemd-tmpfiles-setup.service"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudev_2dtrigger_2eservice", 0, "systemd-udev-trigger.service"); - test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dcontrol_2esocket", 0, "systemd-udevd-control.socket"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2dkernel_2esocket", 0, "systemd-udevd-kernel.socket"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dudevd_2eservice", 0, "systemd-udevd.service"); test_unit_name_from_dbus_path_one("/org/freedesktop/systemd1/unit/systemd_2dupdate_2ddone_2eservice", 0, "systemd-update-done.service"); diff --git a/src/udev/meson.build b/src/udev/meson.build index 893241db0f..15d140398b 100644 --- a/src/udev/meson.build +++ b/src/udev/meson.build @@ -32,13 +32,11 @@ udevadm_export_sources = files( 'udev-builtin-path_id.c', 'udev-builtin-usb_id.c', 'udev-config.c', - 'udev-ctrl.c', 'udev-dump.c', 'udev-error.c', '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-ctrl.c b/src/udev/udev-ctrl.c deleted file mode 100644 index fbd0834d16..0000000000 --- a/src/udev/udev-ctrl.c +++ /dev/null @@ -1,362 +0,0 @@ -/* SPDX-License-Identifier: LGPL-2.1-or-later */ - -#include -#include -#include - -#include "sd-event.h" - -#include "alloc-util.h" -#include "errno-util.h" -#include "fd-util.h" -#include "format-util.h" -#include "iovec-util.h" -#include "log.h" -#include "socket-util.h" -#include "strxcpyx.h" -#include "udev-ctrl.h" - -/* wire protocol magic must match */ -#define UDEV_CTRL_MAGIC 0xdead1dea - -typedef struct UdevCtrlMessageWire { - char version[16]; - unsigned magic; - UdevCtrlMessageType type; - UdevCtrlMessageValue value; -} UdevCtrlMessageWire; - -struct UdevCtrl { - unsigned n_ref; - int sock; - int sock_connect; - union sockaddr_union saddr; - socklen_t addrlen; - bool bound; - bool connected; - sd_event *event; - sd_event_source *event_source; - sd_event_source *event_source_connect; - udev_ctrl_handler_t callback; - void *userdata; -}; - -int udev_ctrl_new_from_fd(UdevCtrl **ret, int fd) { - _cleanup_close_ int sock = -EBADF; - UdevCtrl *uctrl; - int r; - - assert(ret); - - if (fd < 0) { - sock = socket(AF_UNIX, SOCK_SEQPACKET|SOCK_NONBLOCK|SOCK_CLOEXEC, 0); - if (sock < 0) - return log_error_errno(errno, "Failed to create socket: %m"); - } - - /* enable receiving of the sender credentials in the messages */ - r = setsockopt_int(fd >= 0 ? fd : sock, SOL_SOCKET, SO_PASSCRED, true); - if (r < 0) - log_warning_errno(r, "Failed to set SO_PASSCRED, ignoring: %m"); - - r = setsockopt_int(fd >= 0 ? fd : sock, SOL_SOCKET, SO_PASSRIGHTS, false); - if (r < 0) - log_debug_errno(r, "Failed to turn off SO_PASSRIGHTS, ignoring: %m"); - - uctrl = new(UdevCtrl, 1); - if (!uctrl) - return -ENOMEM; - - *uctrl = (UdevCtrl) { - .n_ref = 1, - .sock = fd >= 0 ? fd : TAKE_FD(sock), - .sock_connect = -EBADF, - .bound = fd >= 0, - }; - - uctrl->saddr.un = (struct sockaddr_un) { - .sun_family = AF_UNIX, - .sun_path = "/run/udev/control", - }; - - uctrl->addrlen = sockaddr_un_len(&uctrl->saddr.un); - - *ret = TAKE_PTR(uctrl); - return 0; -} - -int udev_ctrl_enable_receiving(UdevCtrl *uctrl) { - assert(uctrl); - - if (uctrl->bound) - return 0; - - (void) sockaddr_un_unlink(&uctrl->saddr.un); - if (bind(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) - return log_error_errno(errno, "Failed to bind udev control socket: %m"); - - if (listen(uctrl->sock, 0) < 0) - return log_error_errno(errno, "Failed to listen udev control socket: %m"); - - uctrl->bound = true; - return 0; -} - -static void udev_ctrl_disconnect(UdevCtrl *uctrl) { - if (!uctrl) - return; - - uctrl->event_source_connect = sd_event_source_unref(uctrl->event_source_connect); - uctrl->sock_connect = safe_close(uctrl->sock_connect); -} - -static UdevCtrl *udev_ctrl_free(UdevCtrl *uctrl) { - assert(uctrl); - - udev_ctrl_disconnect(uctrl); - - sd_event_source_unref(uctrl->event_source); - safe_close(uctrl->sock); - - sd_event_unref(uctrl->event); - return mfree(uctrl); -} - -DEFINE_TRIVIAL_REF_UNREF_FUNC(UdevCtrl, udev_ctrl, udev_ctrl_free); - -int udev_ctrl_attach_event(UdevCtrl *uctrl, sd_event *event) { - int r; - - assert_return(uctrl, -EINVAL); - assert_return(!uctrl->event, -EBUSY); - - if (event) - uctrl->event = sd_event_ref(event); - else { - r = sd_event_default(&uctrl->event); - if (r < 0) - return r; - } - - return 0; -} - -sd_event_source *udev_ctrl_get_event_source(UdevCtrl *uctrl) { - assert(uctrl); - - return uctrl->event_source; -} - -static void udev_ctrl_disconnect_and_listen_again(UdevCtrl *uctrl) { - udev_ctrl_disconnect(uctrl); - udev_ctrl_unref(uctrl); - (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_ON); - /* We don't return NULL here because uctrl is not freed */ -} - -DEFINE_TRIVIAL_CLEANUP_FUNC_FULL(UdevCtrl*, udev_ctrl_disconnect_and_listen_again, NULL); - -static int udev_ctrl_connection_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - _cleanup_(udev_ctrl_disconnect_and_listen_againp) UdevCtrl *uctrl = NULL; - UdevCtrlMessageWire msg_wire; - struct iovec iov = IOVEC_MAKE(&msg_wire, sizeof(UdevCtrlMessageWire)); - CMSG_BUFFER_TYPE(CMSG_SPACE(sizeof(struct ucred))) control; - struct msghdr smsg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = &control, - .msg_controllen = sizeof(control), - }; - struct ucred *cred; - ssize_t size; - - assert(userdata); - - /* When UDEV_CTRL_EXIT is received, manager unref udev_ctrl object. - * To avoid the object freed, let's increment the refcount. */ - uctrl = udev_ctrl_ref(userdata); - - size = recvmsg_safe(fd, &smsg, 0); - if (ERRNO_IS_NEG_TRANSIENT(size)) - return 0; - if (size == -ECHRNG) { - log_warning_errno(size, "Got message with truncated control data (unexpected fds sent?), ignoring."); - return 0; - } - if (size == -EXFULL) { - log_warning_errno(size, "Got message with truncated payload data, ignoring."); - return 0; - } - if (size < 0) - return log_error_errno(size, "Failed to receive ctrl message: %m"); - - cmsg_close_all(&smsg); - - if (size != sizeof(msg_wire)) { - log_warning("Received message with invalid length, ignoring"); - return 0; - } - - cred = CMSG_FIND_DATA(&smsg, SOL_SOCKET, SCM_CREDENTIALS, struct ucred); - if (!cred) { - log_warning("No sender credentials received, ignoring message"); - return 0; - } - - if (cred->uid != 0) { - log_warning("Invalid sender uid "UID_FMT", ignoring message", cred->uid); - return 0; - } - - if (msg_wire.magic != UDEV_CTRL_MAGIC) { - log_warning("Message magic 0x%08x doesn't match, ignoring message", msg_wire.magic); - return 0; - } - - if (msg_wire.type == _UDEV_CTRL_END_MESSAGES) - return 0; - - if (uctrl->callback) - (void) uctrl->callback(uctrl, msg_wire.type, &msg_wire.value, uctrl->userdata); - - /* Do not disconnect and wait for next message. */ - uctrl = udev_ctrl_unref(uctrl); - return 0; -} - -static int udev_ctrl_event_handler(sd_event_source *s, int fd, uint32_t revents, void *userdata) { - UdevCtrl *uctrl = ASSERT_PTR(userdata); - _cleanup_close_ int sock = -EBADF; - struct ucred ucred; - int r; - - sock = accept4(fd, NULL, NULL, SOCK_CLOEXEC|SOCK_NONBLOCK); - if (sock < 0) { - if (ERRNO_IS_ACCEPT_AGAIN(errno)) - return 0; - - return log_error_errno(errno, "Failed to accept ctrl connection: %m"); - } - - /* check peer credential of connection */ - r = getpeercred(sock, &ucred); - if (r < 0) { - log_error_errno(r, "Failed to receive credentials of ctrl connection: %m"); - return 0; - } - - if (ucred.uid > 0) { - log_error("Invalid sender uid "UID_FMT", closing connection", ucred.uid); - return 0; - } - - r = sd_event_add_io(uctrl->event, &uctrl->event_source_connect, sock, EPOLLIN, udev_ctrl_connection_event_handler, uctrl); - if (r < 0) { - log_error_errno(r, "Failed to create event source for udev control connection: %m"); - return 0; - } - - (void) sd_event_source_set_description(uctrl->event_source_connect, "udev-ctrl-connection"); - - /* Do not accept multiple connection. */ - (void) sd_event_source_set_enabled(uctrl->event_source, SD_EVENT_OFF); - - uctrl->sock_connect = TAKE_FD(sock); - return 0; -} - -int udev_ctrl_start(UdevCtrl *uctrl, udev_ctrl_handler_t callback, void *userdata) { - int r; - - assert(uctrl); - - if (!uctrl->event) { - r = udev_ctrl_attach_event(uctrl, NULL); - if (r < 0) - return r; - } - - r = udev_ctrl_enable_receiving(uctrl); - if (r < 0) - return r; - - uctrl->callback = callback; - uctrl->userdata = userdata; - - r = sd_event_add_io(uctrl->event, &uctrl->event_source, uctrl->sock, EPOLLIN, udev_ctrl_event_handler, uctrl); - if (r < 0) - return r; - - (void) sd_event_source_set_description(uctrl->event_source, "udev-ctrl"); - - return 0; -} - -int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, const void *data) { - UdevCtrlMessageWire ctrl_msg_wire = { - .version = "udev-" PROJECT_VERSION_STR, - .magic = UDEV_CTRL_MAGIC, - .type = type, - }; - - if (type == UDEV_CTRL_SET_ENV) { - assert(data); - strscpy(ctrl_msg_wire.value.buf, sizeof(ctrl_msg_wire.value.buf), data); - } else if (IN_SET(type, UDEV_CTRL_SET_LOG_LEVEL, UDEV_CTRL_SET_CHILDREN_MAX)) - ctrl_msg_wire.value.intval = PTR_TO_INT(data); - - if (!uctrl->connected) { - if (connect(uctrl->sock, &uctrl->saddr.sa, uctrl->addrlen) < 0) - return -errno; - uctrl->connected = true; - } - - if (send(uctrl->sock, &ctrl_msg_wire, sizeof(ctrl_msg_wire), 0) < 0) - return -errno; - - return 0; -} - -int udev_ctrl_wait(UdevCtrl *uctrl, usec_t timeout) { - _cleanup_(sd_event_source_disable_unrefp) sd_event_source *source_io = NULL, *source_timeout = NULL; - int r; - - assert(uctrl); - - if (uctrl->sock < 0) - return 0; - if (!uctrl->connected) - return 0; - - r = udev_ctrl_send(uctrl, _UDEV_CTRL_END_MESSAGES, NULL); - if (r < 0) - return r; - - if (timeout == 0) - return 0; - - if (!uctrl->event) { - r = udev_ctrl_attach_event(uctrl, NULL); - if (r < 0) - return r; - } - - r = sd_event_add_io(uctrl->event, &source_io, uctrl->sock, EPOLLIN, NULL, INT_TO_PTR(0)); - if (r < 0) - return r; - - (void) sd_event_source_set_description(source_io, "udev-ctrl-wait-io"); - - if (timeout != USEC_INFINITY) { - r = sd_event_add_time_relative( - uctrl->event, &source_timeout, CLOCK_BOOTTIME, - timeout, - 0, NULL, INT_TO_PTR(-ETIMEDOUT)); - if (r < 0) - return r; - - (void) sd_event_source_set_description(source_timeout, "udev-ctrl-wait-timeout"); - } - - return sd_event_loop(uctrl->event); -} diff --git a/src/udev/udev-ctrl.h b/src/udev/udev-ctrl.h deleted file mode 100644 index 83c66239d0..0000000000 --- a/src/udev/udev-ctrl.h +++ /dev/null @@ -1,72 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -#pragma once - -#include "udev-forward.h" - -typedef enum UdevCtrlMessageType { - _UDEV_CTRL_END_MESSAGES, - UDEV_CTRL_SET_LOG_LEVEL, - UDEV_CTRL_STOP_EXEC_QUEUE, - UDEV_CTRL_START_EXEC_QUEUE, - UDEV_CTRL_RELOAD, - UDEV_CTRL_SET_ENV, - UDEV_CTRL_SET_CHILDREN_MAX, - UDEV_CTRL_PING, - UDEV_CTRL_EXIT, -} UdevCtrlMessageType; - -typedef union UdevCtrlMessageValue { - int intval; - char buf[256]; -} UdevCtrlMessageValue; - -typedef int (*udev_ctrl_handler_t)(UdevCtrl *udev_ctrl, UdevCtrlMessageType type, - const UdevCtrlMessageValue *value, void *userdata); - -int udev_ctrl_new_from_fd(UdevCtrl **ret, int fd); -static inline int udev_ctrl_new(UdevCtrl **ret) { - return udev_ctrl_new_from_fd(ret, -EBADF); -} - -int udev_ctrl_enable_receiving(UdevCtrl *uctrl); -DECLARE_TRIVIAL_REF_UNREF_FUNC(UdevCtrl, udev_ctrl); -int udev_ctrl_attach_event(UdevCtrl *uctrl, sd_event *event); -int udev_ctrl_start(UdevCtrl *uctrl, udev_ctrl_handler_t callback, void *userdata); -sd_event_source *udev_ctrl_get_event_source(UdevCtrl *uctrl); - -int udev_ctrl_wait(UdevCtrl *uctrl, usec_t timeout); - -int udev_ctrl_send(UdevCtrl *uctrl, UdevCtrlMessageType type, const void *data); -static inline int udev_ctrl_send_set_log_level(UdevCtrl *uctrl, int priority) { - return udev_ctrl_send(uctrl, UDEV_CTRL_SET_LOG_LEVEL, INT_TO_PTR(priority)); -} - -static inline int udev_ctrl_send_stop_exec_queue(UdevCtrl *uctrl) { - return udev_ctrl_send(uctrl, UDEV_CTRL_STOP_EXEC_QUEUE, NULL); -} - -static inline int udev_ctrl_send_start_exec_queue(UdevCtrl *uctrl) { - return udev_ctrl_send(uctrl, UDEV_CTRL_START_EXEC_QUEUE, NULL); -} - -static inline int udev_ctrl_send_reload(UdevCtrl *uctrl) { - return udev_ctrl_send(uctrl, UDEV_CTRL_RELOAD, NULL); -} - -static inline int udev_ctrl_send_set_env(UdevCtrl *uctrl, const char *key) { - return udev_ctrl_send(uctrl, UDEV_CTRL_SET_ENV, key); -} - -static inline int udev_ctrl_send_set_children_max(UdevCtrl *uctrl, int count) { - return udev_ctrl_send(uctrl, UDEV_CTRL_SET_CHILDREN_MAX, INT_TO_PTR(count)); -} - -static inline int udev_ctrl_send_ping(UdevCtrl *uctrl) { - return udev_ctrl_send(uctrl, UDEV_CTRL_PING, NULL); -} - -static inline int udev_ctrl_send_exit(UdevCtrl *uctrl) { - return udev_ctrl_send(uctrl, UDEV_CTRL_EXIT, NULL); -} - -DEFINE_TRIVIAL_CLEANUP_FUNC(UdevCtrl*, udev_ctrl_unref); diff --git a/src/udev/udev-forward.h b/src/udev/udev-forward.h index d4526ad8e5..cc322bc4c6 100644 --- a/src/udev/udev-forward.h +++ b/src/udev/udev-forward.h @@ -5,7 +5,6 @@ #include "forward.h" /* IWYU pragma: export */ -typedef struct UdevCtrl UdevCtrl; typedef struct UdevEvent UdevEvent; typedef struct Manager Manager; typedef struct Event Event; diff --git a/src/udev/udev-manager-ctrl.c b/src/udev/udev-manager-ctrl.c deleted file mode 100644 index c395993a24..0000000000 --- a/src/udev/udev-manager-ctrl.c +++ /dev/null @@ -1,134 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ - -#include "sd-daemon.h" -#include "sd-event.h" - -#include "log.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; - (void) manager_reset_kill_workers_timer(manager); - 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), EVENT_PRIORITY_CONTROL); - 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 deleted file mode 100644 index 270a63e861..0000000000 --- a/src/udev/udev-manager-ctrl.h +++ /dev/null @@ -1,7 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-or-later */ -#pragma once - -#include "udev-forward.h" - -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 fabbdbb88c..2c43d9ccc5 100644 --- a/src/udev/udev-manager.c +++ b/src/udev/udev-manager.c @@ -35,10 +35,8 @@ #include "time-util.h" #include "udev-builtin.h" #include "udev-config.h" -#include "udev-ctrl.h" #include "udev-error.h" #include "udev-manager.h" -#include "udev-manager-ctrl.h" #include "udev-rules.h" #include "udev-spawn.h" #include "udev-trace.h" @@ -166,7 +164,6 @@ Manager* manager_free(Manager *manager) { sd_device_monitor_unref(manager->monitor); - udev_ctrl_unref(manager->ctrl); sd_varlink_server_unref(manager->varlink_server); sd_event_source_unref(manager->inotify_event); @@ -255,7 +252,6 @@ void manager_exit(Manager *manager) { (void) sd_notify(/* unset_environment= */ false, NOTIFY_STOPPING_MESSAGE); /* close sources of new events and discard buffered events */ - manager->ctrl = udev_ctrl_unref(manager->ctrl); manager->varlink_server = sd_varlink_server_unref(manager->varlink_server); (void) manager_serialize_config(manager); @@ -1410,9 +1406,7 @@ static int manager_listen_fds(Manager *manager, int *ret_varlink_fd) { if (streq(names[i], "varlink")) { varlink_fd = fd; r = 0; - } else if (streq(names[i], "systemd-udevd-control.socket")) - r = manager_init_ctrl(manager, fd); - else if (streq(names[i], "systemd-udevd-kernel.socket")) + } else if (streq(names[i], "systemd-udevd-kernel.socket")) r = manager_init_device_monitor(manager, fd); else if (streq(names[i], "inotify")) r = manager_init_inotify(manager, fd); @@ -1473,10 +1467,6 @@ int manager_main(Manager *manager) { if (r < 0) return r; - r = manager_start_ctrl(manager); - if (r < 0) - return r; - r = manager_start_varlink_server(manager, TAKE_FD(varlink_fd)); if (r < 0) return r; diff --git a/src/udev/udev-manager.h b/src/udev/udev-manager.h index 4e18dd5404..1b5db6e3b6 100644 --- a/src/udev/udev-manager.h +++ b/src/udev/udev-manager.h @@ -33,7 +33,6 @@ #define EVENT_PRIORITY_SIGHUP (SD_EVENT_PRIORITY_NORMAL + 1) /* Let's not interrupt the service by any user process, even that requires privileges. */ #define EVENT_PRIORITY_VARLINK (SD_EVENT_PRIORITY_NORMAL + 2) -#define EVENT_PRIORITY_CONTROL (SD_EVENT_PRIORITY_NORMAL + 2) /* The event is intended to trigger the post-event source, hence can be the lowest priority. */ #define EVENT_PRIORITY_REQUEUE_EVENT (SD_EVENT_PRIORITY_NORMAL + 3) @@ -48,7 +47,6 @@ typedef struct Manager { Hashmap *properties; sd_device_monitor *monitor; - UdevCtrl *ctrl; sd_varlink_server *varlink_server; char *worker_notify_socket_path; diff --git a/src/udev/udev-varlink.c b/src/udev/udev-varlink.c index 183265fc53..70567dc58a 100644 --- a/src/udev/udev-varlink.c +++ b/src/udev/udev-varlink.c @@ -2,6 +2,7 @@ #include "bus-polkit.h" #include "fd-util.h" +#include "fs-util.h" #include "json-util.h" #include "log.h" #include "string-util.h" @@ -197,6 +198,14 @@ int manager_start_varlink_server(Manager *manager, int fd) { TAKE_FD(fd_close); + /* For backward compatibility. The existence of the file is used by udevadm settle, sd-device, + * libudev, and many external projects for checking if udevd is running. Note, it may be already + * created by PID1 through systemd-udevd-varlink.socket. But, we need to explicitly create it here, + * to make it created even in systemd-less systems or systemd-less initrd. */ + r = symlink_idempotent(UDEV_VARLINK_ADDRESS, "/run/udev/control", /* make_relative= */ false); + if (r < 0) + log_warning_errno(r, "Failed to create symlink /run/udev/control to "UDEV_VARLINK_ADDRESS", ignoring: %m"); + r = sd_varlink_server_add_interface_many( v, &vl_interface_io_systemd_service, diff --git a/src/udev/udevadm-control.c b/src/udev/udevadm-control.c index cef3ec7fd5..54bf1a003b 100644 --- a/src/udev/udevadm-control.c +++ b/src/udev/udevadm-control.c @@ -3,7 +3,6 @@ #include #include "creds-util.h" -#include "errno-util.h" #include "format-table.h" #include "help-util.h" #include "log.h" @@ -14,7 +13,6 @@ #include "strv.h" #include "syslog-util.h" #include "time-util.h" -#include "udev-ctrl.h" #include "udev-varlink.h" #include "udevadm.h" #include "varlink-util.h" @@ -170,79 +168,11 @@ static int parse_argv(int argc, char *argv[]) { return 1; } -static int send_control_commands_via_ctrl(void) { - _cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL; - int r; - - r = udev_ctrl_new(&uctrl); - if (r < 0) - return log_error_errno(r, "Failed to initialize udev control: %m"); - - if (arg_exit) { - r = udev_ctrl_send_exit(uctrl); - if (r < 0) - return log_error_errno(r, "Failed to send exit request: %m"); - return 0; - } - - if (arg_log_level >= 0) { - r = udev_ctrl_send_set_log_level(uctrl, arg_log_level); - if (r < 0) - return log_error_errno(r, "Failed to send request to set log level: %m"); - } - - if (arg_start_exec_queue == false) { - r = udev_ctrl_send_stop_exec_queue(uctrl); - if (r < 0) - return log_error_errno(r, "Failed to send request to stop exec queue: %m"); - } - - if (arg_start_exec_queue == true) { - r = udev_ctrl_send_start_exec_queue(uctrl); - if (r < 0) - return log_error_errno(r, "Failed to send request to start exec queue: %m"); - } - - if (arg_reload) { - r = udev_ctrl_send_reload(uctrl); - if (r < 0) - return log_error_errno(r, "Failed to send reload request: %m"); - } - - STRV_FOREACH(env, arg_env) { - r = udev_ctrl_send_set_env(uctrl, *env); - if (r < 0) - return log_error_errno(r, "Failed to send request to update environment: %m"); - } - - if (arg_max_children >= 0) { - r = udev_ctrl_send_set_children_max(uctrl, arg_max_children); - if (r < 0) - return log_error_errno(r, "Failed to send request to set number of children: %m"); - } - - if (arg_ping) { - r = udev_ctrl_send_ping(uctrl); - if (r < 0) - return log_error_errno(r, "Failed to send a ping message: %m"); - } - - r = udev_ctrl_wait(uctrl, arg_timeout); - if (r < 0) - return log_error_errno(r, "Failed to wait for daemon to reply: %m"); - - return 0; -} - static int send_control_commands(void) { _cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *link = NULL; int r; r = udev_varlink_connect(&link, arg_timeout); - if (ERRNO_IS_NEG_DISCONNECT(r) || r == -ENOENT) { - log_debug_errno(r, "Failed to connect to udev via varlink, falling back to use legacy control socket, ignoring: %m"); - return send_control_commands_via_ctrl(); - } if (r < 0) return log_error_errno(r, "Failed to connect to udev via varlink: %m"); diff --git a/src/udev/udevadm-settle.c b/src/udev/udevadm-settle.c index c23e87c9d6..4398f40e72 100644 --- a/src/udev/udevadm-settle.c +++ b/src/udev/udevadm-settle.c @@ -209,8 +209,8 @@ int verb_settle_main(int argc, char *argv[], uintptr_t _data, void *userdata) { (void) emit_deprecation_warning(); if (getuid() == 0) { - r = udev_ping(MAX(5 * USEC_PER_SEC, arg_timeout_usec), /* ignore_connection_failure= */ true); - if (r <= 0) + r = udev_ping(MAX(5 * USEC_PER_SEC, arg_timeout_usec)); + if (r < 0) return r; } else { /* For non-privileged users, at least check if udevd is running. */ diff --git a/src/udev/udevadm-trigger.c b/src/udev/udevadm-trigger.c index f1cdbfe105..5d7752783f 100644 --- a/src/udev/udevadm-trigger.c +++ b/src/udev/udevadm-trigger.c @@ -521,10 +521,9 @@ int verb_trigger_main(int argc, char *argv[], uintptr_t _data, void *userdata) { return r; if (arg_ping) { - r = udev_ping(arg_ping_timeout_usec, /* ignore_connection_failure= */ false); + r = udev_ping(arg_ping_timeout_usec); if (r < 0) return r; - assert(r > 0); } if (arg_settle) { diff --git a/src/udev/udevadm-util.c b/src/udev/udevadm-util.c index 8e90946960..7c0c9601e0 100644 --- a/src/udev/udevadm-util.c +++ b/src/udev/udevadm-util.c @@ -8,14 +8,12 @@ #include "conf-files.h" #include "constants.h" #include "device-private.h" -#include "errno-util.h" #include "extract-word.h" #include "log.h" #include "path-util.h" #include "string-table.h" #include "string-util.h" #include "strv.h" -#include "udev-ctrl.h" #include "udev-rules.h" #include "udev-varlink.h" #include "udevadm-util.h" @@ -174,39 +172,11 @@ int parse_key_value_argument(const char *str, bool require_value, char **key, ch return 0; } -static int udev_ping_via_ctrl(usec_t timeout_usec, bool ignore_connection_failure) { - _cleanup_(udev_ctrl_unrefp) UdevCtrl *uctrl = NULL; - int r; - - r = udev_ctrl_new(&uctrl); - if (r < 0) - return log_error_errno(r, "Failed to initialize udev control: %m"); - - r = udev_ctrl_send_ping(uctrl); - if (r < 0) { - bool ignore = ignore_connection_failure && (ERRNO_IS_NEG_DISCONNECT(r) || r == -ENOENT); - log_full_errno(ignore ? LOG_DEBUG : LOG_ERR, r, - "Failed to connect to udev daemon%s: %m", - ignore ? ", ignoring" : ""); - return ignore ? 0 : r; - } - - r = udev_ctrl_wait(uctrl, timeout_usec); - if (r < 0) - return log_error_errno(r, "Failed to wait for daemon to reply: %m"); - - return 1; /* received reply */ -} - -int udev_ping(usec_t timeout_usec, bool ignore_connection_failure) { +int udev_ping(usec_t timeout_usec) { _cleanup_(sd_varlink_flush_close_unrefp) sd_varlink *link = NULL; int r; r = udev_varlink_connect(&link, timeout_usec); - if (ERRNO_IS_NEG_DISCONNECT(r) || r == -ENOENT) { - log_debug_errno(r, "Failed to connect to udev via varlink, falling back to use legacy control socket, ignoring: %m"); - return udev_ping_via_ctrl(timeout_usec, ignore_connection_failure); - } if (r < 0) return log_error_errno(r, "Failed to connect to udev via varlink: %m"); @@ -214,7 +184,7 @@ int udev_ping(usec_t timeout_usec, bool ignore_connection_failure) { if (r < 0) return r; - return 1; /* received reply */ + return 0; } static int search_rules_file_in_conf_dirs(const char *s, const char *root, ConfFile ***files, size_t *n_files) { diff --git a/src/udev/udevadm-util.h b/src/udev/udevadm-util.h index 906479825c..dc3d6bb833 100644 --- a/src/udev/udevadm-util.h +++ b/src/udev/udevadm-util.h @@ -11,5 +11,5 @@ int find_device_with_action(const char *id, sd_device_action_t action, sd_device int parse_device_action(const char *str, sd_device_action_t *ret); int parse_resolve_name_timing(const char *str, ResolveNameTiming *ret); int parse_key_value_argument(const char *str, bool require_value, char **key, char **value); -int udev_ping(usec_t timeout, bool ignore_connection_failure); +int udev_ping(usec_t timeout); int search_rules_files(char * const *a, const char *root, ConfFile ***ret_files, size_t *ret_n_files); diff --git a/units/meson.build b/units/meson.build index a4b0dc61cc..8e1f3c2aa8 100644 --- a/units/meson.build +++ b/units/meson.build @@ -985,11 +985,6 @@ units = [ 'symlinks' : ['sysinit.target.wants/'], 'install_tag' : 'udev', }, - { - 'file' : 'systemd-udevd-control.socket', - 'symlinks' : ['sockets.target.wants/'], - 'install_tag' : 'udev', - }, { 'file' : 'systemd-udevd-kernel.socket', 'symlinks' : ['sockets.target.wants/'], @@ -997,7 +992,7 @@ units = [ }, { 'file' : 'systemd-udevd-varlink.socket', - 'symlinks' : ['sockets.target.wants/'], + 'symlinks' : ['sockets.target.wants/', 'systemd-udevd-control.socket'], 'install_tag' : 'udev', }, { diff --git a/units/systemd-udev-trigger.service b/units/systemd-udev-trigger.service index 0ea1a4bd49..5a93e7375f 100644 --- a/units/systemd-udev-trigger.service +++ b/units/systemd-udev-trigger.service @@ -12,7 +12,7 @@ Description=Coldplug All udev Devices Documentation=man:udev(7) man:systemd-udevd.service(8) DefaultDependencies=no Wants=systemd-udevd.service -After=systemd-udevd-kernel.socket systemd-udevd-control.socket systemd-udevd-varlink.socket +After=systemd-udevd-kernel.socket systemd-udevd-varlink.socket Before=sysinit.target ConditionPathIsReadWrite=/sys diff --git a/units/systemd-udevd-control.socket b/units/systemd-udevd-control.socket deleted file mode 100644 index 942f6a5e8b..0000000000 --- a/units/systemd-udevd-control.socket +++ /dev/null @@ -1,23 +0,0 @@ -# SPDX-License-Identifier: LGPL-2.1-or-later -# -# This file is part of systemd. -# -# systemd is free software; you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation; either version 2.1 of the License, or -# (at your option) any later version. - -[Unit] -Description=udev Control Socket -Documentation=man:systemd-udevd-control.socket(8) man:udev(7) -DefaultDependencies=no -Before=sockets.target -ConditionPathIsReadWrite=/sys - -[Socket] -Service=systemd-udevd.service -ListenSequentialPacket=/run/udev/control -SocketMode=0600 -PassCredentials=yes -RemoveOnStop=yes -DeferTrigger=yes diff --git a/units/systemd-udevd-varlink.socket b/units/systemd-udevd-varlink.socket index b1094b9c9b..e2cc9594b0 100644 --- a/units/systemd-udevd-varlink.socket +++ b/units/systemd-udevd-varlink.socket @@ -17,7 +17,7 @@ ConditionPathIsReadWrite=/sys [Socket] Service=systemd-udevd.service ListenStream=/run/udev/io.systemd.Udev -Symlinks=/run/varlink/registry/io.systemd.Udev +Symlinks=/run/varlink/registry/io.systemd.Udev /run/udev/control FileDescriptorName=varlink SocketMode=0644 RemoveOnStop=yes diff --git a/units/systemd-udevd.service.in b/units/systemd-udevd.service.in index 658c19b278..395b912366 100644 --- a/units/systemd-udevd.service.in +++ b/units/systemd-udevd.service.in @@ -39,7 +39,7 @@ DelegateSubgroup=udev Type=notify-reload # Note that udev will reset the value internally for its workers OOMScoreAdjust=-1000 -Sockets=systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket +Sockets=systemd-udevd-kernel.socket systemd-udevd-varlink.socket Restart=always RestartSec=0 ExecStart={{LIBEXECDIR}}/systemd-udevd From 20ef89f64612e16c903e78dd9b9da0af5d14db6c Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 5 Jun 2026 04:18:48 +0900 Subject: [PATCH 5/7] NEWS: mention the removeal of legacy udev control socket --- NEWS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/NEWS b/NEWS index 8da1426b80..963acfdf62 100644 --- a/NEWS +++ b/NEWS @@ -27,6 +27,14 @@ CHANGES WITH 262: older systemd versions, however systemd continues to accept TPM-sealed credentials that were created before this change. + * The legacy socket for controlling systemd-udevd has been removed, and + udevadm now unconditionally uses Varlink IPC. The legacy UNIX socket + /run/udev/control, which is sometimes used to check whether udevd is + running, has been replaced with a symlink to the Varlink socket. This + change does not mean the legacy protocol is supported on this path; + rather, the symlink is maintained to ensure the socket is bound under + the same conditions as before. + Changes in the system and service manager: * The manager now embeds a basic set of unit files (basic.target, From 8e54afe8da43a2204da23051c967d8f5526dc4cc Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 5 Jun 2026 04:07:45 +0900 Subject: [PATCH 6/7] mkosi/opensuse: do not try to package non-existent symlink to systemd-udevd-control.socket --- .../build/mkosi.conf.d/opensuse/mkosi.build.chroot | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot b/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot index 14a69456cd..f3e8841e54 100755 --- a/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot +++ b/mkosi/mkosi.images/build/mkosi.conf.d/opensuse/mkosi.build.chroot @@ -19,9 +19,12 @@ TS="${SOURCE_DATE_EPOCH:-$(date +%s)}" # disable manpage compression as the files cannot be found. Fix the issue by removing the compression # extension. # TODO: remove autovt@ removal when the upstream spec is updated +# TODO: remove systemd-udevd-control.socket removal when the upstream spec is updated while read -r filelist; do sed -E \ -e '/autovt@/d' \ + -e '/sockets\.target\.wants\/systemd-udevd-control\.socket/d' \ + -e '/systemd-udevd-control\.socket\.8/d' \ -e 's/\.gz$//' \ "$filelist" >"/tmp/$(basename "$filelist")" mount --bind "/tmp/$(basename "$filelist")" "$filelist" From 368eb65155c785ddb9a077dc48655bdcb46535d8 Mon Sep 17 00:00:00 2001 From: Luca Boccassi Date: Mon, 20 Jul 2026 10:58:51 +0100 Subject: [PATCH 7/7] mkosi: update debian commit reference to 56402b2bde258999a8f01a8b04465fde9242d6a1 * 56402b2bde Drop symlink to systemd-udevd-control.socket * 3afaaf4f89 Install new files for upstream build --- mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf b/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf index fb4069a0fa..b842c6e2d2 100644 --- a/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf +++ b/mkosi/mkosi.pkgenv/mkosi.conf.d/debian-ubuntu.conf @@ -9,5 +9,5 @@ Environment= GIT_URL=https://salsa.debian.org/systemd-team/systemd.git GIT_SUBDIR=debian GIT_BRANCH=debian/master - GIT_COMMIT=88c420c621dbd1b988950cf26fc60789fc989453 + GIT_COMMIT=56402b2bde258999a8f01a8b04465fde9242d6a1 PKG_SUBDIR=debian