On 2013/03/13 19:02, Daniel P. Berrange wrote: > On Mon, Mar 11, 2013 at 02:26:50PM +0800, Gao feng wrote: >> user namespace doesn't allow to create devices in >> uninit userns. We should create devices on host side. >> >> Signed-off-by: Gao feng <gaofeng@xxxxxxxxxxxxxx> >> --- >> src/lxc/lxc_container.c | 47 +++++++-------------------- >> src/lxc/lxc_controller.c | 83 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 94 insertions(+), 36 deletions(-) > > We actually need this change independently of user namespaces. Currently > the cgroup devices setup we do allows 'mknod' permission, when it really > ought to be blocked. If we move the setup code into the controller then > we can fix the cgroup devices setup to block mknod too. > Yes, Agree with you. I will add this one into my patchset. >> diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c >> index 92af3e5..58d6ee5 100644 >> --- a/src/lxc/lxc_container.c >> +++ b/src/lxc/lxc_container.c >> @@ -681,22 +681,10 @@ static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root) >> return rc; >> } >> >> -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; >> } links[] = { >> @@ -706,18 +694,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, >> @@ -737,15 +713,6 @@ static int lxcContainerPopulateDevices(char **ttyPaths, size_t nttyPaths) >> _("Failed to bind /dev/pts/ptmx on to /dev/ptmx")); >> return -1; >> } >> - } else { >> - /* Legacy devpts, so we need to just use shared one */ >> - dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX); >> - if (mknod("/dev/ptmx", S_IFCHR, dev) < 0 || >> - chmod("/dev/ptmx", 0666)) { >> - virReportSystemError(errno, "%s", >> - _("Failed to make device /dev/ptmx")); >> - return -1; >> - } >> } >> >> for (i = 0 ; i < nttyPaths ; i++) { >> @@ -1988,8 +1955,8 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef, >> if (lxcContainerMountFSDevPTS(root) < 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 */ >> @@ -2306,6 +2273,14 @@ static int lxcContainerChild(void *data) >> goto cleanup; >> } >> >> + /* Wait for controller creating devices for container */ >> + if (lxcContainerWaitForContinue(argv->monitor) < 0) { >> + virReportSystemError(errno, "%s", >> + _("Failed to read the container continue message")); >> + goto cleanup; >> + } >> + VIR_DEBUG("Received container continue message, create devices success."); >> + >> ret = 0; >> cleanup: >> VIR_FREE(ttyPath); >> diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c >> index f17142f..c6f8c3b 100644 >> --- a/src/lxc/lxc_controller.c >> +++ b/src/lxc/lxc_controller.c >> @@ -1092,6 +1092,79 @@ cleanup: >> } >> >> >> +static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl) >> +{ >> + size_t i; >> + char *ptmx = NULL; >> + 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" }, >> + }; >> + virDomainFSDefPtr root = virDomainGetRootFilesystem(ctrl->def); >> + >> + if (root == NULL || root->src == NULL) >> + return 0; >> + >> + /* Populate /dev/ with a few important bits */ >> + for (i = 0 ; i < ARRAY_CARDINALITY(devs) ; i++) { >> + char *path = NULL; >> + if (virAsprintf(&path, "/proc/%llu/root/%s", >> + (unsigned long long)ctrl->initpid, >> + devs[i].path) < 0) { >> + virReportOOMError(); >> + return -1; >> + } >> + 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); >> + VIR_FREE(path); >> + return -1; >> + } >> + VIR_FREE(path); >> + } >> + >> + if (virAsprintf(&ptmx, "/proc/%llu/root/dev/pts/ptmx", >> + (unsigned long long)ctrl->initpid) < 0) { >> + virReportOOMError(); >> + return -1; >> + } >> + >> + if (access(ptmx, W_OK)) { >> + char *path = NULL; >> + if (virAsprintf(&path, "/proc/%llu/root/dev/ptmx", >> + (unsigned long long)ctrl->initpid) < 0) { >> + virReportOOMError(); >> + VIR_FREE(ptmx); >> + return -1; >> + } >> + /* Legacy devpts, so we need to just use shared one */ >> + dev_t dev = makedev(LXC_DEV_MAJ_TTY, LXC_DEV_MIN_PTMX); >> + if (mknod(path, S_IFCHR, dev) < 0 || >> + chmod(path, 0666)) { >> + virReportSystemError(errno, >> + _("Failed to make device %s"), path); >> + VIR_FREE(path); >> + VIR_FREE(ptmx); >> + return -1; >> + } >> + VIR_FREE(path); >> + } >> + VIR_FREE(ptmx); >> + return 0; >> +} >> + >> + >> /** >> * virLXCControllerMoveInterfaces >> * @nveths: number of interfaces >> @@ -1535,6 +1608,16 @@ virLXCControllerRun(virLXCControllerPtr ctrl) >> goto cleanup; >> } >> >> + /* Populate devices for container */ >> + if (virLXCControllerPopulateDevices(ctrl) < 0) >> + goto cleanup; > > We ought to be able to invoke this before lxcContainerStart, so > that we can avoid the send/wait continue bit > We have to wait for init task of container running. So we can populate devices at the right placement. -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list