From: Linus Torvalds Date: Fri, 29 Jul 2016 21:29:04 +0000 (-0700) Subject: Merge branch 'for-4.7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj... X-Git-Tag: v4.8-rc1~98 X-Git-Url: https://repo.jachan.dev/linux.git/commitdiff_plain/574c7e233344b58c6b14b305c93de361d3e7d35d?hp=-c Merge branch 'for-4.7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup Pull more cgroup updates from Tejun Heo: "I forgot to include the patches which got applied to for-4.7-fixes late during last cycle. Eric's three patches fix bugs introduced with the namespace support" * 'for-4.7-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/tj/cgroup: cgroupns: Only allow creation of hierarchies in the initial cgroup namespace cgroupns: Close race between cgroup_post_fork and copy_cgroup_ns cgroupns: Fix the locking in copy_cgroup_ns --- 574c7e233344b58c6b14b305c93de361d3e7d35d diff --combined kernel/cgroup.c index 9624db80dc4e,e0be49fc382f..d1c51b7f5221 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@@ -61,7 -61,7 +61,7 @@@ #include #include #include -#include +#include #include /* @@@ -1160,12 -1160,18 +1160,12 @@@ static void cgroup_exit_root_id(struct { lockdep_assert_held(&cgroup_mutex); - if (root->hierarchy_id) { - idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id); - root->hierarchy_id = 0; - } + idr_remove(&cgroup_hierarchy_idr, root->hierarchy_id); } static void cgroup_free_root(struct cgroup_root *root) { if (root) { - /* hierarchy ID should already have been released */ - WARN_ON_ONCE(root->hierarchy_id); - idr_destroy(&root->cgroup_idr); kfree(root); } @@@ -2209,12 -2215,8 +2209,8 @@@ static struct dentry *cgroup_mount(stru goto out_unlock; } - /* - * We know this subsystem has not yet been bound. Users in a non-init - * user namespace may only mount hierarchies with no bound subsystems, - * i.e. 'none,name=user1' - */ - if (!opts.none && !capable(CAP_SYS_ADMIN)) { + /* Hierarchies may only be created in the initial cgroup namespace. */ + if (ns != &init_cgroup_ns) { ret = -EPERM; goto out_unlock; } @@@ -2956,6 -2958,7 +2952,7 @@@ int cgroup_attach_task_all(struct task_ int retval = 0; mutex_lock(&cgroup_mutex); + percpu_down_write(&cgroup_threadgroup_rwsem); for_each_root(root) { struct cgroup *from_cgrp; @@@ -2970,6 -2973,7 +2967,7 @@@ if (retval) break; } + percpu_up_write(&cgroup_threadgroup_rwsem); mutex_unlock(&cgroup_mutex); return retval; @@@ -4337,6 -4341,8 +4335,8 @@@ int cgroup_transfer_tasks(struct cgrou mutex_lock(&cgroup_mutex); + percpu_down_write(&cgroup_threadgroup_rwsem); + /* all tasks in @from are being moved, all csets are source */ spin_lock_irq(&css_set_lock); list_for_each_entry(link, &from->cset_links, cset_link) @@@ -4365,6 -4371,7 +4365,7 @@@ } while (task && !ret); out_err: cgroup_migrate_finish(&preloaded_csets); + percpu_up_write(&cgroup_threadgroup_rwsem); mutex_unlock(&cgroup_mutex); return ret; } @@@ -5140,8 -5147,6 +5141,8 @@@ static struct cgroup_subsys_state *css_ lockdep_assert_held(&cgroup_mutex); css = ss->css_alloc(parent_css); + if (!css) + css = ERR_PTR(-ENOMEM); if (IS_ERR(css)) return css; @@@ -6168,7 -6173,7 +6169,7 @@@ struct cgroup_subsys_state *css_tryget_ struct cgroup_subsys_state *css_from_id(int id, struct cgroup_subsys *ss) { WARN_ON_ONCE(!rcu_read_lock_held()); - return id > 0 ? idr_find(&ss->css_idr, id) : NULL; + return idr_find(&ss->css_idr, id); } /** @@@ -6205,40 -6210,6 +6206,40 @@@ struct cgroup *cgroup_get_from_path(con } EXPORT_SYMBOL_GPL(cgroup_get_from_path); +/** + * cgroup_get_from_fd - get a cgroup pointer from a fd + * @fd: fd obtained by open(cgroup2_dir) + * + * Find the cgroup from a fd which should be obtained + * by opening a cgroup directory. Returns a pointer to the + * cgroup on success. ERR_PTR is returned if the cgroup + * cannot be found. + */ +struct cgroup *cgroup_get_from_fd(int fd) +{ + struct cgroup_subsys_state *css; + struct cgroup *cgrp; + struct file *f; + + f = fget_raw(fd); + if (!f) + return ERR_PTR(-EBADF); + + css = css_tryget_online_from_dir(f->f_path.dentry, NULL); + fput(f); + if (IS_ERR(css)) + return ERR_CAST(css); + + cgrp = css->cgroup; + if (!cgroup_on_dfl(cgrp)) { + cgroup_put(cgrp); + return ERR_PTR(-EBADF); + } + + return cgrp; +} +EXPORT_SYMBOL_GPL(cgroup_get_from_fd); + /* * sock->sk_cgrp_data handling. For more info, see sock_cgroup_data * definition in cgroup-defs.h. @@@ -6339,14 -6310,11 +6340,11 @@@ struct cgroup_namespace *copy_cgroup_ns if (!ns_capable(user_ns, CAP_SYS_ADMIN)) return ERR_PTR(-EPERM); - mutex_lock(&cgroup_mutex); + /* It is not safe to take cgroup_mutex here */ spin_lock_irq(&css_set_lock); - cset = task_css_set(current); get_css_set(cset); - spin_unlock_irq(&css_set_lock); - mutex_unlock(&cgroup_mutex); new_ns = alloc_cgroup_ns(); if (IS_ERR(new_ns)) {