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(a)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