[PATCH] cgroups: call find_css_set() safely in cgroup_attach_task()

From: Lai Jiangshan
Date: Fri Nov 21 2008 - 03:57:36 EST



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 <laijs@xxxxxxxxxxxxxx>
---
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 358e775..ddc10ac 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -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;




--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/