diff options
author | Li Zefan | 2013-04-19 01:09:52 -0500 |
---|---|---|
committer | Greg Kroah-Hartman | 2013-05-07 22:08:22 -0500 |
commit | fdb2b6f6dfc7b5a1c741a677eb990070690958f7 (patch) | |
tree | 1b2c2f5a8af166416387ee346b54f8b370d1f423 /kernel | |
parent | 1ef527a1111b2a206d39d2e23cf13819e329f8b4 (diff) | |
download | kernel-omap-fdb2b6f6dfc7b5a1c741a677eb990070690958f7.tar.gz kernel-omap-fdb2b6f6dfc7b5a1c741a677eb990070690958f7.tar.xz kernel-omap-fdb2b6f6dfc7b5a1c741a677eb990070690958f7.zip |
cgroup: fix broken file xattrs
commit 712317ad97f41e738e1a19aa0a6392a78a84094e upstream.
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().
Reported-by: Alexey Kodanev <alexey.kodanev@oracle.com>
Signed-off-by: Li Zefan <lizefan@huawei.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'kernel')
-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 5fb09428cd24..cddf1d998381 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c | |||
@@ -162,6 +162,9 @@ struct cfent { | |||
162 | struct list_head node; | 162 | struct list_head node; |
163 | struct dentry *dentry; | 163 | struct dentry *dentry; |
164 | struct cftype *type; | 164 | struct cftype *type; |
165 | |||
166 | /* file xattrs */ | ||
167 | struct simple_xattrs xattrs; | ||
165 | }; | 168 | }; |
166 | 169 | ||
167 | /* | 170 | /* |
@@ -908,13 +911,12 @@ static void cgroup_diput(struct dentry *dentry, struct inode *inode) | |||
908 | } else { | 911 | } else { |
909 | struct cfent *cfe = __d_cfe(dentry); | 912 | struct cfent *cfe = __d_cfe(dentry); |
910 | struct cgroup *cgrp = dentry->d_parent->d_fsdata; | 913 | struct cgroup *cgrp = dentry->d_parent->d_fsdata; |
911 | struct cftype *cft = cfe->type; | ||
912 | 914 | ||
913 | WARN_ONCE(!list_empty(&cfe->node) && | 915 | WARN_ONCE(!list_empty(&cfe->node) && |
914 | cgrp != &cgrp->root->top_cgroup, | 916 | cgrp != &cgrp->root->top_cgroup, |
915 | "cfe still linked for %s\n", cfe->type->name); | 917 | "cfe still linked for %s\n", cfe->type->name); |
918 | simple_xattrs_free(&cfe->xattrs); | ||
916 | kfree(cfe); | 919 | kfree(cfe); |
917 | simple_xattrs_free(&cft->xattrs); | ||
918 | } | 920 | } |
919 | iput(inode); | 921 | iput(inode); |
920 | } | 922 | } |
@@ -2553,7 +2555,7 @@ static struct simple_xattrs *__d_xattrs(struct dentry *dentry) | |||
2553 | if (S_ISDIR(dentry->d_inode->i_mode)) | 2555 | if (S_ISDIR(dentry->d_inode->i_mode)) |
2554 | return &__d_cgrp(dentry)->xattrs; | 2556 | return &__d_cgrp(dentry)->xattrs; |
2555 | else | 2557 | else |
2556 | return &__d_cft(dentry)->xattrs; | 2558 | return &__d_cfe(dentry)->xattrs; |
2557 | } | 2559 | } |
2558 | 2560 | ||
2559 | static inline int xattr_enabled(struct dentry *dentry) | 2561 | static inline int xattr_enabled(struct dentry *dentry) |
@@ -2729,8 +2731,6 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, | |||
2729 | umode_t mode; | 2731 | umode_t mode; |
2730 | char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; | 2732 | char name[MAX_CGROUP_TYPE_NAMELEN + MAX_CFTYPE_NAME + 2] = { 0 }; |
2731 | 2733 | ||
2732 | simple_xattrs_init(&cft->xattrs); | ||
2733 | |||
2734 | if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) { | 2734 | if (subsys && !test_bit(ROOT_NOPREFIX, &cgrp->root->flags)) { |
2735 | strcpy(name, subsys->name); | 2735 | strcpy(name, subsys->name); |
2736 | strcat(name, "."); | 2736 | strcat(name, "."); |
@@ -2755,6 +2755,7 @@ static int cgroup_add_file(struct cgroup *cgrp, struct cgroup_subsys *subsys, | |||
2755 | cfe->type = (void *)cft; | 2755 | cfe->type = (void *)cft; |
2756 | cfe->dentry = dentry; | 2756 | cfe->dentry = dentry; |
2757 | dentry->d_fsdata = cfe; | 2757 | dentry->d_fsdata = cfe; |
2758 | simple_xattrs_init(&cfe->xattrs); | ||
2758 | list_add_tail(&cfe->node, &parent->files); | 2759 | list_add_tail(&cfe->node, &parent->files); |
2759 | cfe = NULL; | 2760 | cfe = NULL; |
2760 | } | 2761 | } |