diff options
author | Eric W. Biederman <ebiederm@xmission.com> | 2016-07-15 07:35:24 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2016-07-15 07:56:32 -0400 |
commit | 7bd8830875bfa380c68f390efbad893293749324 (patch) | |
tree | 86f51feccb725f56d42fd3cca7e256a787cfec13 | |
parent | 82d6489d0fed2ec8a8c48c19e8d8a04ac8e5bb26 (diff) |
cgroupns: Fix the locking in copy_cgroup_ns
If "clone(CLONE_NEWCGROUP...)" is called it results in a nice lockdep
valid splat.
In __cgroup_proc_write the lock ordering is:
cgroup_mutex -- through cgroup_kn_lock_live
cgroup_threadgroup_rwsem
In copy_process the guts of clone the lock ordering is:
cgroup_threadgroup_rwsem -- through threadgroup_change_begin
cgroup_mutex -- through copy_namespaces -- copy_cgroup_ns
lockdep reports some a different call chains for the first ordering of
cgroup_mutex and cgroup_threadgroup_rwsem but it is harder to trace.
This is most definitely deadlock potential under the right
circumstances.
Fix this by by skipping the cgroup_mutex and making the locking in
copy_cgroup_ns mirror the locking in cgroup_post_fork which also runs
during fork under the cgroup_threadgroup_rwsem.
Cc: stable@vger.kernel.org
Fixes: a79a908fd2b0 ("cgroup: introduce cgroup namespaces")
Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
-rw-r--r-- | kernel/cgroup.c | 5 |
1 files changed, 1 insertions, 4 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 75c0ff00aca6..5f01e00cffc4 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -6309,14 +6309,11 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, | |||
6309 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) | 6309 | if (!ns_capable(user_ns, CAP_SYS_ADMIN)) |
6310 | return ERR_PTR(-EPERM); | 6310 | return ERR_PTR(-EPERM); |
6311 | 6311 | ||
6312 | mutex_lock(&cgroup_mutex); | 6312 | /* It is not safe to take cgroup_mutex here */ |
6313 | spin_lock_irq(&css_set_lock); | 6313 | spin_lock_irq(&css_set_lock); |
6314 | |||
6315 | cset = task_css_set(current); | 6314 | cset = task_css_set(current); |
6316 | get_css_set(cset); | 6315 | get_css_set(cset); |
6317 | |||
6318 | spin_unlock_irq(&css_set_lock); | 6316 | spin_unlock_irq(&css_set_lock); |
6319 | mutex_unlock(&cgroup_mutex); | ||
6320 | 6317 | ||
6321 | new_ns = alloc_cgroup_ns(); | 6318 | new_ns = alloc_cgroup_ns(); |
6322 | if (IS_ERR(new_ns)) { | 6319 | if (IS_ERR(new_ns)) { |