aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/cgroup.c
diff options
context:
space:
mode:
authorLi Zefan <lizefan@huawei.com>2013-03-04 21:57:03 -0500
committerTejun Heo <tj@kernel.org>2013-03-05 12:33:25 -0500
commit7d8e0bf56a66bab08d2f316dd87e56c08cecb899 (patch)
treebe35c2daec953f0c98241c16311879dd45bc4859 /kernel/cgroup.c
parentf50daa704f36a6544a902c52b6cf37b0493dfc5d (diff)
cgroup: avoid accessing modular cgroup subsys structure without locking
subsys[i] is set to NULL in cgroup_unload_subsys() at modular unload, and that's protected by cgroup_mutex, and then the memory *subsys[i] resides will be freed. So this is unsafe without any locking: if (!ss || ss->module) ... v2: - add a comment for enum cgroup_subsys_id - simplify the comment in cgroup_exit() Signed-off-by: Li Zefan <lizefan@huawei.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r--kernel/cgroup.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 9df799d5d31c..7a6c4c72ca55 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -4940,17 +4940,17 @@ void cgroup_post_fork(struct task_struct *child)
4940 * and addition to css_set. 4940 * and addition to css_set.
4941 */ 4941 */
4942 if (need_forkexit_callback) { 4942 if (need_forkexit_callback) {
4943 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { 4943 /*
4944 * fork/exit callbacks are supported only for builtin
4945 * subsystems, and the builtin section of the subsys
4946 * array is immutable, so we don't need to lock the
4947 * subsys array here. On the other hand, modular section
4948 * of the array can be freed at module unload, so we
4949 * can't touch that.
4950 */
4951 for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
4944 struct cgroup_subsys *ss = subsys[i]; 4952 struct cgroup_subsys *ss = subsys[i];
4945 4953
4946 /*
4947 * fork/exit callbacks are supported only for
4948 * builtin subsystems and we don't need further
4949 * synchronization as they never go away.
4950 */
4951 if (!ss || ss->module)
4952 continue;
4953
4954 if (ss->fork) 4954 if (ss->fork)
4955 ss->fork(child); 4955 ss->fork(child);
4956 } 4956 }
@@ -5015,13 +5015,13 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
5015 tsk->cgroups = &init_css_set; 5015 tsk->cgroups = &init_css_set;
5016 5016
5017 if (run_callbacks && need_forkexit_callback) { 5017 if (run_callbacks && need_forkexit_callback) {
5018 for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) { 5018 /*
5019 * fork/exit callbacks are supported only for builtin
5020 * subsystems, see cgroup_post_fork() for details.
5021 */
5022 for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
5019 struct cgroup_subsys *ss = subsys[i]; 5023 struct cgroup_subsys *ss = subsys[i];
5020 5024
5021 /* modular subsystems can't use callbacks */
5022 if (!ss || ss->module)
5023 continue;
5024
5025 if (ss->exit) { 5025 if (ss->exit) {
5026 struct cgroup *old_cgrp = 5026 struct cgroup *old_cgrp =
5027 rcu_dereference_raw(cg->subsys[i])->cgroup; 5027 rcu_dereference_raw(cg->subsys[i])->cgroup;