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.
This commit is contained in:
@@ -1319,7 +1319,6 @@ manpages = [
|
||||
['systemd-udevd.service',
|
||||
'8',
|
||||
['systemd-udevd',
|
||||
'systemd-udevd-control.socket',
|
||||
'systemd-udevd-kernel.socket',
|
||||
'systemd-udevd-varlink.socket'],
|
||||
''],
|
||||
|
||||
@@ -18,7 +18,6 @@
|
||||
|
||||
<refnamediv>
|
||||
<refname>systemd-udevd.service</refname>
|
||||
<refname>systemd-udevd-control.socket</refname>
|
||||
<refname>systemd-udevd-kernel.socket</refname>
|
||||
<refname>systemd-udevd-varlink.socket</refname>
|
||||
<refname>systemd-udevd</refname>
|
||||
@@ -27,7 +26,6 @@
|
||||
|
||||
<refsynopsisdiv>
|
||||
<para><filename>systemd-udevd.service</filename></para>
|
||||
<para><filename>systemd-udevd-control.socket</filename></para>
|
||||
<para><filename>systemd-udevd-kernel.socket</filename></para>
|
||||
<para><filename>systemd-udevd-varlink.socket</filename></para>
|
||||
|
||||
|
||||
+1
-1
@@ -713,7 +713,7 @@
|
||||
Note that <filename>systemd-udevd.service</filename> contains
|
||||
<option>Restart=always</option> and so as a result, this option restarts systemd-udevd.
|
||||
If you want to stop <filename>systemd-udevd.service</filename>, please use the following:
|
||||
<programlisting>systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd-varlink.socket systemd-udevd.service</programlisting>
|
||||
<programlisting>systemctl stop systemd-udevd-kernel.socket systemd-udevd-varlink.socket systemd-udevd.service</programlisting>
|
||||
</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
@@ -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");
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -1,362 +0,0 @@
|
||||
/* SPDX-License-Identifier: LGPL-2.1-or-later */
|
||||
|
||||
#include <poll.h>
|
||||
#include <sys/un.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#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);
|
||||
}
|
||||
@@ -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);
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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);
|
||||
+1
-11
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
#include <string.h>
|
||||
|
||||
#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");
|
||||
|
||||
|
||||
@@ -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. */
|
||||
|
||||
@@ -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) {
|
||||
|
||||
+2
-32
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
-6
@@ -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',
|
||||
},
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user