]> xenbits.xensource.com Git - libvirt.git/commitdiff
Ensure systemd cgroup ownership is delegated to container with userns
authorRichard Weinberger <richard@nod.at>
Mon, 24 Feb 2014 12:23:33 +0000 (12:23 +0000)
committerDaniel P. Berrange <berrange@redhat.com>
Mon, 24 Feb 2014 15:35:47 +0000 (15:35 +0000)
This function is needed for user namespaces, where we need to chmod()
the cgroup to the initial uid/gid such that systemd is allowed to
use the cgroup.

Signed-off-by: Richard Weinberger <richard@nod.at>
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
src/libvirt_private.syms
src/lxc/lxc_cgroup.c
src/util/vircgroup.c
src/util/vircgroup.h

index 7b0ca980cd2b2e093fe7125bfe20cb3b21ed1553..4578f1b5991f70e3feb7d76d7aa0971e21e1ec78 100644 (file)
@@ -1067,6 +1067,7 @@ virCgroupSetMemory;
 virCgroupSetMemoryHardLimit;
 virCgroupSetMemorySoftLimit;
 virCgroupSetMemSwapHardLimit;
+virCgroupSetOwner;
 virCgroupSupportsCpuBW;
 
 
index cc0d5e8d08bde72aea62e9aa2562010c2c224c7a..39d955cd8cc2e34b6157e126fbb455d8f71e0647 100644 (file)
@@ -484,6 +484,18 @@ virCgroupPtr virLXCCgroupCreate(virDomainDefPtr def)
                             &cgroup) < 0)
         goto cleanup;
 
+    /* setup control group permissions for user namespace */
+    if (def->idmap.uidmap) {
+        if (virCgroupSetOwner(cgroup,
+                              def->idmap.uidmap[0].target,
+                              def->idmap.gidmap[0].target,
+                              (1 << VIR_CGROUP_CONTROLLER_SYSTEMD)) < 0) {
+            virCgroupFree(&cgroup);
+            cgroup = NULL;
+            goto cleanup;
+        }
+    }
+
 cleanup:
     return cgroup;
 }
index 2dba10c644855ccdfa26ef76d8c98cce58c80588..a8987b7510456bd6128efdac8c242b910c04a172 100644 (file)
@@ -3608,6 +3608,76 @@ cleanup:
 }
 
 
+int virCgroupSetOwner(virCgroupPtr cgroup,
+                      uid_t uid,
+                      gid_t gid,
+                      int controllers)
+{
+    int ret = -1;
+    size_t i;
+    char *base = NULL, *entry = NULL;
+    DIR *dh = NULL;
+
+    for (i = 0; i < VIR_CGROUP_CONTROLLER_LAST; i++) {
+        struct dirent *de;
+
+        if (!((1 << i) & controllers))
+            continue;
+
+        if (!cgroup->controllers[i].mountPoint)
+            continue;
+
+        if (virAsprintf(&base, "%s%s", cgroup->controllers[i].mountPoint,
+                        cgroup->controllers[i].placement) < 0)
+            goto cleanup;
+
+        if (!(dh = opendir(base))) {
+            virReportSystemError(errno,
+                                 _("Unable to open dir '%s'"), base);
+            goto cleanup;
+        }
+
+        while ((de = readdir(dh)) != NULL) {
+            if (STREQ(de->d_name, ".") ||
+                STREQ(de->d_name, ".."))
+                continue;
+
+            if (virAsprintf(&entry, "%s/%s", base, de->d_name) < 0)
+                goto cleanup;
+
+            if (chown(entry, uid, gid) < 0) {
+                virReportSystemError(errno,
+                                     _("cannot chown '%s' to (%u, %u)"),
+                                     entry, uid, gid);
+                goto cleanup;
+            }
+
+            VIR_FREE(entry);
+        }
+
+        if (chown(base, uid, gid) < 0) {
+            virReportSystemError(errno,
+                                 _("cannot chown '%s' to (%u, %u)"),
+                                 base, uid, gid);
+            goto cleanup;
+        }
+
+        VIR_FREE(base);
+        closedir(dh);
+        dh = NULL;
+    }
+
+    ret = 0;
+
+ cleanup:
+    if (dh)
+        closedir(dh);
+    VIR_FREE(entry);
+    VIR_FREE(base);
+    return ret;
+}
+
+
 /**
  * virCgroupSupportsCpuBW():
  * Check whether the host supports CFS bandwidth.
index 67478f5e6bc03f796959334151048c42922a1d7d..ecac9a0e3676c4d956a24571998d1c5f00b9809c 100644 (file)
@@ -249,4 +249,9 @@ int virCgroupIsolateMount(virCgroupPtr group,
 
 bool virCgroupSupportsCpuBW(virCgroupPtr cgroup);
 
+int virCgroupSetOwner(virCgroupPtr cgroup,
+                      uid_t uid,
+                      gid_t gid,
+                      int controllers);
+
 #endif /* __VIR_CGROUP_H__ */