Merge pull request #2820 from brauner/2019-01-31/cgfsng_sys/kernel/cgroup/delegate

cgroups: use of /sys/kernel/cgroup/delegate file
This commit is contained in:
Stéphane Graber 2019-02-01 12:38:14 +01:00 committed by GitHub
commit 9fb7aab8a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 17 deletions

View File

@ -820,6 +820,7 @@ static struct hierarchy *add_hierarchy(struct hierarchy ***h, char **clist, char
new->container_full_path = NULL;
new->monitor_full_path = NULL;
new->version = type;
new->cgroup2_chown = NULL;
newentry = append_null_to_list((void ***)h);
(*h)[newentry] = new;
@ -1640,13 +1641,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 +2523,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 +2671,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 +2751,13 @@ cleanup_on_err:
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 +2793,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 +2821,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)

View File

@ -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);

View File

@ -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;