[lxc-devel] [lxc/master] cgroups: use of /sys/kernel/cgroup/delegate file
brauner on Github
lxc-bot at linuxcontainers.org
Fri Feb 1 10:04:22 UTC 2019
A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 477 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20190201/e2bc5b8f/attachment.bin>
-------------- next part --------------
From 18aae901b695e7fccb8843c41888bac3e0b0f212 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brauner at ubuntu.com>
Date: Fri, 1 Feb 2019 10:57:49 +0100
Subject: [PATCH] cgroups: use of /sys/kernel/cgroup/delegate file
This file contains the files one needs to chown to successfully delegate
cgroup files to unprivileged users.
Signed-off-by: Christian Brauner <christian.brauner at ubuntu.com>
---
src/lxc/cgroups/cgfsng.c | 63 +++++++++++++++++++++++++++++++---------
src/lxc/cgroups/cgroup.c | 10 +++++--
src/lxc/cgroups/cgroup.h | 5 ++++
src/lxc/lxccontainer.h | 6 ++++
4 files changed, 67 insertions(+), 17 deletions(-)
diff --git a/src/lxc/cgroups/cgfsng.c b/src/lxc/cgroups/cgfsng.c
index c4fc65252..5f0684bdb 100644
--- a/src/lxc/cgroups/cgfsng.c
+++ b/src/lxc/cgroups/cgfsng.c
@@ -1640,13 +1640,11 @@ static int chown_cgroup_wrapper(void *data)
if (arg->hierarchies[i]->version != CGROUP2_SUPER_MAGIC)
continue;
- fullpath = must_make_path(path, "cgroup.subtree_control", NULL);
- (void)chowmod(fullpath, destuid, nsgid, 0664);
- free(fullpath);
-
- fullpath = must_make_path(path, "cgroup.threads", NULL);
- (void)chowmod(fullpath, destuid, nsgid, 0664);
- free(fullpath);
+ for (char **p = arg->hierarchies[i]->cgroup2_chown; p && *p; p++) {
+ fullpath = must_make_path(path, *p, NULL);
+ (void)chowmod(fullpath, destuid, nsgid, 0664);
+ free(fullpath);
+ }
}
return 0;
@@ -2524,10 +2522,40 @@ static bool cgroup_use_wants_controllers(const struct cgroup_ops *ops,
return true;
}
+static void cg_unified_delegate(char ***delegate)
+{
+ char *tmp;
+ int idx;
+ char *standard[] = {"cgroup.subtree_control", "cgroup.threads", NULL};
+
+ tmp = read_file("/sys/kernel/cgroup/delegate");
+ if (!tmp) {
+ for (char **p = standard; p && *p; p++) {
+ idx = append_null_to_list((void ***)delegate);
+ (*delegate)[idx] = must_copy_string(*p);
+ }
+ } else {
+ char *token;
+ lxc_iterate_parts (token, tmp, " \t\n") {
+ /*
+ * We always need to chown this for both cgroup and
+ * cgroup2.
+ */
+ if (strcmp(token, "cgroup.procs") == 0)
+ continue;
+
+ idx = append_null_to_list((void ***)delegate);
+ (*delegate)[idx] = must_copy_string(token);
+ }
+ free(tmp);
+ }
+}
+
/* At startup, parse_hierarchies finds all the info we need about cgroup
* mountpoints and current cgroups, and stores it in @d.
*/
-static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative)
+static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative,
+ bool unprivileged)
{
int ret;
char *basecginfo;
@@ -2642,8 +2670,11 @@ static bool cg_hybrid_init(struct cgroup_ops *ops, bool relative)
goto next;
new = add_hierarchy(&ops->hierarchies, controller_list, mountpoint, base_cgroup, type);
- if (type == CGROUP2_SUPER_MAGIC && !ops->unified)
+ if (type == CGROUP2_SUPER_MAGIC && !ops->unified) {
+ if (unprivileged)
+ cg_unified_delegate(&new->cgroup2_chown);
ops->unified = new;
+ }
continue;
@@ -2719,11 +2750,13 @@ static char *cg_unified_get_current_cgroup(bool relative)
return copy;
}
-static int cg_unified_init(struct cgroup_ops *ops, bool relative)
+static int cg_unified_init(struct cgroup_ops *ops, bool relative,
+ bool unprivileged)
{
int ret;
- char *mountpoint, *subtree_path;
+ char *mountpoint, *subtree_path, *tmp;
char **delegatable;
+ struct hierarchy *new;
char *base_cgroup = NULL;
ret = cg_is_pure_unified();
@@ -2759,7 +2792,9 @@ static int cg_unified_init(struct cgroup_ops *ops, bool relative)
* controllers per container.
*/
- add_hierarchy(&ops->hierarchies, delegatable, mountpoint, base_cgroup, CGROUP2_SUPER_MAGIC);
+ new = add_hierarchy(&ops->hierarchies, delegatable, mountpoint, base_cgroup, CGROUP2_SUPER_MAGIC);
+ if (!unprivileged)
+ cg_unified_delegate(&new->cgroup2_chown);
ops->cgroup_layout = CGROUP_LAYOUT_UNIFIED;
return CGROUP2_SUPER_MAGIC;
@@ -2785,14 +2820,14 @@ static bool cg_init(struct cgroup_ops *ops, struct lxc_conf *conf)
free(pin);
}
- ret = cg_unified_init(ops, relative);
+ ret = cg_unified_init(ops, relative, !lxc_list_empty(&conf->id_map));
if (ret < 0)
return false;
if (ret == CGROUP2_SUPER_MAGIC)
return true;
- return cg_hybrid_init(ops, relative);
+ return cg_hybrid_init(ops, relative, !lxc_list_empty(&conf->id_map));
}
__cgfsng_ops static bool cgfsng_data_init(struct cgroup_ops *ops)
diff --git a/src/lxc/cgroups/cgroup.c b/src/lxc/cgroups/cgroup.c
index f0d4e1eff..bf92bf298 100644
--- a/src/lxc/cgroups/cgroup.c
+++ b/src/lxc/cgroups/cgroup.c
@@ -82,12 +82,16 @@ void cgroup_exit(struct cgroup_ops *ops)
free(ops->container_cgroup);
for (it = ops->hierarchies; it && *it; it++) {
- char **ctrlr;
+ char **p;
- for (ctrlr = (*it)->controllers; ctrlr && *ctrlr; ctrlr++)
- free(*ctrlr);
+ for (p = (*it)->controllers; p && *p; p++)
+ free(*p);
free((*it)->controllers);
+ for (p = (*it)->cgroup2_chown; p && *p; p++)
+ free(*p);
+ free((*it)->cgroup2_chown);
+
free((*it)->mountpoint);
free((*it)->container_base_path);
free((*it)->container_full_path);
diff --git a/src/lxc/cgroups/cgroup.h b/src/lxc/cgroups/cgroup.h
index d4dcd506b..b5d4c42bc 100644
--- a/src/lxc/cgroups/cgroup.h
+++ b/src/lxc/cgroups/cgroup.h
@@ -81,6 +81,11 @@ typedef enum {
* CGROUP2_SUPER_MAGIC.
*/
struct hierarchy {
+ /*
+ * cgroup2 only: what files need to be chowned to delegate a cgroup to
+ * an unprivileged user.
+ */
+ char **cgroup2_chown;
char **controllers;
char *mountpoint;
char *container_base_path;
diff --git a/src/lxc/lxccontainer.h b/src/lxc/lxccontainer.h
index c46be521e..2dfe4040b 100644
--- a/src/lxc/lxccontainer.h
+++ b/src/lxc/lxccontainer.h
@@ -867,6 +867,12 @@ struct lxc_container {
*/
int (*umount)(struct lxc_container *c, const char *target,
unsigned long mountflags, struct lxc_mount *mnt);
+
+ /*!
+ * \brief Get a file descriptor from the container.
+ */
+ int (*ioctl)(struct lxc_container *c, unsigned int command,
+ unsigned int flags, void *data);
};
/*!
More information about the lxc-devel
mailing list