[libvirt] [PATCH 1/7] LXC: Setup disks for container on host side

Since mknod in container is forbidden, we should setup disks on host side. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_container.c | 98 ------------------------------------------------ src/lxc/lxc_controller.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 94 insertions(+), 98 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index fcd9b74..caad02b 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -1367,100 +1367,6 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef, } -static int lxcContainerSetupDisk(virDomainDefPtr vmDef, - virDomainDiskDefPtr def, - virSecurityManagerPtr securityDriver) -{ - char *src = NULL; - char *dst = NULL; - int ret = -1; - struct stat sb; - mode_t mode; - char *tmpsrc = def->src; - - if (def->type != VIR_DOMAIN_DISK_TYPE_BLOCK) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Can't setup disk for non-block device")); - goto cleanup; - } - if (def->src == NULL) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Can't setup disk without media")); - goto cleanup; - } - - if (virAsprintf(&src, "/.oldroot/%s", def->src) < 0) - goto cleanup; - - if (virAsprintf(&dst, "/dev/%s", def->dst) < 0) - goto cleanup; - - if (stat(src, &sb) < 0) { - virReportSystemError(errno, - _("Unable to access %s"), def->src); - goto cleanup; - } - - if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Disk source %s must be a character/block device"), - def->src); - goto cleanup; - } - - mode = 0700; - if (S_ISCHR(sb.st_mode)) - mode |= S_IFCHR; - else - mode |= S_IFBLK; - - /* Yes, the device name we're creating may not - * actually correspond to the major:minor number - * we're using, but we've no other option at this - * time. Just have to hope that containerized apps - * don't get upset that the major:minor is different - * to that normally implied by the device name - */ - VIR_DEBUG("Creating dev %s (%d,%d) from %s", - dst, major(sb.st_rdev), minor(sb.st_rdev), src); - if (mknod(dst, mode, sb.st_rdev) < 0) { - virReportSystemError(errno, - _("Unable to create device %s"), - dst); - goto cleanup; - } - /* Labelling normally operates on src, but we need - * to actally label the dst here, so hack the config */ - def->src = dst; - if (virSecurityManagerSetImageLabel(securityDriver, vmDef, def) < 0) - goto cleanup; - - ret = 0; - -cleanup: - def->src = tmpsrc; - VIR_FREE(src); - VIR_FREE(dst); - return ret; -} - -static int lxcContainerSetupAllDisks(virDomainDefPtr vmDef, - virSecurityManagerPtr securityDriver) -{ - size_t i; - VIR_DEBUG("Setting up disks"); - - for (i = 0; i < vmDef->ndisks; i++) { - if (lxcContainerSetupDisk(vmDef, vmDef->disks[i], - securityDriver) < 0) - return -1; - } - - VIR_DEBUG("Setup all disks"); - return 0; -} - - static int lxcContainerSetupHostdevSubsysUSB(virDomainDefPtr vmDef, virDomainHostdevDefPtr def, virSecurityManagerPtr securityDriver) @@ -1837,10 +1743,6 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef, if (lxcContainerMountAllFS(vmDef, sec_mount_options) < 0) goto cleanup; - /* Sets up any extra disks from guest config */ - if (lxcContainerSetupAllDisks(vmDef, securityDriver) < 0) - goto cleanup; - /* Sets up any extra host devices from guest config */ if (lxcContainerSetupAllHostdevs(vmDef, securityDriver) < 0) goto cleanup; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 3f3d93b..e9d2848 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1309,6 +1309,97 @@ cleanup: } +static int virLXCControllerSetupDisk(virLXCControllerPtr ctrl, + virDomainDiskDefPtr def, + virSecurityManagerPtr securityDriver) +{ + char *dst = NULL; + int ret = -1; + struct stat sb; + mode_t mode; + char *tmpsrc = def->src; + + if (def->type != VIR_DOMAIN_DISK_TYPE_BLOCK) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Can't setup disk for non-block device")); + goto cleanup; + } + if (def->src == NULL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Can't setup disk without media")); + goto cleanup; + } + + if (virAsprintf(&dst, "/%s/%s.dev/%s", + LXC_STATE_DIR, ctrl->def->name, def->dst) < 0) + goto cleanup; + + if (stat(def->src, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access %s"), def->src); + goto cleanup; + } + + if (!S_ISCHR(sb.st_mode) && !S_ISBLK(sb.st_mode)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Disk source %s must be a character/block device"), + def->src); + goto cleanup; + } + + mode = 0700; + if (S_ISCHR(sb.st_mode)) + mode |= S_IFCHR; + else + mode |= S_IFBLK; + + /* Yes, the device name we're creating may not + * actually correspond to the major:minor number + * we're using, but we've no other option at this + * time. Just have to hope that containerized apps + * don't get upset that the major:minor is different + * to that normally implied by the device name + */ + VIR_DEBUG("Creating dev %s (%d,%d) from %s", + dst, major(sb.st_rdev), minor(sb.st_rdev), def->src); + if (mknod(dst, mode, sb.st_rdev) < 0) { + virReportSystemError(errno, + _("Unable to create device %s"), + dst); + goto cleanup; + } + + /* Labelling normally operates on src, but we need + * to actally label the dst here, so hack the config */ + def->src = dst; + if (virSecurityManagerSetImageLabel(securityDriver, ctrl->def, def) < 0) + goto cleanup; + + ret = 0; + +cleanup: + def->src = tmpsrc; + VIR_FREE(dst); + return ret; +} + +static int virLXCControllerSetupAllDisks(virLXCControllerPtr ctrl) +{ + size_t i; + VIR_DEBUG("Setting up disks"); + + for (i = 0; i < ctrl->def->ndisks; i++) { + if (virLXCControllerSetupDisk(ctrl, ctrl->def->disks[i], + ctrl->securityManager) < 0) + return -1; + } + + VIR_DEBUG("Setup all disks"); + return 0; +} + + + /** * virLXCControllerMoveInterfaces * @nveths: number of interfaces @@ -1724,6 +1815,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (virLXCControllerPopulateDevices(ctrl) < 0) goto cleanup; + if (virLXCControllerSetupAllDisks(ctrl) < 0) + goto cleanup; + if (virLXCControllerSetupFuse(ctrl) < 0) goto cleanup; -- 1.8.3.1

These disk devices are created for container, the owner should be the root user of container. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_controller.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index e9d2848..38b632e 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1369,6 +1369,9 @@ static int virLXCControllerSetupDisk(virLXCControllerPtr ctrl, goto cleanup; } + if (virLXCControllerChown(ctrl, dst) < 0) + goto cleanup; + /* Labelling normally operates on src, but we need * to actally label the dst here, so hack the config */ def->src = dst; -- 1.8.3.1

lxc driver will use this function to change the owner of hot added devices. Move virLXCControllerChown to lxc_container.c and Rename it to lxcContainerChown. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_container.c | 21 +++++++++++++++++++++ src/lxc/lxc_container.h | 2 ++ src/lxc/lxc_controller.c | 33 ++++++--------------------------- 3 files changed, 29 insertions(+), 27 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index caad02b..6bc259b 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -2116,3 +2116,24 @@ int lxcContainerAvailable(int features) VIR_DEBUG("container support is enabled"); return 0; } + +int lxcContainerChown(virDomainDefPtr def, const char *path) +{ + uid_t uid; + gid_t gid; + + if (!def->idmap.uidmap) + return 0; + + uid = def->idmap.uidmap[0].target; + gid = def->idmap.gidmap[0].target; + + if (chown(path, uid, gid) < 0) { + virReportSystemError(errno, + _("Failed to change owner of %s to %u:%u"), + path, uid, gid); + return -1; + } + + return 0; +} diff --git a/src/lxc/lxc_container.h b/src/lxc/lxc_container.h index 6f270d7..0e3b591 100644 --- a/src/lxc/lxc_container.h +++ b/src/lxc/lxc_container.h @@ -67,4 +67,6 @@ int lxcContainerSetupHostdevCapsMakePath(const char *dev); virArch lxcContainerGetAlt32bitArch(virArch arch); +int lxcContainerChown(virDomainDefPtr def, const char *path); + #endif /* LXC_CONTAINER_H */ diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 38b632e..4907af4 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1113,27 +1113,6 @@ cleanup2: return rc; } -static int -virLXCControllerChown(virLXCControllerPtr ctrl, char *path) -{ - uid_t uid; - gid_t gid; - - if (!ctrl->def->idmap.uidmap) - return 0; - - uid = ctrl->def->idmap.uidmap[0].target; - gid = ctrl->def->idmap.gidmap[0].target; - - if (chown(path, uid, gid) < 0) { - virReportSystemError(errno, - _("Failed to change owner of %s to %u:%u"), - path, uid, gid); - return -1; - } - - return 0; -} static int virLXCControllerSetupUsernsMap(virDomainIdMapEntryPtr map, @@ -1248,7 +1227,7 @@ static int virLXCControllerSetupDev(virLXCControllerPtr ctrl) goto cleanup; } - if (virLXCControllerChown(ctrl, dev) < 0) + if (lxcContainerChown(ctrl->def, dev) < 0) goto cleanup; ret = 0; @@ -1296,7 +1275,7 @@ static int virLXCControllerPopulateDevices(virLXCControllerPtr ctrl) goto cleanup; } - if (virLXCControllerChown(ctrl, path) < 0) + if (lxcContainerChown(ctrl->def, path) < 0) goto cleanup; VIR_FREE(path); @@ -1369,7 +1348,7 @@ static int virLXCControllerSetupDisk(virLXCControllerPtr ctrl, goto cleanup; } - if (virLXCControllerChown(ctrl, dst) < 0) + if (lxcContainerChown(ctrl->def, dst) < 0) goto cleanup; /* Labelling normally operates on src, but we need @@ -1627,8 +1606,8 @@ virLXCControllerSetupDevPTS(virLXCControllerPtr ctrl) goto cleanup; } - if ((virLXCControllerChown(ctrl, ctrl->devptmx) < 0) || - (virLXCControllerChown(ctrl, devpts) < 0)) + if ((lxcContainerChown(ctrl->def, ctrl->devptmx) < 0) || + (lxcContainerChown(ctrl->def, devpts) < 0)) goto cleanup; ret = 0; @@ -1666,7 +1645,7 @@ virLXCControllerSetupConsoles(virLXCControllerPtr ctrl, } /* Change the owner of tty device to the root user of container */ - if (virLXCControllerChown(ctrl, ttyHostPath) < 0) + if (lxcContainerChown(ctrl->def, ttyHostPath) < 0) goto cleanup; VIR_FREE(ttyHostPath); -- 1.8.3.1

The owner of this disk device should be the root user of container. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_driver.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index 1279edf..bd92135 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3258,6 +3258,10 @@ lxcDomainAttachDeviceDiskLive(virLXCDriverPtr driver, dst); goto cleanup; } + + if (lxcContainerChown(vm->def, dst) < 0) + goto cleanup; + created = true; /* Labelling normally operates on src, but we need -- 1.8.3.1

Otherwise the container will fail to start if we enable user namespace, since there is no rights to do mknod in uninit user namespace. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_container.c | 263 --------------------------------------- src/lxc/lxc_controller.c | 313 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 313 insertions(+), 263 deletions(-) diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c index 6bc259b..955ad41 100644 --- a/src/lxc/lxc_container.c +++ b/src/lxc/lxc_container.c @@ -1367,72 +1367,6 @@ static int lxcContainerMountAllFS(virDomainDefPtr vmDef, } -static int lxcContainerSetupHostdevSubsysUSB(virDomainDefPtr vmDef, - virDomainHostdevDefPtr def, - virSecurityManagerPtr securityDriver) -{ - int ret = -1; - char *src = NULL; - char *dstdir = NULL; - char *dstfile = NULL; - struct stat sb; - mode_t mode; - - if (virAsprintf(&dstdir, USB_DEVFS "/%03d", - def->source.subsys.u.usb.bus) < 0) - goto cleanup; - - if (virAsprintf(&dstfile, "%s/%03d", - dstdir, - def->source.subsys.u.usb.device) < 0) - goto cleanup; - - if (virAsprintf(&src, "/.oldroot/%s", dstfile) < 0) - goto cleanup; - - if (stat(src, &sb) < 0) { - virReportSystemError(errno, - _("Unable to access %s"), src); - goto cleanup; - } - - if (!S_ISCHR(sb.st_mode)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("USB source %s was not a character device"), - src); - goto cleanup; - } - - mode = 0700 | S_IFCHR; - - if (virFileMakePath(dstdir) < 0) { - virReportSystemError(errno, - _("Unable to create %s"), dstdir); - goto cleanup; - } - - VIR_DEBUG("Creating dev %s (%d,%d)", - dstfile, major(sb.st_rdev), minor(sb.st_rdev)); - if (mknod(dstfile, mode, sb.st_rdev) < 0) { - virReportSystemError(errno, - _("Unable to create device %s"), - dstfile); - goto cleanup; - } - - if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) - goto cleanup; - - ret = 0; - -cleanup: - VIR_FREE(src); - VIR_FREE(dstfile); - VIR_FREE(dstdir); - return ret; -} - - int lxcContainerSetupHostdevCapsMakePath(const char *dev) { int ret = -1; @@ -1459,199 +1393,6 @@ cleanup: } -static int lxcContainerSetupHostdevCapsStorage(virDomainDefPtr vmDef, - virDomainHostdevDefPtr def, - virSecurityManagerPtr securityDriver) -{ - char *src = NULL; - int ret = -1; - struct stat sb; - mode_t mode; - char *dev = def->source.caps.u.storage.block; - - if (dev == NULL) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Missing storage host block path")); - goto cleanup; - } - - if (virAsprintf(&src, "/.oldroot/%s", dev) < 0) - goto cleanup; - - if (stat(src, &sb) < 0) { - virReportSystemError(errno, - _("Unable to access %s"), - src); - goto cleanup; - } - - if (!S_ISBLK(sb.st_mode)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Storage source %s must be a block device"), - dev); - goto cleanup; - } - - if (lxcContainerSetupHostdevCapsMakePath(dev) < 0) { - virReportError(errno, - _("Failed to create directory for device %s"), - dev); - goto cleanup; - } - - mode = 0700 | S_IFBLK; - - VIR_DEBUG("Creating dev %s (%d,%d)", dev, - major(sb.st_rdev), minor(sb.st_rdev)); - if (mknod(dev, mode, sb.st_rdev) < 0) { - virReportSystemError(errno, - _("Unable to create device %s"), - dev); - goto cleanup; - } - - if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) - goto cleanup; - - ret = 0; - -cleanup: - VIR_FREE(src); - return ret; -} - - -static int lxcContainerSetupHostdevCapsMisc(virDomainDefPtr vmDef, - virDomainHostdevDefPtr def, - virSecurityManagerPtr securityDriver) -{ - char *src = NULL; - int ret = -1; - struct stat sb; - mode_t mode; - char *dev = def->source.caps.u.misc.chardev; - - if (dev == NULL) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("Missing storage host block path")); - goto cleanup; - } - - if (virAsprintf(&src, "/.oldroot/%s", dev) < 0) - goto cleanup; - - if (stat(src, &sb) < 0) { - virReportSystemError(errno, - _("Unable to access %s"), - src); - goto cleanup; - } - - if (!S_ISCHR(sb.st_mode)) { - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Storage source %s must be a character device"), - dev); - goto cleanup; - } - - if (lxcContainerSetupHostdevCapsMakePath(dev) < 0) { - virReportError(errno, - _("Failed to create directory for device %s"), - dev); - goto cleanup; - } - - mode = 0700 | S_IFCHR; - - VIR_DEBUG("Creating dev %s (%d,%d)", dev, - major(sb.st_rdev), minor(sb.st_rdev)); - if (mknod(dev, mode, sb.st_rdev) < 0) { - virReportSystemError(errno, - _("Unable to create device %s"), - dev); - goto cleanup; - } - - if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) - goto cleanup; - - ret = 0; - -cleanup: - VIR_FREE(src); - return ret; -} - -static int lxcContainerSetupHostdevSubsys(virDomainDefPtr vmDef, - virDomainHostdevDefPtr def, - virSecurityManagerPtr securityDriver) -{ - switch (def->source.subsys.type) { - case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: - return lxcContainerSetupHostdevSubsysUSB(vmDef, def, securityDriver); - - default: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported host device mode %s"), - virDomainHostdevSubsysTypeToString(def->source.subsys.type)); - return -1; - } -} - - -static int lxcContainerSetupHostdevCaps(virDomainDefPtr vmDef, - virDomainHostdevDefPtr def, - virSecurityManagerPtr securityDriver) -{ - switch (def->source.subsys.type) { - case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: - return lxcContainerSetupHostdevCapsStorage(vmDef, def, securityDriver); - - case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: - return lxcContainerSetupHostdevCapsMisc(vmDef, def, securityDriver); - - case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET: - return 0; // case is handled in virLXCControllerMoveInterfaces - - default: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported host device mode %s"), - virDomainHostdevCapsTypeToString(def->source.subsys.type)); - return -1; - } -} - - -static int lxcContainerSetupAllHostdevs(virDomainDefPtr vmDef, - virSecurityManagerPtr securityDriver) -{ - size_t i; - VIR_DEBUG("Setting up hostdevs"); - - for (i = 0; i < vmDef->nhostdevs; i++) { - virDomainHostdevDefPtr def = vmDef->hostdevs[i]; - switch (def->mode) { - case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: - if (lxcContainerSetupHostdevSubsys(vmDef, def, securityDriver) < 0) - return -1; - break; - case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: - if (lxcContainerSetupHostdevCaps(vmDef, def, securityDriver) < 0) - return -1; - break; - default: - virReportError(VIR_ERR_CONFIG_UNSUPPORTED, - _("Unsupported host device mode %s"), - virDomainHostdevModeTypeToString(def->mode)); - return -1; - } - } - - VIR_DEBUG("Setup all hostdevs"); - return 0; -} - - /* Got a FS mapped to /, we're going the pivot_root * approach to do a better-chroot-than-chroot * this is based on this thread http://lkml.org/lkml/2008/3/5/29 @@ -1743,10 +1484,6 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef, if (lxcContainerMountAllFS(vmDef, sec_mount_options) < 0) goto cleanup; - /* Sets up any extra host devices from guest config */ - if (lxcContainerSetupAllHostdevs(vmDef, securityDriver) < 0) - goto cleanup; - /* Gets rid of all remaining mounts from host OS, including /.oldroot itself */ if (lxcContainerUnmountSubtree("/.oldroot", true) < 0) goto cleanup; diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index 4907af4..dbb053a 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1288,6 +1288,316 @@ cleanup: } +static int +virLXCControllerSetupHostdevSubsysUSB(virDomainDefPtr vmDef, + virDomainHostdevDefPtr def, + virSecurityManagerPtr securityDriver) +{ + int ret = -1; + char *src = NULL; + char *dstdir = NULL; + char *dstfile = NULL; + char *vroot = NULL; + struct stat sb; + mode_t mode; + + if (virAsprintf(&src, USB_DEVFS "/%03d/%03d", + def->source.subsys.u.usb.bus, + def->source.subsys.u.usb.device) < 0) + goto cleanup; + + if (virAsprintf(&vroot, "/%s/%s.dev/bus/usb/", + LXC_STATE_DIR, vmDef->name) < 0) + goto cleanup; + + if (virAsprintf(&dstdir, "%s/%03d/", vroot, + def->source.subsys.u.usb.bus) < 0) + goto cleanup; + + if (virAsprintf(&dstfile, "%s/%03d", dstdir, + def->source.subsys.u.usb.device) < 0) + goto cleanup; + + if (stat(src, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access %s"), src); + goto cleanup; + } + + if (!S_ISCHR(sb.st_mode)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("USB source %s was not a character device"), + src); + goto cleanup; + } + + mode = 0700 | S_IFCHR; + + if (virFileMakePath(dstdir) < 0) { + virReportSystemError(errno, + _("Unable to create %s"), dstdir); + goto cleanup; + } + + VIR_DEBUG("Creating dev %s (%d,%d)", + dstfile, major(sb.st_rdev), minor(sb.st_rdev)); + if (mknod(dstfile, mode, sb.st_rdev) < 0) { + virReportSystemError(errno, + _("Unable to create device %s"), + dstfile); + goto cleanup; + } + + if (virSecurityManagerSetHostdevLabel(securityDriver, + vmDef, def, vroot) < 0) + goto cleanup; + + ret = 0; + +cleanup: + VIR_FREE(src); + VIR_FREE(dstfile); + VIR_FREE(dstdir); + VIR_FREE(vroot); + return ret; +} + + +static int +virLXCControllerSetupHostdevCapsStorage(virDomainDefPtr vmDef, + virDomainHostdevDefPtr def, + virSecurityManagerPtr securityDriver) +{ + char *dst = NULL; + char *path = NULL; + int len = 0; + int ret = -1; + struct stat sb; + mode_t mode; + char *dev = def->source.caps.u.storage.block; + + if (dev == NULL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Missing storage host block path")); + goto cleanup; + } + + if (VIR_STRDUP(path, dev) < 0) + goto cleanup; + + while (*(path + len) == '/') + len++; + + if (virAsprintf(&dst, "/%s/%s.dev/%s", + LXC_STATE_DIR, vmDef->name, + strchr(path + len, '/')) < 0) + goto cleanup; + + if (stat(dev, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access %s"), + dev); + goto cleanup; + } + + if (!S_ISBLK(sb.st_mode)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Storage source %s must be a block device"), + dev); + goto cleanup; + } + + if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) { + virReportError(errno, + _("Failed to create directory for device %s"), + dev); + goto cleanup; + } + + mode = 0700 | S_IFBLK; + + VIR_DEBUG("Creating dev %s (%d,%d)", dst, + major(sb.st_rdev), minor(sb.st_rdev)); + if (mknod(dst, mode, sb.st_rdev) < 0) { + virReportSystemError(errno, + _("Unable to create device %s"), + dst); + goto cleanup; + } + + def->source.caps.u.storage.block = dst; + if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) + goto cleanup; + + ret = 0; + +cleanup: + def->source.caps.u.storage.block = dev; + VIR_FREE(dst); + VIR_FREE(path); + return ret; +} + + +static int +virLXCControllerSetupHostdevCapsMisc(virDomainDefPtr vmDef, + virDomainHostdevDefPtr def, + virSecurityManagerPtr securityDriver) +{ + char *dst = NULL; + char *path = NULL; + int len = 0; + int ret = -1; + struct stat sb; + mode_t mode; + char *dev = def->source.caps.u.misc.chardev; + + if (dev == NULL) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("Missing storage host block path")); + goto cleanup; + } + + if (VIR_STRDUP(path, dev) < 0) + goto cleanup; + + while (*(path + len) == '/') + len++; + + if (virAsprintf(&dst, "/%s/%s.dev/%s", + LXC_STATE_DIR, vmDef->name, + strchr(path + len, '/')) < 0) + goto cleanup; + + if (stat(dev, &sb) < 0) { + virReportSystemError(errno, + _("Unable to access %s"), + dev); + goto cleanup; + } + + if (!S_ISCHR(sb.st_mode)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Storage source %s must be a character device"), + dev); + goto cleanup; + } + + if (lxcContainerSetupHostdevCapsMakePath(dst) < 0) { + virReportError(errno, + _("Failed to create directory for device %s"), + dst); + goto cleanup; + } + + mode = 0700 | S_IFCHR; + + VIR_DEBUG("Creating dev %s (%d,%d)", dst, + major(sb.st_rdev), minor(sb.st_rdev)); + if (mknod(dst, mode, sb.st_rdev) < 0) { + virReportSystemError(errno, + _("Unable to create device %s"), + dev); + goto cleanup; + } + + def->source.caps.u.misc.chardev = dst; + if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) + goto cleanup; + + ret = 0; + +cleanup: + def->source.caps.u.misc.chardev = dev; + VIR_FREE(dst); + VIR_FREE(path); + return ret; +} + +static int +virLXCControllerSetupHostdevSubsys(virDomainDefPtr vmDef, + virDomainHostdevDefPtr def, + virSecurityManagerPtr securityDriver) +{ + switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB: + return virLXCControllerSetupHostdevSubsysUSB(vmDef, + def, + securityDriver); + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported host device mode %s"), + virDomainHostdevSubsysTypeToString(def->source.subsys.type)); + return -1; + } +} + + +static int +virLXCControllerSetupHostdevCaps(virDomainDefPtr vmDef, + virDomainHostdevDefPtr def, + virSecurityManagerPtr securityDriver) +{ + switch (def->source.subsys.type) { + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_STORAGE: + return virLXCControllerSetupHostdevCapsStorage(vmDef, + def, + securityDriver); + + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_MISC: + return virLXCControllerSetupHostdevCapsMisc(vmDef, + def, + securityDriver); + + case VIR_DOMAIN_HOSTDEV_CAPS_TYPE_NET: + return 0; // case is handled in virLXCControllerMoveInterfaces + + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported host device mode %s"), + virDomainHostdevCapsTypeToString(def->source.subsys.type)); + return -1; + } +} + + +static int +virLXCControllerSetupAllHostdevs(virLXCControllerPtr ctrl) +{ + size_t i; + virDomainDefPtr vmDef = ctrl->def; + virSecurityManagerPtr securityDriver = ctrl->securityManager; + VIR_DEBUG("Setting up hostdevs"); + + for (i = 0; i < vmDef->nhostdevs; i++) { + virDomainHostdevDefPtr def = vmDef->hostdevs[i]; + switch (def->mode) { + case VIR_DOMAIN_HOSTDEV_MODE_SUBSYS: + if (virLXCControllerSetupHostdevSubsys(vmDef, + def, + securityDriver) < 0) + return -1; + break; + case VIR_DOMAIN_HOSTDEV_MODE_CAPABILITIES: + if (virLXCControllerSetupHostdevCaps(vmDef, + def, + securityDriver) < 0) + return -1; + break; + default: + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Unsupported host device mode %s"), + virDomainHostdevModeTypeToString(def->mode)); + return -1; + } + } + + VIR_DEBUG("Setup all hostdevs"); + return 0; +} + + static int virLXCControllerSetupDisk(virLXCControllerPtr ctrl, virDomainDiskDefPtr def, virSecurityManagerPtr securityDriver) @@ -1800,6 +2110,9 @@ virLXCControllerRun(virLXCControllerPtr ctrl) if (virLXCControllerSetupAllDisks(ctrl) < 0) goto cleanup; + if (virLXCControllerSetupAllHostdevs(ctrl) < 0) + goto cleanup; + if (virLXCControllerSetupFuse(ctrl) < 0) goto cleanup; -- 1.8.3.1

These host devices are created for container, the owner should be the root user of container. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_controller.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lxc/lxc_controller.c b/src/lxc/lxc_controller.c index dbb053a..ce1f941 100644 --- a/src/lxc/lxc_controller.c +++ b/src/lxc/lxc_controller.c @@ -1348,6 +1348,9 @@ virLXCControllerSetupHostdevSubsysUSB(virDomainDefPtr vmDef, goto cleanup; } + if (lxcContainerChown(vmDef, dstfile) < 0) + goto cleanup; + if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, vroot) < 0) goto cleanup; @@ -1425,6 +1428,9 @@ virLXCControllerSetupHostdevCapsStorage(virDomainDefPtr vmDef, goto cleanup; } + if (lxcContainerChown(vmDef, dst) < 0) + goto cleanup; + def->source.caps.u.storage.block = dst; if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) goto cleanup; @@ -1501,6 +1507,9 @@ virLXCControllerSetupHostdevCapsMisc(virDomainDefPtr vmDef, goto cleanup; } + if (lxcContainerChown(vmDef, dst) < 0) + goto cleanup; + def->source.caps.u.misc.chardev = dst; if (virSecurityManagerSetHostdevLabel(securityDriver, vmDef, def, NULL) < 0) goto cleanup; -- 1.8.3.1

The owner of this host devices should be the root user of container. Signed-off-by: Gao feng <gaofeng@cn.fujitsu.com> --- src/lxc/lxc_driver.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/lxc/lxc_driver.c b/src/lxc/lxc_driver.c index bd92135..098051b 100644 --- a/src/lxc/lxc_driver.c +++ b/src/lxc/lxc_driver.c @@ -3513,6 +3513,9 @@ lxcDomainAttachDeviceHostdevSubsysUSBLive(virLXCDriverPtr driver, } created = true; + if (lxcContainerChown(vm->def, dstfile) < 0) + goto cleanup; + if (virSecurityManagerSetHostdevLabel(driver->securityManager, vm->def, def, vroot) < 0) goto cleanup; @@ -3610,6 +3613,9 @@ lxcDomainAttachDeviceHostdevStorageLive(virLXCDriverPtr driver, } created = true; + if (lxcContainerChown(vm->def, dst) < 0) + goto cleanup; + if (virSecurityManagerSetHostdevLabel(driver->securityManager, vm->def, def, vroot) < 0) goto cleanup; @@ -3715,6 +3721,9 @@ lxcDomainAttachDeviceHostdevMiscLive(virLXCDriverPtr driver, } created = true; + if (lxcContainerChown(vm->def, dst) < 0) + goto cleanup; + if (virSecurityManagerSetHostdevLabel(driver->securityManager, vm->def, def, vroot) < 0) goto cleanup; -- 1.8.3.1

On 07/15/2013 12:07 AM, Gao feng wrote:
Since mknod in container is forbidden, we should setup disks on host side.
It helps to send a 0/7 cover letter, with all your other messages in-reply-to the cover letter. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On 07/16/2013 04:28 AM, Eric Blake wrote:
On 07/15/2013 12:07 AM, Gao feng wrote:
Since mknod in container is forbidden, we should setup disks on host side.
It helps to send a 0/7 cover letter, with all your other messages in-reply-to the cover letter.
Yes, I will resend this serial of patch with cover. Thanks
participants (2)
-
Eric Blake
-
Gao feng