linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] sysfs: Fix internal_create_group() for named group updates
@ 2018-06-16  1:29 Rajat Jain
  2018-06-16  7:11 ` Greg Kroah-Hartman
  0 siblings, 1 reply; 6+ messages in thread
From: Rajat Jain @ 2018-06-16  1:29 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel; +Cc: Rajat Jain, rajatxjain

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>
---
 fs/sysfs/group.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 4802ec0e1e3a..8bd10dc730ae 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -119,12 +119,23 @@ static int internal_create_group(struct kobject *kobj, int update,
 		return -EINVAL;
 	}
 	if (grp->name) {
-		kn = kernfs_create_dir(kobj->sd, grp->name,
-				       S_IRWXU | S_IRUGO | S_IXUGO, kobj);
-		if (IS_ERR(kn)) {
-			if (PTR_ERR(kn) == -EEXIST)
-				sysfs_warn_dup(kobj->sd, grp->name);
-			return PTR_ERR(kn);
+		if (update) {
+			kn = kernfs_find_and_get(kobj->sd, grp->name);
+			if (!kn) {
+				WARN(1,
+				     "Can't update unknown attr grp name: %s/%s\n",
+				     kobj->name, grp->name);
+				return -EINVAL;
+			}
+		} else {
+			kn = kernfs_create_dir(kobj->sd, grp->name,
+					       S_IRWXU | S_IRUGO | S_IXUGO,
+					       kobj);
+			if (IS_ERR(kn)) {
+				if (PTR_ERR(kn) == -EEXIST)
+					sysfs_warn_dup(kobj->sd, grp->name);
+				return PTR_ERR(kn);
+			}
 		}
 	} else
 		kn = kobj->sd;
@@ -199,7 +210,8 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups);
  * of the attribute files being created already exist.  Furthermore,
  * if the visibility of the files has changed through the is_visible()
  * callback, it will update the permissions and add or remove the
- * relevant files.
+ * relevant files. Changing a group's name (subdirectory name under
+ * kobj's directory in sysfs) is not allowed.
  *
  * The primary use for this function is to call it after making a change
  * that affects group visibility.
-- 
2.18.0.rc1.244.gcf134e6275-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH] sysfs: Fix internal_create_group() for named group updates
  2018-06-16  1:29 [PATCH] sysfs: Fix internal_create_group() for named group updates Rajat Jain
@ 2018-06-16  7:11 ` Greg Kroah-Hartman
  2018-06-16  8:09   ` Rajat Jain
  0 siblings, 1 reply; 6+ messages in thread
From: Greg Kroah-Hartman @ 2018-06-16  7:11 UTC (permalink / raw)
  To: Rajat Jain; +Cc: linux-kernel, rajatxjain

On Fri, Jun 15, 2018 at 06:29:10PM -0700, Rajat Jain wrote:
> 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.

Who uses sysfs_update_group() today that has these problems?  Or do you
want to use it in new code?  How can it be broken today so badly that it
does not work?

> Signed-off-by: Rajat Jain <rajatja@google.com>
> ---
>  fs/sysfs/group.c | 26 +++++++++++++++++++-------
>  1 file changed, 19 insertions(+), 7 deletions(-)
> 
> diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
> index 4802ec0e1e3a..8bd10dc730ae 100644
> --- a/fs/sysfs/group.c
> +++ b/fs/sysfs/group.c
> @@ -119,12 +119,23 @@ static int internal_create_group(struct kobject *kobj, int update,
>  		return -EINVAL;
>  	}
>  	if (grp->name) {
> -		kn = kernfs_create_dir(kobj->sd, grp->name,
> -				       S_IRWXU | S_IRUGO | S_IXUGO, kobj);
> -		if (IS_ERR(kn)) {
> -			if (PTR_ERR(kn) == -EEXIST)
> -				sysfs_warn_dup(kobj->sd, grp->name);
> -			return PTR_ERR(kn);
> +		if (update) {
> +			kn = kernfs_find_and_get(kobj->sd, grp->name);
> +			if (!kn) {
> +				WARN(1,
> +				     "Can't update unknown attr grp name: %s/%s\n",
> +				     kobj->name, grp->name);
> +				return -EINVAL;

This is going to cause the syzbot to bug the heck out of us, as people
do run with panic-on-warning.  Just make this a "normal" error message
and dump the stack if you want that.

But maybe we should just get rid of this function entirely, it feels
very ackward and I can't remember why we added it...

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [PATCH] sysfs: Fix internal_create_group() for named group updates
  2018-06-16  7:11 ` Greg Kroah-Hartman
@ 2018-06-16  8:09   ` Rajat Jain
  2018-06-16  8:18     ` [PATCH v2] " Rajat Jain
  0 siblings, 1 reply; 6+ messages in thread
From: Rajat Jain @ 2018-06-16  8:09 UTC (permalink / raw)
  To: Greg Kroah-Hartman; +Cc: Rajat Jain, linux-kernel

Hi Greg,

Thanks for your review.

On Sat, Jun 16, 2018 at 12:11 AM, Greg Kroah-Hartman
<gregkh@linuxfoundation.org> wrote:
> On Fri, Jun 15, 2018 at 06:29:10PM -0700, Rajat Jain wrote:
>> 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.
>
> Who uses sysfs_update_group() today that has these problems?  Or do you
> want to use it in new code?  How can it be broken today so badly that it
> does not work?

Sorry, my bad, I need to provide more clarification: None of the
existing users of this API use it on a named attribute group, thus
will not see this issue. I hit this issue while writing new code
(However, since then my code logic has changed so that it does not
need to use this API anymore).

I'm just trying to fix an issue with this API, that I stumbled upon,
which might be seen in future by any new code that uses this API with
named attribute groups. At the minimum, I think we should clarify in
comments (or better yet, ensure) that this API cannot be misused.


>
>> Signed-off-by: Rajat Jain <rajatja@google.com>
>> ---
>>  fs/sysfs/group.c | 26 +++++++++++++++++++-------
>>  1 file changed, 19 insertions(+), 7 deletions(-)
>>
>> diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
>> index 4802ec0e1e3a..8bd10dc730ae 100644
>> --- a/fs/sysfs/group.c
>> +++ b/fs/sysfs/group.c
>> @@ -119,12 +119,23 @@ static int internal_create_group(struct kobject *kobj, int update,
>>               return -EINVAL;
>>       }
>>       if (grp->name) {
>> -             kn = kernfs_create_dir(kobj->sd, grp->name,
>> -                                    S_IRWXU | S_IRUGO | S_IXUGO, kobj);
>> -             if (IS_ERR(kn)) {
>> -                     if (PTR_ERR(kn) == -EEXIST)
>> -                             sysfs_warn_dup(kobj->sd, grp->name);
>> -                     return PTR_ERR(kn);
>> +             if (update) {
>> +                     kn = kernfs_find_and_get(kobj->sd, grp->name);
>> +                     if (!kn) {
>> +                             WARN(1,
>> +                                  "Can't update unknown attr grp name: %s/%s\n",
>> +                                  kobj->name, grp->name);
>> +                             return -EINVAL;
>
> This is going to cause the syzbot to bug the heck out of us, as people
> do run with panic-on-warning.  Just make this a "normal" error message
> and dump the stack if you want that.

Agreed, I will turn into a normal error.

>
> But maybe we should just get rid of this function entirely, it feels
> very ackward and I can't remember why we added it...

There are a couple of existing in-tree users of this API, and I do not
understand a lot about that code.

Thanks & Best Regards,

Rajat

>
> thanks,
>
> greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v2] sysfs: Fix internal_create_group() for named group updates
  2018-06-16  8:09   ` Rajat Jain
@ 2018-06-16  8:18     ` Rajat Jain
  2018-06-16  8:37       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 6+ messages in thread
From: Rajat Jain @ 2018-06-16  8:18 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel; +Cc: Rajat Jain, rajatxjain

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>
---
v2: Use pr_warn() instead of WARN()

 fs/sysfs/group.c | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index 4802ec0e1e3a..2b7d3536e6cb 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,
 		return -EINVAL;
 	}
 	if (grp->name) {
-		kn = kernfs_create_dir(kobj->sd, grp->name,
-				       S_IRWXU | S_IRUGO | S_IXUGO, kobj);
-		if (IS_ERR(kn)) {
-			if (PTR_ERR(kn) == -EEXIST)
-				sysfs_warn_dup(kobj->sd, grp->name);
-			return PTR_ERR(kn);
+		if (update) {
+			kn = kernfs_find_and_get(kobj->sd, grp->name);
+			if (!kn) {
+				pr_warn("Can't update unknown attr grp name: %s/%s\n",
+					kobj->name, grp->name);
+				return -EINVAL;
+			}
+		} else {
+			kn = kernfs_create_dir(kobj->sd, grp->name,
+					       S_IRWXU | S_IRUGO | S_IXUGO,
+					       kobj);
+			if (IS_ERR(kn)) {
+				if (PTR_ERR(kn) == -EEXIST)
+					sysfs_warn_dup(kobj->sd, grp->name);
+				return PTR_ERR(kn);
+			}
 		}
 	} else
 		kn = kobj->sd;
@@ -199,7 +209,8 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups);
  * of the attribute files being created already exist.  Furthermore,
  * if the visibility of the files has changed through the is_visible()
  * callback, it will update the permissions and add or remove the
- * relevant files.
+ * relevant files. Changing a group's name (subdirectory name under
+ * kobj's directory in sysfs) is not allowed.
  *
  * The primary use for this function is to call it after making a change
  * that affects group visibility.
-- 
2.18.0.rc1.244.gcf134e6275-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [PATCH v2] sysfs: Fix internal_create_group() for named group updates
  2018-06-16  8:18     ` [PATCH v2] " Rajat Jain
@ 2018-06-16  8:37       ` Greg Kroah-Hartman
  2018-06-16 17:49         ` [PATCH v3] " Rajat Jain
  0 siblings, 1 reply; 6+ messages in thread
From: Greg Kroah-Hartman @ 2018-06-16  8:37 UTC (permalink / raw)
  To: Rajat Jain; +Cc: linux-kernel, rajatxjain

On Sat, Jun 16, 2018 at 01:18:37AM -0700, Rajat Jain wrote:
> 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>
> ---
> v2: Use pr_warn() instead of WARN()

Looks good, I'll queue it up after 4.18-rc1 is out, thanks for the
update so quickly.

greg k-h

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [PATCH v3] sysfs: Fix internal_create_group() for named group updates
  2018-06-16  8:37       ` Greg Kroah-Hartman
@ 2018-06-16 17:49         ` Rajat Jain
  0 siblings, 0 replies; 6+ messages in thread
From: Rajat Jain @ 2018-06-16 17:49 UTC (permalink / raw)
  To: Greg Kroah-Hartman, linux-kernel; +Cc: Rajat Jain, rajatxjain

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>
---
v2: Use pr_warn() instead of WARN()
v3: drop the extra reference taken by kernfs_find_and_get()

 fs/sysfs/group.c | 29 ++++++++++++++++++++++-------
 1 file 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,
 		return -EINVAL;
 	}
 	if (grp->name) {
-		kn = kernfs_create_dir(kobj->sd, grp->name,
-				       S_IRWXU | S_IRUGO | S_IXUGO, kobj);
-		if (IS_ERR(kn)) {
-			if (PTR_ERR(kn) == -EEXIST)
-				sysfs_warn_dup(kobj->sd, grp->name);
-			return PTR_ERR(kn);
+		if (update) {
+			kn = kernfs_find_and_get(kobj->sd, grp->name);
+			if (!kn) {
+				pr_warn("Can't update unknown attr grp name: %s/%s\n",
+					kobj->name, grp->name);
+				return -EINVAL;
+			}
+		} else {
+			kn = kernfs_create_dir(kobj->sd, grp->name,
+					       S_IRWXU | S_IRUGO | S_IXUGO,
+					       kobj);
+			if (IS_ERR(kn)) {
+				if (PTR_ERR(kn) == -EEXIST)
+					sysfs_warn_dup(kobj->sd, grp->name);
+				return PTR_ERR(kn);
+			}
 		}
 	} else
 		kn = kobj->sd;
@@ -135,6 +145,10 @@ static int internal_create_group(struct kobject *kobj, int update,
 			kernfs_remove(kn);
 	}
 	kernfs_put(kn);
+
+	if (grp->name && update)
+		kernfs_put(kn);
+
 	return error;
 }
 
@@ -199,7 +213,8 @@ EXPORT_SYMBOL_GPL(sysfs_create_groups);
  * of the attribute files being created already exist.  Furthermore,
  * if the visibility of the files has changed through the is_visible()
  * callback, it will update the permissions and add or remove the
- * relevant files.
+ * relevant files. Changing a group's name (subdirectory name under
+ * kobj's directory in sysfs) is not allowed.
  *
  * The primary use for this function is to call it after making a change
  * that affects group visibility.
-- 
2.18.0.rc1.244.gcf134e6275-goog


^ permalink raw reply related	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2018-06-16 17:49 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-06-16  1:29 [PATCH] sysfs: Fix internal_create_group() for named group updates Rajat Jain
2018-06-16  7:11 ` Greg Kroah-Hartman
2018-06-16  8:09   ` Rajat Jain
2018-06-16  8:18     ` [PATCH v2] " Rajat Jain
2018-06-16  8:37       ` Greg Kroah-Hartman
2018-06-16 17:49         ` [PATCH v3] " Rajat Jain

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).