aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRajat Jain <rajatja@google.com>2018-06-16 13:49:46 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2018-07-07 11:54:46 -0400
commitc855cf2759d27142f771173d9fd8e7fdf9cf5138 (patch)
treebdca38399864bfa1900851f1ef1f6248b9debf5a
parent319b11ef5719a2f0ae65ce5f665f263a5e7a06c3 (diff)
sysfs: Fix internal_create_group() for named group updates
There are a couple of problems with named group updates in the code today: * sysfs_update_group() will always fail for a named group, because internal_create_group() will try to create a new sysfs directory unconditionally, which will ofcourse fail with -EEXIST. * We can leak the kernfs_node for grp->name if some one tries to: - rename a group (change grp->name), or - update a named group, to an unnamed group It appears that the whole purpose of sysfs_update_group() was to allow changing the permissions or visibility of attributes and not the names. So make it clear in the comments, and allow it to update an existing named group. Signed-off-by: Rajat Jain <rajatja@google.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--fs/sysfs/group.c29
1 files changed, 22 insertions, 7 deletions
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 4802ec0e1e3a..38240410f831 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -119,12 +119,22 @@ static int internal_create_group(struct kobject *kobj, int update,
119 return -EINVAL; 119 return -EINVAL;
120 } 120 }
121 if (grp->name) { 121 if (grp->name) {
122 kn = kernfs_create_dir(kobj->sd, grp->name, 122 if (update) {
123 S_IRWXU | S_IRUGO | S_IXUGO, kobj); 123 kn = kernfs_find_and_get(kobj->sd, grp->name);
124 if (IS_ERR(kn)) { 124 if (!kn) {
125 if (PTR_ERR(kn) == -EEXIST) 125 pr_warn("Can't update unknown attr grp name: %s/%s\n",
126 sysfs_warn_dup(kobj->sd, grp->name); 126 kobj->name, grp->name);
127 return PTR_ERR(kn); 127 return -EINVAL;
128 }
129 } else {
130 kn = kernfs_create_dir(kobj->sd, grp->name,
131 S_IRWXU | S_IRUGO | S_IXUGO,
132 kobj);
133 if (IS_ERR(kn)) {
134 if (PTR_ERR(kn) == -EEXIST)
135 sysfs_warn_dup(kobj->sd, grp->name);
136 return PTR_ERR(kn);
137 }
128 } 138 }
129 } else 139 } else
130 kn = kobj->sd; 140 kn = kobj->sd;
@@ -135,6 +145,10 @@ static int internal_create_group(struct kobject *kobj, int update,
135 kernfs_remove(kn); 145 kernfs_remove(kn);
136 } 146 }
137 kernfs_put(kn); 147 kernfs_put(kn);
148
149 if (grp->name && update)
150 kernfs_put(kn);
151
138 return error; 152 return error;
139} 153}
140 154
@@ -199,7 +213,8 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups);
199 * of the attribute files being created already exist. Furthermore, 213 * of the attribute files being created already exist. Furthermore,
200 * if the visibility of the files has changed through the is_visible() 214 * if the visibility of the files has changed through the is_visible()
201 * callback, it will update the permissions and add or remove the 215 * callback, it will update the permissions and add or remove the
202 * relevant files. 216 * relevant files. Changing a group's name (subdirectory name under
217 * kobj's directory in sysfs) is not allowed.
203 * 218 *
204 * The primary use for this function is to call it after making a change 219 * The primary use for this function is to call it after making a change
205 * that affects group visibility. 220 * that affects group visibility.