[libvirt] [PATCH v3]LXC: Helper function for checking permission of dir when userns enabled

Chen Hanxiao chenhanxiao at cn.fujitsu.com
Tue Sep 10 08:18:29 UTC 2013


From: Chen Hanxiao <chenhanxiao at cn.fujitsu.com>

If we enable userns, the process with uid/gid in idmap
should have enough permission to access dir we provided
for containers.
Currently, the debug log is very implicit
or misleading sometimes.
This patch will help clarify this for us
when using debug log or virsh.

v2: syntax-check clean

v3: reliable method for checking permission of dir

Signed-off-by: Chen Hanxiao <chenhanxiao at cn.fujitsu.com>
---
 src/lxc/lxc_container.c | 88 +++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/src/lxc/lxc_container.c b/src/lxc/lxc_container.c
index 8abaea0..9a05e30 100644
--- a/src/lxc/lxc_container.c
+++ b/src/lxc/lxc_container.c
@@ -110,6 +110,13 @@ struct __lxc_child_argv {
     int handshakefd;
 };
 
+typedef struct __lxc_userns_DirPermCheck_argv lxc_userns_DirPermCheck_argv_t;
+struct __lxc_userns_DirPermCheck_argv {
+    uid_t uid;
+    gid_t gid;
+    virDomainDefPtr vmDef;
+};
+
 static int lxcContainerMountFSBlock(virDomainFSDefPtr fs,
                                     const char *srcprefix);
 
@@ -1829,6 +1836,84 @@ lxcNeedNetworkNamespace(virDomainDefPtr def)
     return false;
 }
 
+static
+int lxcContainerCheckDirPermissionChild(void *argv)
+{
+    size_t i;
+    lxc_userns_DirPermCheck_argv_t *args = argv;
+    uid_t uid = args->uid;
+    uid_t gid = args->gid;
+    virDomainDefPtr vmDef = args->vmDef;
+    char *path;
+
+    if (virSetUIDGID(uid, gid, NULL, 0) < 0) {
+        virReportSystemError(errno, "%s",
+                              _("setuid or setgid failed"));
+        _exit(-1);
+    }
+
+    for (i = 0; i < vmDef->nfss; i++) {
+        path = vmDef->fss[i]->src;
+        if (access(path, R_OK) || access(path, W_OK) || virFileIsExecutable(path)) {
+            VIR_DEBUG("Src dir '%s' does not belong to uid/gid: %d/%d",
+                      vmDef->fss[i]->src, uid, gid);
+            _exit(-1);
+        }
+    }
+
+    _exit(0);
+}
+
+/*
+ * Helper function for helping check
+ * whether we have enough privilege
+ * to operate the source dir when userns enabled
+ * @vmDef: pointer to vm definition structure
+ * Returns 0 on success or -1 in case of error
+ */
+static int
+lxcContainerCheckDirPermission(virDomainDefPtr vmDef)
+{
+    uid_t uid;
+    gid_t gid;
+    int cpid = 0;
+    int status;
+    char *childStack;
+    char *stack;
+    int flags =  SIGCHLD;
+
+    uid = vmDef->idmap.uidmap[0].target;
+    gid = vmDef->idmap.gidmap[0].target;
+
+    lxc_userns_DirPermCheck_argv_t args = {
+        .uid = uid,
+        .gid = gid,
+        .vmDef = vmDef
+    };
+
+    if (VIR_ALLOC_N(stack, getpagesize() * 4) < 0)
+        return -1;
+
+    childStack = stack + (getpagesize() * 4);
+    cpid = clone(lxcContainerCheckDirPermissionChild, childStack, flags, &args);
+    VIR_FREE(stack);
+    if (cpid < 0) {
+        virReportSystemError(errno, "%s",
+                             _("Unable to clone to check permission of directory"));
+        return -1;
+    } else if (virProcessWait(cpid, &status) < 0) {
+        return -1;
+    }
+
+    if (WEXITSTATUS(status) != 0) {
+        virReportSystemError(errno, "%s",
+                             _("Check the permission of source dir provided for container"));
+        return -1;
+    }
+
+    return 0;
+}
+
 /**
  * lxcContainerStart:
  * @def: pointer to virtual machine structure
@@ -1880,6 +1965,9 @@ int lxcContainerStart(virDomainDefPtr def,
         if (userns_supported()) {
             VIR_DEBUG("Enable user namespace");
             cflags |= CLONE_NEWUSER;
+            if (lxcContainerCheckDirPermission(def) < 0) {
+                return -1;
+            }
         } else {
             virReportSystemError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
                                  _("Kernel doesn't support user namespace"));
-- 
1.8.2.1




More information about the libvir-list mailing list