]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
cgfs: switch to userns when removing cgroup
authorSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 2 Mar 2016 22:00:13 +0000 (14:00 -0800)
committerSerge Hallyn <serge.hallyn@ubuntu.com>
Wed, 2 Mar 2016 22:24:34 +0000 (14:24 -0800)
Otherwise unprivileged users may not have the privilege needed to
remove their cgroups.

Signed-off-by: Serge Hallyn <serge.hallyn@ubuntu.com>
src/lxc/cgfs.c
src/lxc/cgmanager.c
src/lxc/cgroup.c
src/lxc/cgroup.h

index 071060b5741320a8113cc13b7c9f8da4034cb56a..37ba3425dae3ed976ddf145d0204975f1a5d1957 100644 (file)
@@ -132,7 +132,8 @@ static void lxc_cgroup_mount_point_free(struct cgroup_mount_point *mp);
 static void lxc_cgroup_hierarchy_free(struct cgroup_hierarchy *h);
 static bool is_valid_cgroup(const char *name);
 static int create_cgroup(struct cgroup_mount_point *mp, const char *path);
-static int remove_cgroup(struct cgroup_mount_point *mp, const char *path, bool recurse);
+static int remove_cgroup(struct cgroup_mount_point *mp, const char *path, bool recurse,
+                               struct lxc_conf *conf);
 static char *cgroup_to_absolute_path(struct cgroup_mount_point *mp, const char *path, const char *suffix);
 static struct cgroup_process_info *find_info_for_subsystem(struct cgroup_process_info *info, const char *subsystem);
 static int do_cgroup_get(const char *cgroup_path, const char *sub_filename, char *value, size_t len);
@@ -150,7 +151,8 @@ static struct cgroup_meta_data *lxc_cgroup_put_meta(struct cgroup_meta_data *met
 
 /* free process membership information */
 static void lxc_cgroup_process_info_free(struct cgroup_process_info *info);
-static void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info);
+static void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info,
+                               struct lxc_conf *conf);
 
 static struct cgroup_ops cgfs_ops;
 
@@ -223,6 +225,20 @@ static int cgroup_rmdir(char *dirname)
        return failed ? -1 : 0;
 }
 
+static int rmdir_wrapper(void *data)
+{
+       char *path = data;
+
+       if (setresgid(0,0,0) < 0)
+               SYSERROR("Failed to setgid to 0");
+       if (setresuid(0,0,0) < 0)
+               SYSERROR("Failed to setuid to 0");
+       if (setgroups(0, NULL) < 0)
+               SYSERROR("Failed to clear groups");
+
+       return cgroup_rmdir(path);
+}
+
 static struct cgroup_meta_data *lxc_cgroup_load_meta()
 {
        const char *cgroup_use = NULL;
@@ -919,7 +935,7 @@ static struct cgroup_process_info *lxc_cgroupfs_create(const char *name, const c
                 * In that case, remove the cgroup from all previous hierarchies
                 */
                for (j = 0, info_ptr = base_info; j < i && info_ptr; info_ptr = info_ptr->next, j++) {
-                       r = remove_cgroup(info_ptr->designated_mount_point, info_ptr->created_paths[info_ptr->created_paths_count - 1], false);
+                       r = remove_cgroup(info_ptr->designated_mount_point, info_ptr->created_paths[info_ptr->created_paths_count - 1], false, NULL);
                        if (r < 0)
                                WARN("could not clean up cgroup we created when trying to create container");
                        free(info_ptr->created_paths[info_ptr->created_paths_count - 1]);
@@ -1077,7 +1093,7 @@ skip:
 out_initial_error:
        saved_errno = errno;
        free(path_so_far);
-       lxc_cgroup_process_info_free_and_remove(base_info);
+       lxc_cgroup_process_info_free_and_remove(base_info, NULL);
        lxc_free_array((void **)new_cgroup_paths, free);
        lxc_free_array((void **)new_cgroup_paths_sub, free);
        lxc_free_array((void **)cgroup_path_components, free);
@@ -1221,7 +1237,7 @@ void lxc_cgroup_process_info_free(struct cgroup_process_info *info)
 }
 
 /* free process membership information and remove cgroups that were created */
-void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info)
+void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info, struct lxc_conf *conf)
 {
        struct cgroup_process_info *next;
        char **pp;
@@ -1237,7 +1253,7 @@ void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info)
                         * '/lxc' cgroup in this container but another container
                         * is still running (for example)
                         */
-                       (void)remove_cgroup(mp, info->cgroup_path, true);
+                       (void)remove_cgroup(mp, info->cgroup_path, true, conf);
        }
        for (pp = info->created_paths; pp && *pp; pp++);
        for ((void)(pp && --pp); info->created_paths && pp >= info->created_paths; --pp) {
@@ -1248,7 +1264,7 @@ void lxc_cgroup_process_info_free_and_remove(struct cgroup_process_info *info)
        free(info->cgroup_path);
        free(info->cgroup_path_sub);
        free(info);
-       lxc_cgroup_process_info_free_and_remove(next);
+       lxc_cgroup_process_info_free_and_remove(next, conf);
 }
 
 static char *lxc_cgroup_get_hierarchy_path_data(const char *subsystem, struct cgfs_data *d)
@@ -1802,7 +1818,8 @@ static bool is_valid_cgroup(const char *name)
 }
 
 static int create_or_remove_cgroup(bool do_remove,
-               struct cgroup_mount_point *mp, const char *path, int recurse)
+               struct cgroup_mount_point *mp, const char *path, int recurse,
+               struct lxc_conf *conf)
 {
        int r, saved_errno = 0;
        char *buf = cgroup_to_absolute_path(mp, path, NULL);
@@ -1813,9 +1830,12 @@ static int create_or_remove_cgroup(bool do_remove,
        if (do_remove) {
                if (!dir_exists(buf))
                        return 0;
-               if (recurse)
-                       r = cgroup_rmdir(buf);
-               else
+               if (recurse) {
+                       if (conf && !lxc_list_empty(&conf->id_map))
+                               r = userns_exec_1(conf, rmdir_wrapper, buf);
+                       else
+                               r = cgroup_rmdir(buf);
+               } else
                        r = rmdir(buf);
        } else
                r = mkdir(buf, 0777);
@@ -1827,13 +1847,13 @@ static int create_or_remove_cgroup(bool do_remove,
 
 static int create_cgroup(struct cgroup_mount_point *mp, const char *path)
 {
-       return create_or_remove_cgroup(false, mp, path, false);
+       return create_or_remove_cgroup(false, mp, path, false, NULL);
 }
 
 static int remove_cgroup(struct cgroup_mount_point *mp,
-                        const char *path, bool recurse)
+                        const char *path, bool recurse, struct lxc_conf *conf)
 {
-       return create_or_remove_cgroup(true, mp, path, recurse);
+       return create_or_remove_cgroup(true, mp, path, recurse, conf);
 }
 
 static char *cgroup_to_absolute_path(struct cgroup_mount_point *mp,
@@ -2311,14 +2331,14 @@ err1:
        return NULL;
 }
 
-static void cgfs_destroy(void *hdata)
+static void cgfs_destroy(void *hdata, struct lxc_conf *conf)
 {
        struct cgfs_data *d = hdata;
 
        if (!d)
                return;
        free(d->name);
-       lxc_cgroup_process_info_free_and_remove(d->info);
+       lxc_cgroup_process_info_free_and_remove(d->info, conf);
        lxc_cgroup_put_meta(d->meta);
        free(d);
 }
index 937c36ed173048343dfa392a5bb8844597681c89..7a35d03aad4f61a9a1bcd82c64e6005032add7ec 100644 (file)
@@ -558,7 +558,7 @@ err1:
 }
 
 /* Called after a failed container startup */
-static void cgm_destroy(void *hdata)
+static void cgm_destroy(void *hdata, struct lxc_conf *conf)
 {
        struct cgm_data *d = hdata;
        char **slist = subsystems;
index 8ee0629a1645fca69f1ca5241da5fb7bc5388dd4..5d67bd36e858b1920d01e71132fe5cabf923e38a 100644 (file)
@@ -71,7 +71,7 @@ bool cgroup_init(struct lxc_handler *handler)
 void cgroup_destroy(struct lxc_handler *handler)
 {
        if (ops) {
-               ops->destroy(handler->cgroup_data);
+               ops->destroy(handler->cgroup_data, handler->conf);
                handler->cgroup_data = NULL;
        }
 }
index 63dcc925412441cabfac2a6a2a9641b91c1649c5..9919486e397a3a925eeca6d4f1f147f634aba1d0 100644 (file)
@@ -41,7 +41,7 @@ struct cgroup_ops {
        const char *name;
 
        void *(*init)(const char *name);
-       void (*destroy)(void *hdata);
+       void (*destroy)(void *hdata, struct lxc_conf *conf);
        bool (*create)(void *hdata);
        bool (*enter)(void *hdata, pid_t pid);
        bool (*create_legacy)(void *hdata, pid_t pid);