diff options
| author | Eric W. Biederman <ebiederm@xmission.com> | 2016-07-15 06:35:24 -0500 |
|---|---|---|
| committer | Michael Bestas <mkbestas@lineageos.org> | 2022-04-19 00:51:05 +0300 |
| commit | 1ae35060f4d21445bc76043bf37df620057361d8 (patch) | |
| tree | 20e3502107c97122821ee459d8048df47b0469fa | |
| parent | 1287b8c676e1ccdeb116336ab519d5975d5818e1 (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>
Signed-off-by: Chatur27 <jasonbright2709@gmail.com>
| -rw-r--r-- | kernel/cgroup.c | 9 |
1 files changed, 3 insertions, 6 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index a623e1a30b24..4e3a796e9585 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -6363,14 +6363,11 @@ struct cgroup_namespace *copy_cgroup_ns(unsigned long flags, if (!ns_capable(user_ns, CAP_SYS_ADMIN)) return ERR_PTR(-EPERM); - mutex_lock(&cgroup_mutex); - spin_lock_bh(&css_set_lock); - + /* 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_bh(&css_set_lock); - mutex_unlock(&cgroup_mutex); + spin_unlock_irq(&css_set_lock); new_ns = alloc_cgroup_ns(); if (IS_ERR(new_ns)) { |
