From: Richard Weinberger <richard(a)nod.at>
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(a)nod.at>
Signed-off-by: Daniel P. Berrange <berrange(a)redhat.com>
Changed in v3:
- Centralized all error reporting
- Use virReportSystemError not VIR_WARN/VIR_ERROR
---
src/libvirt_private.syms | 1 +
src/lxc/lxc_cgroup.c | 12 +++++++++
src/util/vircgroup.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++
src/util/vircgroup.h | 5 ++++
4 files changed, 88 insertions(+)
diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms
index 0b28bac..cfa9f75 100644
--- a/src/libvirt_private.syms
+++ b/src/libvirt_private.syms
@@ -1056,6 +1056,7 @@ virCgroupSetMemory;
virCgroupSetMemoryHardLimit;
virCgroupSetMemorySoftLimit;
virCgroupSetMemSwapHardLimit;
+virCgroupSetOwner;
virCgroupSupportsCpuBW;
diff --git a/src/lxc/lxc_cgroup.c b/src/lxc/lxc_cgroup.c
index cc0d5e8..39d955c 100644
--- a/src/lxc/lxc_cgroup.c
+++ b/src/lxc/lxc_cgroup.c
@@ -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;
}
diff --git a/src/util/vircgroup.c b/src/util/vircgroup.c
index a6d60c5..18c891c 100644
--- a/src/util/vircgroup.c
+++ b/src/util/vircgroup.c
@@ -3253,6 +3253,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.
diff --git a/src/util/vircgroup.h b/src/util/vircgroup.h
index a70eb18..38d94f3 100644
--- a/src/util/vircgroup.h
+++ b/src/util/vircgroup.h
@@ -225,4 +225,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__ */
--
1.8.5.3