diff options
author | Li Zefan <lizefan@huawei.com> | 2013-03-01 02:01:56 -0500 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-03-04 12:50:08 -0500 |
commit | 65dff759d2948cf18e2029fc5c0c595b8b7da3a5 (patch) | |
tree | 2904e81e44bb939413f406bbb2056e88df008f72 /include | |
parent | 6dbe51c251a327e012439c4772097a13df43c5b8 (diff) |
cgroup: fix cgroup_path() vs rename() race
rename() will change dentry->d_name. The result of this race can
be worse than seeing partially rewritten name, but we might access
a stale pointer because rename() will re-allocate memory to hold
a longer name.
As accessing dentry->name must be protected by dentry->d_lock or
parent inode's i_mutex, while on the other hand cgroup-path() can
be called with some irq-safe spinlocks held, we can't generate
cgroup path using dentry->d_name.
Alternatively we make a copy of dentry->d_name and save it in
cgrp->name when a cgroup is created, and update cgrp->name at
rename().
v5: use flexible array instead of zero-size array.
v4: - allocate root_cgroup_name and all root_cgroup->name points to it.
- add cgroup_name() wrapper.
v3: use kfree_rcu() instead of synchronize_rcu() in user-visible path.
v2: make cgrp->name RCU safe.
Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/cgroup.h | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/include/linux/cgroup.h b/include/linux/cgroup.h index 900af5964f55..75c6ec1ba1ba 100644 --- a/include/linux/cgroup.h +++ b/include/linux/cgroup.h | |||
@@ -150,6 +150,11 @@ enum { | |||
150 | CGRP_CPUSET_CLONE_CHILDREN, | 150 | CGRP_CPUSET_CLONE_CHILDREN, |
151 | }; | 151 | }; |
152 | 152 | ||
153 | struct cgroup_name { | ||
154 | struct rcu_head rcu_head; | ||
155 | char name[]; | ||
156 | }; | ||
157 | |||
153 | struct cgroup { | 158 | struct cgroup { |
154 | unsigned long flags; /* "unsigned long" so bitops work */ | 159 | unsigned long flags; /* "unsigned long" so bitops work */ |
155 | 160 | ||
@@ -172,6 +177,19 @@ struct cgroup { | |||
172 | struct cgroup *parent; /* my parent */ | 177 | struct cgroup *parent; /* my parent */ |
173 | struct dentry *dentry; /* cgroup fs entry, RCU protected */ | 178 | struct dentry *dentry; /* cgroup fs entry, RCU protected */ |
174 | 179 | ||
180 | /* | ||
181 | * This is a copy of dentry->d_name, and it's needed because | ||
182 | * we can't use dentry->d_name in cgroup_path(). | ||
183 | * | ||
184 | * You must acquire rcu_read_lock() to access cgrp->name, and | ||
185 | * the only place that can change it is rename(), which is | ||
186 | * protected by parent dir's i_mutex. | ||
187 | * | ||
188 | * Normally you should use cgroup_name() wrapper rather than | ||
189 | * access it directly. | ||
190 | */ | ||
191 | struct cgroup_name __rcu *name; | ||
192 | |||
175 | /* Private pointers for each registered subsystem */ | 193 | /* Private pointers for each registered subsystem */ |
176 | struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; | 194 | struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT]; |
177 | 195 | ||
@@ -404,6 +422,12 @@ struct cgroup_scanner { | |||
404 | void *data; | 422 | void *data; |
405 | }; | 423 | }; |
406 | 424 | ||
425 | /* Caller should hold rcu_read_lock() */ | ||
426 | static inline const char *cgroup_name(const struct cgroup *cgrp) | ||
427 | { | ||
428 | return rcu_dereference(cgrp->name)->name; | ||
429 | } | ||
430 | |||
407 | int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); | 431 | int cgroup_add_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); |
408 | int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); | 432 | int cgroup_rm_cftypes(struct cgroup_subsys *ss, struct cftype *cfts); |
409 | 433 | ||