diff options
author | Li Zefan <lizefan@huawei.com> | 2013-04-19 02:09:52 -0400 |
---|---|---|
committer | Tejun Heo <tj@kernel.org> | 2013-04-19 02:11:40 -0400 |
commit | 712317ad97f41e738e1a19aa0a6392a78a84094e (patch) | |
tree | 66988449eb8cca53e032eed6ddc1169f9296eeac /kernel/cgroup.c | |
parent | e57d5cf2f894e3f2727f8cf74bed0bc81cae70c8 (diff) |
cgroup: fix broken file xattrs
We should store file xattrs in struct cfent instead of struct cftype,
because cftype is a type while cfent is object instance of cftype.
For example each cgroup has a tasks file, and each tasks file is
associated with a uniq cfent, but all those files share the same
struct cftype.
Alexey Kodanev reported a crash, which can be reproduced:
# mount -t cgroup -o xattr /sys/fs/cgroup
# mkdir /sys/fs/cgroup/test
# setfattr -n trusted.value -v test_value /sys/fs/cgroup/tasks
# rmdir /sys/fs/cgroup/test
# umount /sys/fs/cgroup
oops!
In this case, simple_xattrs_free() will free the same struct simple_xattrs
twice.
tj: Dropped unused local variable @cft from cgroup_diput().
Cc: <stable@vger.kernel.org> # 3.8.x
Reported-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'kernel/cgroup.c')
-rw-r--r-- | kernel/cgroup.c | 11 |
1 files changed, 6 insertions, 5 deletions
diff --git a/kernel/cgroup.c b/kernel/cgroup.c index c16719e056ab..192d762ec1f4 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -117,6 +117,9 @@ struct cfent { | |||
117 | struct list_head node; | 117 | struct list_head node; |
118 | struct dentry *dentry; | 118 | struct dentry *dentry; |
119 | struct cftype *type; | 119 | struct cftype *type; |
120 | |||
121 | /* file xattrs */ | ||
122 | struct simple_xattrs xattrs; | ||
120 | }; | 123 | }; |
121 | 124 | ||
122 | /* | 125 | /* |
@@ -882,13 +885,12 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) | |||
882 | } else { | 885 | } else { |
883 | struct cfent *cfe = __d_cfe(dentry); | 886 | struct cfent *cfe = __d_cfe(dentry); |
884 | struct cgroup *cgrp = dentry->d_parent->d_fsdata; | 887 | struct cgroup *cgrp = dentry->d_parent->d_fsdata; |
885 | struct cftype *cft = cfe->type; | ||
886 | 888 | ||
887 | WARN_ONCE(!list_empty(&cfe->node) && | 889 | WARN_ONCE(!list_empty(&cfe->node) && |
888 | cgrp != &cgrp->root->top_cgroup, | 890 | cgrp != &cgrp->root->top_cgroup, |
889 | "cfe still linked for %s\n", cfe->type->name); | 891 | "cfe still linked for %s\n", cfe->type->name); |
892 | simple_xattrs_free(&cfe->xattrs); | ||
890 | kfree(cfe); | 893 | kfree(cfe); |
891 | simple_xattrs_free(&cft->xattrs); | ||
892 | } | 894 | } |
893 | iput(inode); | 895 | iput(inode); |
894 | } | 896 | } |
@@ -2501,7 +2503,7 @@ static struct simple_xattrs *__d_xattrs(struct dentry *dentry) | |||
2501 | if (S_ISDIR(dentry->d_inode->i_mode)) | 2503 | if (S_ISDIR(dentry->d_inode->i_mode)) |
2502 | return &__d_cgrp(dentry)->xattrs; | 2504 | return &__d_cgrp(dentry)->xattrs; |
2503 | else | 2505 | else |
2504 | return &__d_cft(dentry)->xattrs; | 2506 | return &__d_cfe(dentry)->xattrs; |
2505 | } | 2507 | } |
2506 | 2508 | ||
2507 | static inline int xattr_enabled(struct dentry *dentry) | 2509 | static inline int xattr_enabled(struct dentry *dentry) |
@@ -2677,8 +2679,6 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, | |||
2677 | umode_t mode; | 2679 | umode_t mode; |
2678 | char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; | 2680 | char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; |
2679 | 2681 | ||
2680 | simple_xattrs_init(&cft->xattrs); | ||
2681 | |||
2682 | if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) { | 2682 | if (subsys && !(cgrp->root->flags & CGRP_ROOT_NOPREFIX)) { |
2683 | strcpy(name, subsys->name); | 2683 | strcpy(name, subsys->name); |
2684 | strcat(name, "."); | 2684 | strcat(name, "."); |
@@ -2703,6 +2703,7 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, | |||
2703 | cfe->type = (void *)cft; | 2703 | cfe->type = (void *)cft; |
2704 | cfe->dentry = dentry; | 2704 | cfe->dentry = dentry; |
2705 | dentry->d_fsdata = cfe; | 2705 | dentry->d_fsdata = cfe; |
2706 | simple_xattrs_init(&cfe->xattrs); | ||
2706 | list_add_tail(&cfe->node, &parent->files); | 2707 | list_add_tail(&cfe->node, &parent->files); |
2707 | cfe = NULL; | 2708 | cfe = NULL; |
2708 | } | 2709 | } |