2023-08-07 15:26:10

by Mike Tipton

[permalink] [raw]
Subject: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()

Currently, debugfs_create_str() only supports reading strings from
debugfs. Add support for writing them as well.

Based on original implementation by Peter Zijlstra [0]. Write support
was present in the initial patch version, but dropped in v2 due to lack
of users. We have a user now, so reintroduce it.

[0] https://lore.kernel.org/all/YF3Hv5zXb%[email protected]/

Signed-off-by: Mike Tipton <[email protected]>
---
fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)

diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index b7711888dd17..87b3753aa4b1 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
- /* This is really only for read-only strings */
- return -EINVAL;
+ struct dentry *dentry = F_DENTRY(file);
+ char *old, *new = NULL;
+ int pos = *ppos;
+ int r;
+
+ r = debugfs_file_get(dentry);
+ if (unlikely(r))
+ return r;
+
+ old = *(char **)file->private_data;
+
+ /* only allow strict concatenation */
+ r = -EINVAL;
+ if (pos && pos != strlen(old))
+ goto error;
+
+ r = -E2BIG;
+ if (pos + count + 1 > PAGE_SIZE)
+ goto error;
+
+ r = -ENOMEM;
+ new = kmalloc(pos + count + 1, GFP_KERNEL);
+ if (!new)
+ goto error;
+
+ if (pos)
+ memcpy(new, old, pos);
+
+ r = -EFAULT;
+ if (copy_from_user(new + pos, user_buf, count))
+ goto error;
+
+ new[pos + count] = '\0';
+ strim(new);
+
+ rcu_assign_pointer(*(char **)file->private_data, new);
+ synchronize_rcu();
+ kfree(old);
+
+ debugfs_file_put(dentry);
+ return count;
+
+error:
+ kfree(new);
+ debugfs_file_put(dentry);
+ return r;
}

static const struct file_operations fops_str = {
--
2.17.1



2023-08-11 08:11:54

by Georgi Djakov

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()

On 7.08.23 17:29, Mike Tipton wrote:
> Currently, debugfs_create_str() only supports reading strings from
> debugfs. Add support for writing them as well.
>
> Based on original implementation by Peter Zijlstra [0]. Write support
> was present in the initial patch version, but dropped in v2 due to lack
> of users. We have a user now, so reintroduce it.
>
> [0] https://lore.kernel.org/all/YF3Hv5zXb%[email protected]/
>

Hi Greg,

Looks like the original code was reviewed two years ago (not sure if it
counts). But in any case, i need an ack from you to apply this.

There is no build dependency with the rest of the patches (but there is a
functional one). It should be also fine if you apply it directly, if you
prefer so?

Thanks,
Georgi

> Signed-off-by: Mike Tipton <[email protected]>
> ---
> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
> index b7711888dd17..87b3753aa4b1 100644
> --- a/fs/debugfs/file.c
> +++ b/fs/debugfs/file.c
> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
> size_t count, loff_t *ppos)
> {
> - /* This is really only for read-only strings */
> - return -EINVAL;
> + struct dentry *dentry = F_DENTRY(file);
> + char *old, *new = NULL;
> + int pos = *ppos;
> + int r;
> +
> + r = debugfs_file_get(dentry);
> + if (unlikely(r))
> + return r;
> +
> + old = *(char **)file->private_data;
> +
> + /* only allow strict concatenation */
> + r = -EINVAL;
> + if (pos && pos != strlen(old))
> + goto error;
> +
> + r = -E2BIG;
> + if (pos + count + 1 > PAGE_SIZE)
> + goto error;
> +
> + r = -ENOMEM;
> + new = kmalloc(pos + count + 1, GFP_KERNEL);
> + if (!new)
> + goto error;
> +
> + if (pos)
> + memcpy(new, old, pos);
> +
> + r = -EFAULT;
> + if (copy_from_user(new + pos, user_buf, count))
> + goto error;
> +
> + new[pos + count] = '\0';
> + strim(new);
> +
> + rcu_assign_pointer(*(char **)file->private_data, new);
> + synchronize_rcu();
> + kfree(old);
> +
> + debugfs_file_put(dentry);
> + return count;
> +
> +error:
> + kfree(new);
> + debugfs_file_put(dentry);
> + return r;
> }
>
> static const struct file_operations fops_str = {


2023-08-12 10:58:33

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()

On Fri, Aug 11, 2023 at 10:46:34AM +0300, Georgi Djakov wrote:
> On 7.08.23 17:29, Mike Tipton wrote:
> > Currently, debugfs_create_str() only supports reading strings from
> > debugfs. Add support for writing them as well.
> >
> > Based on original implementation by Peter Zijlstra [0]. Write support
> > was present in the initial patch version, but dropped in v2 due to lack
> > of users. We have a user now, so reintroduce it.
> >
> > [0] https://lore.kernel.org/all/YF3Hv5zXb%[email protected]/
> >
>
> Hi Greg,
>
> Looks like the original code was reviewed two years ago (not sure if it
> counts). But in any case, i need an ack from you to apply this.
>
> There is no build dependency with the rest of the patches (but there is a
> functional one). It should be also fine if you apply it directly, if you
> prefer so?

Feel free for this to go with the code that uses it:

Acked-by: Greg Kroah-Hartman <[email protected]>

2023-08-12 11:00:56

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()

On Sat, Aug 12, 2023 at 12:36:12PM +0200, Greg KH wrote:
> On Fri, Aug 11, 2023 at 10:46:34AM +0300, Georgi Djakov wrote:
> > On 7.08.23 17:29, Mike Tipton wrote:
> > > Currently, debugfs_create_str() only supports reading strings from
> > > debugfs. Add support for writing them as well.
> > >
> > > Based on original implementation by Peter Zijlstra [0]. Write support
> > > was present in the initial patch version, but dropped in v2 due to lack
> > > of users. We have a user now, so reintroduce it.
> > >
> > > [0] https://lore.kernel.org/all/YF3Hv5zXb%[email protected]/
> > >
> >
> > Hi Greg,
> >
> > Looks like the original code was reviewed two years ago (not sure if it
> > counts). But in any case, i need an ack from you to apply this.
> >
> > There is no build dependency with the rest of the patches (but there is a
> > functional one). It should be also fine if you apply it directly, if you
> > prefer so?
>
> Feel free for this to go with the code that uses it:
>
> Acked-by: Greg Kroah-Hartman <[email protected]>

Wait, no, this isn't ok, this ACK is now rescinded:

NACKED-by: Greg Kroah-Hartman <[email protected]>

2023-08-12 11:27:55

by Greg Kroah-Hartman

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()

On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote:
> Currently, debugfs_create_str() only supports reading strings from
> debugfs. Add support for writing them as well.
>
> Based on original implementation by Peter Zijlstra [0]. Write support
> was present in the initial patch version, but dropped in v2 due to lack
> of users. We have a user now, so reintroduce it.
>
> [0] https://lore.kernel.org/all/YF3Hv5zXb%[email protected]/
>
> Signed-off-by: Mike Tipton <[email protected]>
> ---
> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
> 1 file changed, 46 insertions(+), 2 deletions(-)
>
> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
> index b7711888dd17..87b3753aa4b1 100644
> --- a/fs/debugfs/file.c
> +++ b/fs/debugfs/file.c
> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
> size_t count, loff_t *ppos)
> {
> - /* This is really only for read-only strings */
> - return -EINVAL;
> + struct dentry *dentry = F_DENTRY(file);
> + char *old, *new = NULL;
> + int pos = *ppos;
> + int r;
> +
> + r = debugfs_file_get(dentry);
> + if (unlikely(r))
> + return r;
> +
> + old = *(char **)file->private_data;
> +
> + /* only allow strict concatenation */
> + r = -EINVAL;
> + if (pos && pos != strlen(old))
> + goto error;
> +
> + r = -E2BIG;
> + if (pos + count + 1 > PAGE_SIZE)
> + goto error;
> +
> + r = -ENOMEM;
> + new = kmalloc(pos + count + 1, GFP_KERNEL);
> + if (!new)
> + goto error;
> +
> + if (pos)
> + memcpy(new, old, pos);
> +
> + r = -EFAULT;
> + if (copy_from_user(new + pos, user_buf, count))
> + goto error;
> +
> + new[pos + count] = '\0';
> + strim(new);
> +
> + rcu_assign_pointer(*(char **)file->private_data, new);
> + synchronize_rcu();
> + kfree(old);
> +
> + debugfs_file_put(dentry);
> + return count;
> +
> +error:
> + kfree(new);
> + debugfs_file_put(dentry);
> + return r;
> }

So you just added write support for ALL debugfs files that use the
string interface, what did you just allow to break?

I recommend just using your own debugfs file function instead, as this
could cause bad problems, right? Are you sure that all string calls can
handle the variable be freed underneath it like this call will allow to
happen?

So I wouldn't recommend doing this, sorry.

greg k-h

2023-08-12 14:09:29

by Georgi Djakov

[permalink] [raw]
Subject: Re: [PATCH v3 1/3] debugfs: Add write support to debugfs_create_str()

Hi Greg,

Thanks for the comments!

On 12.08.23 13:40, Greg KH wrote:
> On Mon, Aug 07, 2023 at 07:29:12AM -0700, Mike Tipton wrote:
>> Currently, debugfs_create_str() only supports reading strings from
>> debugfs. Add support for writing them as well.
>>
>> Based on original implementation by Peter Zijlstra [0]. Write support
>> was present in the initial patch version, but dropped in v2 due to lack
>> of users. We have a user now, so reintroduce it.
>>
>> [0] https://lore.kernel.org/all/YF3Hv5zXb%[email protected]/
>>
>> Signed-off-by: Mike Tipton <[email protected]>
>> ---
>> fs/debugfs/file.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--
>> 1 file changed, 46 insertions(+), 2 deletions(-)
>>
>> diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
>> index b7711888dd17..87b3753aa4b1 100644
>> --- a/fs/debugfs/file.c
>> +++ b/fs/debugfs/file.c
>> @@ -904,8 +904,52 @@ EXPORT_SYMBOL_GPL(debugfs_create_str);
>> static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
>> size_t count, loff_t *ppos)
>> {
>> - /* This is really only for read-only strings */
>> - return -EINVAL;
>> + struct dentry *dentry = F_DENTRY(file);
>> + char *old, *new = NULL;
>> + int pos = *ppos;
>> + int r;
>> +
>> + r = debugfs_file_get(dentry);
>> + if (unlikely(r))
>> + return r;
>> +
>> + old = *(char **)file->private_data;
>> +
>> + /* only allow strict concatenation */
>> + r = -EINVAL;
>> + if (pos && pos != strlen(old))
>> + goto error;
>> +
>> + r = -E2BIG;
>> + if (pos + count + 1 > PAGE_SIZE)
>> + goto error;
>> +
>> + r = -ENOMEM;
>> + new = kmalloc(pos + count + 1, GFP_KERNEL);
>> + if (!new)
>> + goto error;
>> +
>> + if (pos)
>> + memcpy(new, old, pos);
>> +
>> + r = -EFAULT;
>> + if (copy_from_user(new + pos, user_buf, count))
>> + goto error;
>> +
>> + new[pos + count] = '\0';
>> + strim(new);
>> +
>> + rcu_assign_pointer(*(char **)file->private_data, new);
>> + synchronize_rcu();
>> + kfree(old);
>> +
>> + debugfs_file_put(dentry);
>> + return count;
>> +
>> +error:
>> + kfree(new);
>> + debugfs_file_put(dentry);
>> + return r;
>> }
>
> So you just added write support for ALL debugfs files that use the
> string interface, what did you just allow to break?

Not really. According to the existing code, the write support for strings
is enabled only when the file is created with +w permissions. For read-only
files, we use fops_str_ro, which is the case for all existing string files:

$ git grep -w debugfs_create_str | egrep -v "fs/debugfs/file.c|include/linux/debugfs.h"
drivers/firmware/arm_scmi/driver.c: debugfs_create_str("instance_name", 0400, top_dentry,
drivers/firmware/arm_scmi/driver.c: debugfs_create_str("type", 0400, trans, (char **)&dbg->type);
drivers/opp/debugfs.c: debugfs_create_str("of_name", S_IRUGO, d, (char **)&opp->of_name);

For fops_str_ro, the .write function is not implemented, so nothing should break?

> I recommend just using your own debugfs file function instead, as this
> could cause bad problems, right?

Agree, and that should be exactly what this patch does.

> Are you sure that all string calls can
> handle the variable be freed underneath it like this call will allow to
> happen?

Looks fine, at least for this patch-set.

Thanks,
Georgi