From e1d32bb9558179147b0217ba09fc26376a705849 Mon Sep 17 00:00:00 2001 From: Gao feng Date: Fri, 7 Jun 2013 15:12:22 +0800 Subject: [PATCH] LXC: Creating devices for container on host side 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 --- src/lxc/lxc_container.c | 86 +++++++++++++-------------------- src/lxc/lxc_controller.c | 100 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+), 52 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index d4faf3c785..d9734b50ff 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -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 */ diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 0ba6a90e21..be6f6ebbd1 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -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; -- GitLab