]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
LXC: Creating devices for container on host side
authorGao feng <gaofeng@cn.fujitsu.com>
Fri, 7 Jun 2013 07:12:22 +0000 (15:12 +0800)
committerDaniel P. Berrange <berrange@redhat.com>
Tue, 2 Jul 2013 10:20:04 +0000 (11:20 +0100)
user namespace doesn't allow to create devices in
uninit userns. We should create devices on host side.

We first mount tmpfs on dev directroy under state dir
of container. then create devices under this dev dir.

Finally in container, mount the dev directroy created
on host to the /dev/ directroy of container.

Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com>
src/lxc/lxc_container.c
src/lxc/lxc_controller.c

index d4faf3c78516d948d5af3a6f13f3dec2d2025be5..d9734b50ff7a4c8e1c679b54fa3d28054707c8d4 100644 (file)
@@ -683,7 +683,7 @@ err:
 }
 
 
-static int lxcContainerMountBasicFS(char *sec_mount_options)
+static int lxcContainerMountBasicFS(void)
 {
     const struct {
         const char *src;
@@ -709,9 +709,8 @@ static int lxcContainerMountBasicFS(char *sec_mount_options)
 #endif
     };
     int i, rc = -1;
-    char *opts = NULL;
 
-    VIR_DEBUG("Mounting basic filesystems sec_mount_options=%s", sec_mount_options);
+    VIR_DEBUG("Mounting basic filesystems");
 
     for (i = 0; i < ARRAY_CARDINALITY(mnts); i++) {
         const char *srcpath = NULL;
@@ -750,31 +749,10 @@ static int lxcContainerMountBasicFS(char *sec_mount_options)
         }
     }
 
-    /*
-     * tmpfs is limited to 64kb, since we only have device nodes in there
-     * and don't want to DOS the entire OS RAM usage
-     */
-
-    if (virAsprintf(&opts,
-                    "mode=755,size=65536%s", sec_mount_options) < 0) {
-        virReportOOMError();
-        goto cleanup;
-    }
-
-    VIR_DEBUG("Mount devfs on /dev type=tmpfs flags=%x, opts=%s",
-              MS_NOSUID, opts);
-    if (mount("devfs", "/dev", "tmpfs", MS_NOSUID, opts) < 0) {
-        virReportSystemError(errno,
-                             _("Failed to mount %s on %s type %s (%s)"),
-                             "devfs", "/dev", "tmpfs", opts);
-        goto cleanup;
-    }
-
     rc = 0;
 
 cleanup:
     VIR_DEBUG("rc=%d", rc);
-    VIR_FREE(opts);
     return rc;
 }
 
@@ -811,6 +789,30 @@ static int lxcContainerMountProcFuse(virDomainDefPtr def ATTRIBUTE_UNUSED,
 }
 #endif
 
+static int lxcContainerMountFSDev(virDomainDefPtr def,
+                                  const char *stateDir)
+{
+    int ret;
+    char *path = NULL;
+
+    VIR_DEBUG("Mount /dev/ stateDir=%s", stateDir);
+
+    if ((ret = virAsprintf(&path, "/.oldroot/%s/%s.dev",
+                           stateDir, def->name)) < 0)
+        return ret;
+
+    VIR_DEBUG("Tring to move %s to /dev", path);
+
+    if ((ret = mount(path, "/dev", NULL, MS_MOVE, NULL)) < 0) {
+        virReportSystemError(errno,
+                             _("Failed to mount %s on /dev"),
+                             path);
+    }
+
+    VIR_FREE(path);
+    return ret;
+}
+
 static int lxcContainerMountFSDevPTS(virDomainDefPtr def,
                                      const char *stateDir)
 {
@@ -847,21 +849,9 @@ cleanup:
     return ret;
 }
 
-static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
+static int lxcContainerSetupDevices(char **ttyPaths, size_t nttyPaths)
 {
     size_t i;
-    const struct {
-        int maj;
-        int min;
-        mode_t mode;
-        const char *path;
-    } devs[] = {
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/dev/null" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/dev/zero" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/dev/full" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/dev/random" },
-        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/dev/urandom" },
-    };
     const struct {
         const char *src;
         const char *dst;
@@ -872,18 +862,6 @@ static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths)
         { "/proc/self/fd", "/dev/fd" },
     };
 
-    /* Populate /dev/ with a few important bits */
-    for (i = 0; i < ARRAY_CARDINALITY(devs); i++) {
-        dev_t dev = makedev(devs[i].maj, devs[i].min);
-        if (mknod(devs[i].path, S_IFCHR, dev) < 0 ||
-            chmod(devs[i].path, devs[i].mode)) {
-            virReportSystemError(errno,
-                                 _("Failed to make device %s"),
-                                 devs[i].path);
-            return -1;
-        }
-    }
-
     for (i = 0; i < ARRAY_CARDINALITY(links); i++) {
         if (symlink(links[i].src, links[i].dst) < 0) {
             virReportSystemError(errno,
@@ -1802,7 +1780,7 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
         goto cleanup;
 
     /* Mounts the core /proc, /sys, etc filesystems */
-    if (lxcContainerMountBasicFS(sec_mount_options) < 0)
+    if (lxcContainerMountBasicFS() < 0)
         goto cleanup;
 
     /* Mounts /proc/meminfo etc sysinfo */
@@ -1814,12 +1792,16 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
     if (virCgroupIsolateMount(cgroup, "/.oldroot/", sec_mount_options) < 0)
         goto cleanup;
 
+    /* Mounts /dev */
+    if (lxcContainerMountFSDev(vmDef, stateDir) < 0)
+        goto cleanup;
+
     /* Mounts /dev/pts */
     if (lxcContainerMountFSDevPTS(vmDef, stateDir) < 0)
         goto cleanup;
 
-    /* Populates device nodes in /dev/ */
-    if (lxcContainerPopulateDevices(ttyPaths, nttyPaths) < 0)
+    /* Setup device nodes in /dev/ */
+    if (lxcContainerSetupDevices(ttyPaths, nttyPaths) < 0)
         goto cleanup;
 
     /* Sets up any non-root mounts from guest config */
index 0ba6a90e21547234e049a30985850672164b811e..be6f6ebbd14ac57573ca0a93f0f96f318283c9fa 100644 (file)
@@ -1192,6 +1192,103 @@ cleanup:
     return ret;
 }
 
+static int virLXCControllerSetupDev(virLXCControllerPtr ctrl)
+{
+    char *mount_options = NULL;
+    char *opts = NULL;
+    char *dev = NULL;
+    int ret = -1;
+
+    VIR_DEBUG("Setting up /dev/ for container");
+
+    mount_options = virSecurityManagerGetMountOptions(ctrl->securityManager,
+                                                      ctrl->def);
+
+    if (virAsprintf(&dev, "/%s/%s.dev",
+                    LXC_STATE_DIR, ctrl->def->name) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    if (virFileMakePath(dev) < 0) {
+        virReportSystemError(errno,
+                             _("Failed to make path %s"), dev);
+        goto cleanup;
+    }
+
+    /*
+     * tmpfs is limited to 64kb, since we only have device nodes in there
+     * and don't want to DOS the entire OS RAM usage
+     */
+
+    if (virAsprintf(&opts,
+                    "mode=755,size=65536%s", mount_options) < 0) {
+        virReportOOMError();
+        goto cleanup;
+    }
+
+    VIR_DEBUG("Mount devfs on %s type=tmpfs flags=%x, opts=%s",
+              dev, MS_NOSUID, opts);
+    if (mount("devfs", dev, "tmpfs", MS_NOSUID, opts) < 0) {
+        virReportSystemError(errno,
+                             _("Failed to mount devfs on %s type %s (%s)"),
+                             dev, "tmpfs", opts);
+        goto cleanup;
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(opts);
+    VIR_FREE(mount_options);
+    VIR_FREE(dev);
+    return ret;
+}
+
+static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl)
+{
+    size_t i;
+    int ret = -1;
+    char *path = NULL;
+    const struct {
+        int maj;
+        int min;
+        mode_t mode;
+        const char *path;
+    } devs[] = {
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_NULL, 0666, "/null" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_ZERO, 0666, "/zero" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_FULL, 0666, "/full" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_RANDOM, 0666, "/random" },
+        { LXC_DEV_MAJ_MEMORY, LXC_DEV_MIN_URANDOM, 0666, "/urandom" },
+    };
+
+    if (virLXCControllerSetupDev(ctrl) < 0)
+        goto cleanup;
+
+    /* Populate /dev/ with a few important bits */
+    for (i = 0; i < ARRAY_CARDINALITY(devs); i++) {
+        if (virAsprintf(&path, "/%s/%s.dev/%s",
+                        LXC_STATE_DIR, ctrl->def->name, devs[i].path) < 0) {
+            virReportOOMError();
+            goto cleanup;
+        }
+
+        dev_t dev = makedev(devs[i].maj, devs[i].min);
+        if (mknod(path, S_IFCHR, dev) < 0 ||
+            chmod(path, devs[i].mode)) {
+            virReportSystemError(errno,
+                                 _("Failed to make device %s"),
+                                 path);
+            goto cleanup;
+        }
+        VIR_FREE(path);
+    }
+
+    ret = 0;
+cleanup:
+    VIR_FREE(path);
+    return ret;
+}
 
 
 /**
@@ -1594,6 +1691,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl)
     if (virLXCControllerSetupDevPTS(ctrl) < 0)
         goto cleanup;
 
+    if (virLXCControllerPopulateDevices(ctrl) < 0)
+        goto cleanup;
+
     if (virLXCControllerSetupFuse(ctrl) < 0)
         goto cleanup;