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@xxxxxxxxxxxxxx> --- 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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list