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>
This commit is contained in:
+14
-14
@@ -4940,17 +4940,17 @@ void cgroup_post_fork(struct task_struct *child)
|
||||
* and addition to css_set.
|
||||
*/
|
||||
if (need_forkexit_callback) {
|
||||
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
|
||||
/*
|
||||
* fork/exit callbacks are supported only for builtin
|
||||
* subsystems, and the builtin section of the subsys
|
||||
* array is immutable, so we don't need to lock the
|
||||
* subsys array here. On the other hand, modular section
|
||||
* of the array can be freed at module unload, so we
|
||||
* can't touch that.
|
||||
*/
|
||||
for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
|
||||
struct cgroup_subsys *ss = subsys[i];
|
||||
|
||||
/*
|
||||
* fork/exit callbacks are supported only for
|
||||
* builtin subsystems and we don't need further
|
||||
* synchronization as they never go away.
|
||||
*/
|
||||
if (!ss || ss->module)
|
||||
continue;
|
||||
|
||||
if (ss->fork)
|
||||
ss->fork(child);
|
||||
}
|
||||
@@ -5015,13 +5015,13 @@ void cgroup_exit(struct task_struct *tsk, int run_callbacks)
|
||||
tsk->cgroups = &init_css_set;
|
||||
|
||||
if (run_callbacks && need_forkexit_callback) {
|
||||
for (i = 0; i < CGROUP_SUBSYS_COUNT; i++) {
|
||||
/*
|
||||
* fork/exit callbacks are supported only for builtin
|
||||
* subsystems, see cgroup_post_fork() for details.
|
||||
*/
|
||||
for (i = 0; i < CGROUP_BUILTIN_SUBSYS_COUNT; i++) {
|
||||
struct cgroup_subsys *ss = subsys[i];
|
||||
|
||||
/* modular subsystems can't use callbacks */
|
||||
if (!ss || ss->module)
|
||||
continue;
|
||||
|
||||
if (ss->exit) {
|
||||
struct cgroup *old_cgrp =
|
||||
rcu_dereference_raw(cg->subsys[i])->cgroup;
|
||||
|
||||
Reference in New Issue
Block a user