summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay.sievers@vrfy.org>2011-03-23 16:40:23 +0100
committerKay Sievers <kay.sievers@vrfy.org>2011-03-23 16:40:23 +0100
commitfc1de713f5b754fb38876b5b797e18f812727f0a (patch)
treed9b9a7159f9a5a058f1918dbe4bce61c03bb6b28
parenta31d76b18675a0bf213fdd16242b4268c9ff48e0 (diff)
systemd: bind udev control socket in systemd and split udev.service
We should bind the udev socket from systemd, so we are sure that the abstract namespace socket is always bound by a root process and there is never a window during an update where an untrusted process can steal our socket. Also split the udev.service file, so that the daemon can be updated/restarted without triggering any coldplug events.
-rw-r--r--Makefile.am8
-rw-r--r--configure.ac1
-rw-r--r--init/udev-trigger.service.in11
-rw-r--r--init/udev.service.in5
-rw-r--r--init/udev.socket5
-rw-r--r--libudev/libudev-ctrl.c39
-rw-r--r--libudev/libudev-private.h1
-rw-r--r--udev/udevd.c14
8 files changed, 68 insertions, 16 deletions
diff --git a/Makefile.am b/Makefile.am
index 40f13e790e..7ad9a242b7 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -124,14 +124,20 @@ sharepkgconfig_DATA = udev/udev.pc
if WITH_SYSTEMD
systemdsystemunit_DATA = \
+ init/udev.socket \
init/udev.service \
+ init/udev-trigger.service \
init/udev-settle.service
+EXTRA_DIST += init/udev.socket
+
systemd-install-hook:
+ mkdir -p $(DESTDIR)$(systemdsystemunitdir)/socket.target.wants
+ ln -sf ../udev.socket $(DESTDIR)$(systemdsystemunitdir)/socket.target.wants/udev.socket
mkdir -p $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants
ln -sf ../udev.service $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants/udev.service
+ ln -sf ../udev-trigger.service $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants/udev-trigger.service
ln -sf ../udev-settle.service $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants/udev-settle.service
- ln -sf ../udev-retry.service $(DESTDIR)$(systemdsystemunitdir)/basic.target.wants/udev-retry.service
INSTALL_DATA_HOOKS += systemd-install-hook
endif
diff --git a/configure.ac b/configure.ac
index 4ba5e32f30..1775fb072b 100644
--- a/configure.ac
+++ b/configure.ac
@@ -137,6 +137,7 @@ AC_CONFIG_FILES([
Makefile
udev/udev.pc
init/udev.service
+ init/udev-trigger.service
init/udev-settle.service
libudev/libudev.pc
libudev/docs/Makefile
diff --git a/init/udev-trigger.service.in b/init/udev-trigger.service.in
new file mode 100644
index 0000000000..0ede3171ea
--- /dev/null
+++ b/init/udev-trigger.service.in
@@ -0,0 +1,11 @@
+[Unit]
+Description=udev Coldplug all Devices
+Requires=udev.service
+After=udev.service
+Before=basic.target
+DefaultDependencies=no
+
+[Service]
+Type=oneshot
+RemainAfterExit=yes
+ExecStart=@sbindir@/udevadm trigger --type=subsystems --action=add ; @sbindir@/udevadm trigger --type=devices --action=add
diff --git a/init/udev.service.in b/init/udev.service.in
index 908c8e9acc..c02a4b4d85 100644
--- a/init/udev.service.in
+++ b/init/udev.service.in
@@ -1,9 +1,10 @@
[Unit]
Description=udev Kernel Device Manager
-DefaultDependencies=no
+Requires=udev.socket
+After=udev.socket
Before=basic.target
+DefaultDependencies=no
[Service]
Type=notify
ExecStart=@sbindir@/udevd
-ExecStartPost=@sbindir@/udevadm trigger --type=subsystems --action=add ; @sbindir@/udevadm trigger --type=devices --action=add
diff --git a/init/udev.socket b/init/udev.socket
new file mode 100644
index 0000000000..324ab47093
--- /dev/null
+++ b/init/udev.socket
@@ -0,0 +1,5 @@
+[Unit]
+Description=udev Kernel Device Manager Socket
+
+[Socket]
+ListenDatagram=@/org/kernel/udev/udevd
diff --git a/libudev/libudev-ctrl.c b/libudev/libudev-ctrl.c
index af59c36826..63bf539197 100644
--- a/libudev/libudev-ctrl.c
+++ b/libudev/libudev-ctrl.c
@@ -61,7 +61,7 @@ struct udev_ctrl {
socklen_t addrlen;
};
-struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path)
+static struct udev_ctrl *udev_ctrl_new(struct udev *udev)
{
struct udev_ctrl *uctrl;
@@ -70,6 +70,16 @@ struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socke
return NULL;
uctrl->refcount = 1;
uctrl->udev = udev;
+ return uctrl;
+}
+
+struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path)
+{
+ struct udev_ctrl *uctrl;
+
+ uctrl = udev_ctrl_new(udev);
+ if (uctrl == NULL)
+ return NULL;
uctrl->sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
if (uctrl->sock < 0) {
@@ -84,6 +94,17 @@ struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socke
/* translate leading '@' to abstract namespace */
if (uctrl->saddr.sun_path[0] == '@')
uctrl->saddr.sun_path[0] = '\0';
+ return uctrl;
+}
+
+struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd)
+{
+ struct udev_ctrl *uctrl;
+
+ uctrl = udev_ctrl_new(udev);
+ if (uctrl == NULL)
+ return NULL;
+ uctrl->sock = fd;
return uctrl;
}
@@ -91,16 +112,18 @@ struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socke
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl)
{
int err;
- const int feature_on = 1;
-
- err= bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen);
- if (err < 0) {
- err(uctrl->udev, "bind failed: %m\n");
- return err;
+ const int on = 1;
+
+ if (uctrl->addrlen > 0) {
+ err = bind(uctrl->sock, (struct sockaddr *)&uctrl->saddr, uctrl->addrlen);
+ if (err < 0) {
+ err(uctrl->udev, "bind failed: %m\n");
+ return err;
+ }
}
/* enable receiving of the sender credentials */
- setsockopt(uctrl->sock, SOL_SOCKET, SO_PASSCRED, &feature_on, sizeof(feature_on));
+ setsockopt(uctrl->sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
return 0;
}
diff --git a/libudev/libudev-private.h b/libudev/libudev-private.h
index bd317933ba..10612560f9 100644
--- a/libudev/libudev-private.h
+++ b/libudev/libudev-private.h
@@ -125,6 +125,7 @@ int udev_monitor_send_device(struct udev_monitor *udev_monitor,
/* libudev-ctrl.c - daemon runtime setup */
struct udev_ctrl;
struct udev_ctrl *udev_ctrl_new_from_socket(struct udev *udev, const char *socket_path);
+struct udev_ctrl *udev_ctrl_new_from_fd(struct udev *udev, int fd);
int udev_ctrl_enable_receiving(struct udev_ctrl *uctrl);
struct udev_ctrl *udev_ctrl_ref(struct udev_ctrl *uctrl);
void udev_ctrl_unref(struct udev_ctrl *uctrl);
diff --git a/udev/udevd.c b/udev/udevd.c
index ef82f72d05..1871474ff9 100644
--- a/udev/udevd.c
+++ b/udev/udevd.c
@@ -1228,16 +1228,20 @@ int main(int argc, char *argv[])
if (write(STDERR_FILENO, 0, 0) < 0)
dup2(fd, STDERR_FILENO);
- udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
+ /* udevadm control socket */
+ if (sd_listen_fds(true) == 1 && sd_is_socket(SD_LISTEN_FDS_START, AF_LOCAL, SOCK_DGRAM, -1))
+ udev_ctrl = udev_ctrl_new_from_fd(udev, SD_LISTEN_FDS_START);
+ else
+ udev_ctrl = udev_ctrl_new_from_socket(udev, UDEV_CTRL_SOCK_PATH);
if (udev_ctrl == NULL) {
- fprintf(stderr, "error initializing control socket");
- err(udev, "error initializing udevd socket");
+ fprintf(stderr, "error initializing udev control socket");
+ err(udev, "error initializing udev control socket");
rc = 1;
goto exit;
}
if (udev_ctrl_enable_receiving(udev_ctrl) < 0) {
- fprintf(stderr, "error binding control socket, seems udevd is already running\n");
- err(udev, "error binding control socket, seems udevd is already running\n");
+ fprintf(stderr, "error binding udev control socket\n");
+ err(udev, "error binding udev control socket\n");
rc = 1;
goto exit;
}