cgroups: call find_css_set() safely in cgroup_attach_task()
PATCH 1/1 cgroups: call find_css_set() safely in cgroup_attach_task()
in cgroup_attach_task(), tsk maybe exit when we call find_css_set(). and find_css_set() will access to invalid css_set.
this patch increase the count before get_css_set(), and decrease it after find_css_set().
NOTICE:
css_set's refcount is also taskcount, after this patch applied, taskcount may be off-by-one WHEN cgroup_lock() is not held.
but I reviewed other code which use taskcount, they are still correct. No regression found by reviewing and simply testing.
So I do not use two counters in css_set.
(one counter for taskcount, the other for refcount. like struct mm_struct) If this fix cause regression, we will use two counters in css_set.
Signed-off-by Lai Jiangshan <[email protected]>
---
kernel/cgroup.c +6 -1
@@ -1217,7 +1222,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)int retval =0 ;struct cgroup_subsys *ss;struct cgroup *oldcgrp; -struct css_set *cg = tsk->cgroups; +struct css_set *cg;struct css_set *newcg;struct cgroupfs_root *root = cgrp->root;int subsys_id;
@@ -1237,11 +1242,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk) } } +task_lock (tsk); + cg = tsk->cgroups; +get_css_set (cg); +task_unlock (tsk);/* * Locate or allocate a new css_set for this task, * based on its final set of cgroups */ newcg =find_css_set (cg, cgrp); +put_css_set (cg);if (!newcg)return -ENOMEM ;