chiark / gitweb /
libudev: disable monitor inside a container
authorKay Sievers <kay@vrfy.org>
Wed, 18 Dec 2013 21:01:31 +0000 (22:01 +0100)
committerKay Sievers <kay@vrfy.org>
Wed, 18 Dec 2013 21:01:31 +0000 (22:01 +0100)
Uevents are events of the host, which should not leak into a container.
Containers do not support hotplug at the moment, and devices and uevents
are not namespace aware.

TODO
src/libudev/libudev-monitor.c

diff --git a/TODO b/TODO
index 1500d6b..8025169 100644 (file)
--- a/TODO
+++ b/TODO
@@ -1,10 +1,4 @@
 Bugfixes:
-* sort-out libudev's is_initialized logic for:
-  - enumerate devices:
-    - is_initialized is true if a database exists
-  - in-container devices:
-    - is_initialized is always false, because there is no database
-
 * enabling an instance unit creates a pointless link, and
   the unit will be started with getty@getty.service:
     $ systemctl enable getty@.service
index e07e462..4586b3d 100644 (file)
@@ -35,6 +35,7 @@
 #include "libudev.h"
 #include "libudev-private.h"
 #include "socket-util.h"
+#include "missing.h"
 
 /**
  * SECTION:libudev-monitor
@@ -105,6 +106,62 @@ static struct udev_monitor *udev_monitor_new(struct udev *udev)
         return udev_monitor;
 }
 
+/* we consider udev running when /dev is on devtmpfs */
+static bool udev_has_devtmpfs(struct udev *udev) {
+        struct file_handle *h;
+        int mount_id;
+        _cleanup_fclose_ FILE *f = NULL;
+        char line[LINE_MAX], *e;
+        int r;
+
+        h = alloca(MAX_HANDLE_SZ);
+
+        r = name_to_handle_at(AT_FDCWD, "/dev", h, &mount_id, 0);
+        if (r < 0)
+                return false;
+
+
+        f = fopen("/proc/self/mountinfo", "re");
+        if (!f)
+                return false;
+
+        FOREACH_LINE(line, f, return false) {
+                _cleanup_free_ char *opts = NULL;
+                int mid;
+
+                if (sscanf(line, "%i", &mid) != 1)
+                        continue;
+
+                if (mid != mount_id)
+                        continue;
+
+                e = strstr(line, " - ");
+                if (!e)
+                        continue;
+
+                /* accept any name that starts with the currently expected type */
+                if (startswith(e + 3, "devtmpfs"))
+                        return true;
+        }
+
+        return false;
+}
+
+/* we consider udev running when we have running udev service */
+static bool udev_has_service(struct udev *udev) {
+        struct udev_queue *queue;
+        bool active;
+
+        queue = udev_queue_new(udev);
+        if (!queue)
+                return false;
+
+        active = udev_queue_get_udev_is_active(queue);
+        udev_queue_unref(queue);
+
+        return active;
+}
+
 struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const char *name, int fd)
 {
         struct udev_monitor *udev_monitor;
@@ -127,8 +184,14 @@ struct udev_monitor *udev_monitor_new_from_netlink_fd(struct udev *udev, const c
          * is running. Uevents would otherwise broadcast the processing data
          * of the host into containers, which is not acceptable. Containers
          * will currently just not get any uevents.
+         *
+         * We clear the netlink multicast group here, so the socket will
+         * not receive any messages.
          */
-        
+        if (!udev_has_service(udev) && !udev_has_devtmpfs(udev)) {
+                udev_dbg(udev, "udev seems not to be active, disable the monitor\n");
+                group = 0;
+        }
 
         udev_monitor = udev_monitor_new(udev);
         if (udev_monitor == NULL)