aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
authorLi Zefan2013-04-19 01:09:52 -0500
committerGreg Kroah-Hartman2013-05-07 22:08:22 -0500
commitfdb2b6f6dfc7b5a1c741a677eb990070690958f7 (patch)
tree1b2c2f5a8af166416387ee346b54f8b370d1f423 /kernel
parent1ef527a1111b2a206d39d2e23cf13819e329f8b4 (diff)
downloadkernel-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.c11
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
2559static inline int xattr_enabled(struct dentry *dentry) 2561static 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 }