aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLai Jiangshan <laijs@cn.fujitsu.com>2009-01-07 21:07:39 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2009-01-08 11:31:02 -0500
commit77efecd9e0526327548152df715ab8644ecb5ba0 (patch)
tree4dd2a82fe5db454fb018e434e07c3e6f30dc9832 /kernel
parent104cbd55377029e70fc2cee01089e84b9c36e5dc (diff)
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 increases the count before get_css_set(), and decreases it after find_css_set(). NOTE: 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@cn.fujitsu.com> Cc: Paul Menage <menage@google.com> Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com> Cc: Pavel Emelyanov <xemul@openvz.org> Cc: Balbir Singh <balbir@in.ibm.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/cgroup.c7
1 files changed, 6 insertions, 1 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c
index 00d5136d38c2..61e92c5867ea 100644
--- a/kernel/cgroup.c
+++ b/kernel/cgroup.c
@@ -1214,7 +1214,7 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1214 int retval = 0; 1214 int retval = 0;
1215 struct cgroup_subsys *ss; 1215 struct cgroup_subsys *ss;
1216 struct cgroup *oldcgrp; 1216 struct cgroup *oldcgrp;
1217 struct css_set *cg = tsk->cgroups; 1217 struct css_set *cg;
1218 struct css_set *newcg; 1218 struct css_set *newcg;
1219 struct cgroupfs_root *root = cgrp->root; 1219 struct cgroupfs_root *root = cgrp->root;
1220 int subsys_id; 1220 int subsys_id;
@@ -1234,11 +1234,16 @@ int cgroup_attach_task(struct cgroup *cgrp, struct task_struct *tsk)
1234 } 1234 }
1235 } 1235 }
1236 1236
1237 task_lock(tsk);
1238 cg = tsk->cgroups;
1239 get_css_set(cg);
1240 task_unlock(tsk);
1237 /* 1241 /*
1238 * Locate or allocate a new css_set for this task, 1242 * Locate or allocate a new css_set for this task,
1239 * based on its final set of cgroups 1243 * based on its final set of cgroups
1240 */ 1244 */
1241 newcg = find_css_set(cg, cgrp); 1245 newcg = find_css_set(cg, cgrp);
1246 put_css_set(cg);
1242 if (!newcg) 1247 if (!newcg)
1243 return -ENOMEM; 1248 return -ENOMEM;
1244 1249