| From d1897c9538edafd4ae6bbd03cc075962ddde2c21 Mon Sep 17 00:00:00 2001 |
| From: Tejun Heo <tj@kernel.org> |
| Date: Wed, 21 Feb 2018 11:39:22 -0800 |
| Subject: cgroup: fix rule checking for threaded mode switching |
| |
| From: Tejun Heo <tj@kernel.org> |
| |
| commit d1897c9538edafd4ae6bbd03cc075962ddde2c21 upstream. |
| |
| A domain cgroup isn't allowed to be turned threaded if its subtree is |
| populated or domain controllers are enabled. cgroup_enable_threaded() |
| depended on cgroup_can_be_thread_root() test to enforce this rule. A |
| parent which has populated domain descendants or have domain |
| controllers enabled can't become a thread root, so the above rules are |
| enforced automatically. |
| |
| However, for the root cgroup which can host mixed domain and threaded |
| children, cgroup_can_be_thread_root() doesn't check any of those |
| conditions and thus first level cgroups ends up escaping those rules. |
| |
| This patch fixes the bug by adding explicit checks for those rules in |
| cgroup_enable_threaded(). |
| |
| Reported-by: Michael Kerrisk (man-pages) <mtk.manpages@gmail.com> |
| Signed-off-by: Tejun Heo <tj@kernel.org> |
| Fixes: 8cfd8147df67 ("cgroup: implement cgroup v2 thread support") |
| Cc: stable@vger.kernel.org # v4.14+ |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| kernel/cgroup/cgroup.c | 10 ++++++++++ |
| 1 file changed, 10 insertions(+) |
| |
| --- a/kernel/cgroup/cgroup.c |
| +++ b/kernel/cgroup/cgroup.c |
| @@ -3148,6 +3148,16 @@ static int cgroup_enable_threaded(struct |
| if (cgroup_is_threaded(cgrp)) |
| return 0; |
| |
| + /* |
| + * If @cgroup is populated or has domain controllers enabled, it |
| + * can't be switched. While the below cgroup_can_be_thread_root() |
| + * test can catch the same conditions, that's only when @parent is |
| + * not mixable, so let's check it explicitly. |
| + */ |
| + if (cgroup_is_populated(cgrp) || |
| + cgrp->subtree_control & ~cgrp_dfl_threaded_ss_mask) |
| + return -EOPNOTSUPP; |
| + |
| /* we're joining the parent's domain, ensure its validity */ |
| if (!cgroup_is_valid_domain(dom_cgrp) || |
| !cgroup_can_be_thread_root(dom_cgrp)) |