The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxc/pull/2820

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
This file contains the files one needs to chown to successfully delegate
cgroup files to unprivileged users.

Signed-off-by: Christian Brauner <christian.brau...@ubuntu.com>
From 18aae901b695e7fccb8843c41888bac3e0b0f212 Mon Sep 17 00:00:00 2001
From: Christian Brauner <christian.brau...@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.brau...@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);
 };
 
 /*!
_______________________________________________
lxc-devel mailing list
lxc-devel@lists.linuxcontainers.org
http://lists.linuxcontainers.org/listinfo/lxc-devel

Reply via email to