* [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only
@ 2026-08-07 10:00 Yichong Chen
2026-08-07 10:00 ` [PATCH v3 1/3] interconnect: debugfs: replace writable string helper Yichong Chen
` (3 more replies)
0 siblings, 4 replies; 8+ messages in thread
From: Yichong Chen @ 2026-08-07 10:00 UTC (permalink / raw)
To: gregkh
Cc: rafael, dakr, djakov, quic_mdtipton, vkoul, yung-chuan.liao,
pierre-louis.bossart, driver-core, linux-kernel, linux-pm,
linux-sound, Yichong Chen
debugfs_create_str() has a generic write implementation that replaces the
backing string. Concurrent writers can race and free the same old string
twice.
Instead of adding more locking to the generic helper, convert the existing
writable in-tree users to local file operations and make
debugfs_create_str() read-only.
Changes since v2:
- Use scoped mutex guards in the interconnect and SoundWire conversions.
- Clarify why GFP_KERNEL is safe in the interconnect conversion after the
RCU read-side critical section is removed.
- Drop the unnecessary firmware_file = NULL assignment in the SoundWire
exit path.
- Use WARN() instead of WARN_ONCE() so each writable debugfs_create_str()
caller can be reported.
Changes since v1:
- Follow Greg's suggestion to avoid adding locking to the generic
debugfs_create_str() write path.
- Convert the existing writable in-tree users to local file operations.
- Make debugfs_create_str() read-only and refuse writable modes.
- Split the change into a 3-patch series.
Yichong Chen (3):
interconnect: debugfs: replace writable string helper
soundwire: debugfs: replace writable string helper
debugfs: make debugfs_create_str() read-only
drivers/interconnect/debugfs-client.c | 81 +++++++++++++++++++++------
drivers/soundwire/debugfs.c | 63 ++++++++++++++++++---
fs/debugfs/file.c | 81 ++++-----------------------
3 files changed, 129 insertions(+), 96 deletions(-)
--
2.51.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 1/3] interconnect: debugfs: replace writable string helper
2026-08-07 10:00 [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only Yichong Chen
@ 2026-08-07 10:00 ` Yichong Chen
2026-08-07 10:00 ` [PATCH v3 2/3] soundwire: " Yichong Chen
` (2 subsequent siblings)
3 siblings, 0 replies; 8+ messages in thread
From: Yichong Chen @ 2026-08-07 10:00 UTC (permalink / raw)
To: gregkh
Cc: rafael, dakr, djakov, quic_mdtipton, vkoul, yung-chuan.liao,
pierre-louis.bossart, driver-core, linux-kernel, linux-pm,
linux-sound, Yichong Chen
debugfs_create_str() is being made read-only because its generic write
path is hard to make safe without adding more locking to the helper.
Convert the interconnect debugfs client src_node and dst_node entries to
local file operations before removing writable string support from
debugfs_create_str(). Protect the string replacement and path lookup with
the existing debugfs_lock.
The old code duplicated the strings under rcu_read_lock(), so it had to use
GFP_ATOMIC. The local file operations protect src_node and dst_node with
debugfs_lock instead, so the allocation can use GFP_KERNEL.
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
---
drivers/interconnect/debugfs-client.c | 81 +++++++++++++++++++++------
1 file changed, 64 insertions(+), 17 deletions(-)
diff --git a/drivers/interconnect/debugfs-client.c b/drivers/interconnect/debugfs-client.c
index 08df9188ef94..c587fbf519c6 100644
--- a/drivers/interconnect/debugfs-client.c
+++ b/drivers/interconnect/debugfs-client.c
@@ -5,6 +5,7 @@
#include <linux/debugfs.h>
#include <linux/interconnect.h>
#include <linux/platform_device.h>
+#include <linux/slab.h>
#include "internal.h"
@@ -36,6 +37,59 @@ struct debugfs_path {
struct list_head list;
};
+static ssize_t icc_node_read(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char **node = file->private_data;
+ char *copy;
+ size_t len;
+ ssize_t ret;
+
+ scoped_guard(mutex, &debugfs_lock) {
+ copy = kstrdup(*node ?: "", GFP_KERNEL);
+ }
+ if (!copy)
+ return -ENOMEM;
+
+ len = strlen(copy);
+ copy[len++] = '\n';
+ ret = simple_read_from_buffer(user_buf, count, ppos, copy, len);
+ kfree(copy);
+ return ret;
+}
+
+static ssize_t icc_node_write(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char **node = file->private_data;
+ char *old, *new;
+
+ if (*ppos)
+ return -EINVAL;
+ if (count + 1 > PAGE_SIZE)
+ return -E2BIG;
+
+ new = memdup_user_nul(user_buf, count);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+ strim(new);
+
+ scoped_guard(mutex, &debugfs_lock) {
+ old = *node;
+ *node = new;
+ }
+
+ kfree(old);
+ return count;
+}
+
+static const struct file_operations icc_node_fops = {
+ .open = simple_open,
+ .read = icc_node_read,
+ .write = icc_node_write,
+ .llseek = default_llseek,
+};
+
static struct icc_path *get_path(const char *src, const char *dst)
{
struct debugfs_path *path;
@@ -54,26 +108,19 @@ static int icc_get_set(void *data, u64 val)
char *src, *dst;
int ret = 0;
- mutex_lock(&debugfs_lock);
-
- rcu_read_lock();
- src = rcu_dereference(src_node);
- dst = rcu_dereference(dst_node);
+ guard(mutex)(&debugfs_lock);
/*
* If we've already looked up a path, then use the existing one instead
* of calling icc_get() again. This allows for updating previous BW
* votes when "get" is written to multiple times for multiple paths.
*/
- cur_path = get_path(src, dst);
- if (cur_path) {
- rcu_read_unlock();
+ cur_path = get_path(src_node, dst_node);
+ if (cur_path)
goto out;
- }
- src = kstrdup(src, GFP_ATOMIC);
- dst = kstrdup(dst, GFP_ATOMIC);
- rcu_read_unlock();
+ src = kstrdup(src_node, GFP_KERNEL);
+ dst = kstrdup(dst_node, GFP_KERNEL);
if (!src || !dst) {
ret = -ENOMEM;
@@ -105,7 +152,6 @@ static int icc_get_set(void *data, u64 val)
kfree(src);
kfree(dst);
out:
- mutex_unlock(&debugfs_lock);
return ret;
}
@@ -115,7 +161,7 @@ static int icc_commit_set(void *data, u64 val)
{
int ret;
- mutex_lock(&debugfs_lock);
+ guard(mutex)(&debugfs_lock);
if (!cur_path) {
ret = -EINVAL;
@@ -130,7 +176,6 @@ static int icc_commit_set(void *data, u64 val)
icc_set_tag(cur_path, tag);
ret = icc_set_bw(cur_path, avg_bw, peak_bw);
out:
- mutex_unlock(&debugfs_lock);
return ret;
}
@@ -160,8 +205,10 @@ int icc_debugfs_client_init(struct dentry *icc_dir)
client_dir = debugfs_create_dir("test_client", icc_dir);
- debugfs_create_str("src_node", 0600, client_dir, &src_node);
- debugfs_create_str("dst_node", 0600, client_dir, &dst_node);
+ debugfs_create_file("src_node", 0600, client_dir, &src_node,
+ &icc_node_fops);
+ debugfs_create_file("dst_node", 0600, client_dir, &dst_node,
+ &icc_node_fops);
debugfs_create_file("get", 0200, client_dir, NULL, &icc_get_fops);
debugfs_create_u32("avg_bw", 0600, client_dir, &avg_bw);
debugfs_create_u32("peak_bw", 0600, client_dir, &peak_bw);
--
2.51.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 2/3] soundwire: debugfs: replace writable string helper
2026-08-07 10:00 [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only Yichong Chen
2026-08-07 10:00 ` [PATCH v3 1/3] interconnect: debugfs: replace writable string helper Yichong Chen
@ 2026-08-07 10:00 ` Yichong Chen
2026-08-07 10:00 ` [PATCH v3 3/3] debugfs: make debugfs_create_str() read-only Yichong Chen
2026-10-01 12:51 ` [PATCH v3 0/3] " Greg KH
3 siblings, 0 replies; 8+ messages in thread
From: Yichong Chen @ 2026-08-07 10:00 UTC (permalink / raw)
To: gregkh
Cc: rafael, dakr, djakov, quic_mdtipton, vkoul, yung-chuan.liao,
pierre-louis.bossart, driver-core, linux-kernel, linux-pm,
linux-sound, Yichong Chen
debugfs_create_str() is being made read-only because its generic write
path is hard to make safe without adding more locking to the helper.
Convert the SoundWire firmware_file entry to a local write-only file
operation before removing writable string support from
debugfs_create_str().
Copy the firmware name before request_firmware() so later debugfs writes
cannot replace the string while it is being used.
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
---
drivers/soundwire/debugfs.c | 63 ++++++++++++++++++++++++++++++++-----
1 file changed, 55 insertions(+), 8 deletions(-)
diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
index 099eb84a548e..a8a6db164fe7 100644
--- a/drivers/soundwire/debugfs.c
+++ b/drivers/soundwire/debugfs.c
@@ -145,6 +145,38 @@ static u32 start_addr;
static size_t num_bytes;
static u8 read_buffer[MAX_CMD_BYTES];
static char *firmware_file;
+static DEFINE_MUTEX(firmware_file_lock);
+
+static ssize_t firmware_file_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ char *old, *new;
+
+ if (*ppos)
+ return -EINVAL;
+ if (count + 1 > PAGE_SIZE)
+ return -E2BIG;
+
+ new = memdup_user_nul(user_buf, count);
+ if (IS_ERR(new))
+ return PTR_ERR(new);
+ strim(new);
+
+ scoped_guard(mutex, &firmware_file_lock) {
+ old = firmware_file;
+ firmware_file = new;
+ }
+
+ kfree(old);
+ return count;
+}
+
+static const struct file_operations firmware_file_fops = {
+ .open = simple_open,
+ .write = firmware_file_write,
+ .llseek = default_llseek,
+};
static int set_command(void *data, u64 value)
{
@@ -246,6 +278,7 @@ static int cmd_go(void *data, u64 value)
{
const struct firmware *fw = NULL;
struct sdw_slave *slave = data;
+ char *fw_name = NULL;
ktime_t start_t;
ktime_t finish_t;
int ret;
@@ -265,15 +298,24 @@ static int cmd_go(void *data, u64 value)
}
if (cmd == 0) {
- ret = request_firmware(&fw, firmware_file, &slave->dev);
+ scoped_guard(mutex, &firmware_file_lock) {
+ if (firmware_file)
+ fw_name = kstrdup(firmware_file, GFP_KERNEL);
+ }
+ if (!fw_name) {
+ ret = -ENOMEM;
+ goto out;
+ }
+
+ ret = request_firmware(&fw, fw_name, &slave->dev);
if (ret < 0) {
- dev_err(&slave->dev, "firmware %s not found\n", firmware_file);
+ dev_err(&slave->dev, "firmware %s not found\n", fw_name);
goto out;
}
if (fw->size < num_bytes) {
dev_err(&slave->dev,
"firmware %s: firmware size %zd, desired %zd\n",
- firmware_file, fw->size, num_bytes);
+ fw_name, fw->size, num_bytes);
goto out;
}
}
@@ -306,6 +348,7 @@ static int cmd_go(void *data, u64 value)
out:
if (fw)
release_firmware(fw);
+ kfree(fw_name);
pm_runtime_mark_last_busy(&slave->dev);
pm_runtime_put(&slave->dev);
@@ -358,7 +401,8 @@ void sdw_slave_debugfs_init(struct sdw_slave *slave)
debugfs_create_file("read_buffer", 0400, d, slave, &read_buffer_fops);
if (firmware_file)
- debugfs_create_str("firmware_file", 0200, d, &firmware_file);
+ debugfs_create_file("firmware_file", 0200, d, NULL,
+ &firmware_file_fops);
slave->debugfs = d;
}
@@ -370,8 +414,10 @@ void sdw_slave_debugfs_exit(struct sdw_slave *slave)
void sdw_debugfs_init(void)
{
- if (!firmware_file)
- firmware_file = kstrdup("", GFP_KERNEL);
+ scoped_guard(mutex, &firmware_file_lock) {
+ if (!firmware_file)
+ firmware_file = kstrdup("", GFP_KERNEL);
+ }
sdw_debugfs_root = debugfs_create_dir("soundwire", NULL);
}
@@ -379,6 +425,7 @@ void sdw_debugfs_init(void)
void sdw_debugfs_exit(void)
{
debugfs_remove_recursive(sdw_debugfs_root);
- kfree(firmware_file);
- firmware_file = NULL;
+ scoped_guard(mutex, &firmware_file_lock) {
+ kfree(firmware_file);
+ }
}
--
2.51.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 3/3] debugfs: make debugfs_create_str() read-only
2026-08-07 10:00 [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only Yichong Chen
2026-08-07 10:00 ` [PATCH v3 1/3] interconnect: debugfs: replace writable string helper Yichong Chen
2026-08-07 10:00 ` [PATCH v3 2/3] soundwire: " Yichong Chen
@ 2026-08-07 10:00 ` Yichong Chen
2026-10-01 12:51 ` [PATCH v3 0/3] " Greg KH
3 siblings, 0 replies; 8+ messages in thread
From: Yichong Chen @ 2026-08-07 10:00 UTC (permalink / raw)
To: gregkh
Cc: rafael, dakr, djakov, quic_mdtipton, vkoul, yung-chuan.liao,
pierre-louis.bossart, driver-core, linux-kernel, linux-pm,
linux-sound, Yichong Chen
debugfs_create_str() supports replacing the backing string from userspace.
Concurrent writers can race and free the same old string twice.
All writable in-tree users have been converted to local file operations.
Remove the generic write support from debugfs_create_str(), and refuse to
create a file when the caller passes write permission bits.
This makes unsupported writable use visible instead of silently creating a
file with different permissions.
Fixes: 86b5488121db ("debugfs: Add write support to debugfs_create_str()")
Signed-off-by: Yichong Chen <chenyichong@uniontech.com>
---
fs/debugfs/file.c | 81 ++++++-----------------------------------------
1 file changed, 10 insertions(+), 71 deletions(-)
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 08de6652a4f3..170feb75317f 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -1049,98 +1049,37 @@ ssize_t debugfs_read_file_str(struct file *file, char __user *user_buf,
return ret;
}
-static ssize_t debugfs_write_file_str(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- 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 __rcu **)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 = {
.read = debugfs_read_file_str,
- .write = debugfs_write_file_str,
- .open = simple_open,
- .llseek = default_llseek,
-};
-
-static const struct file_operations fops_str_ro = {
- .read = debugfs_read_file_str,
- .open = simple_open,
- .llseek = default_llseek,
-};
-
-static const struct file_operations fops_str_wo = {
- .write = debugfs_write_file_str,
.open = simple_open,
.llseek = default_llseek,
};
/**
- * debugfs_create_str - create a debugfs file that is used to read and write a string value
+ * debugfs_create_str - create a debugfs file that is used to read a string value
* @name: a pointer to a string containing the name of the file to create.
* @mode: the permission that the file should have
* @parent: a pointer to the parent dentry for this file. This should be a
* directory dentry if set. If this parameter is %NULL, then the
* file will be created in the root of the debugfs filesystem.
- * @value: a pointer to the variable that the file should read to and write
- * from. This pointer and the string it points to must not be %NULL.
+ * @value: a pointer to the variable that the file should read from. This
+ * pointer and the string it points to must not be %NULL.
*
* This function creates a file in debugfs with the given name that
- * contains the value of the variable @value. If the @mode variable is so
- * set, it can be read from, and written to.
+ * contains the value of the variable @value. The file can be read from.
+ * Writable files are not supported; if @mode contains write permission bits,
+ * no file is created.
*/
void debugfs_create_str(const char *name, umode_t mode,
struct dentry *parent, char **value)
{
if (WARN_ON(!value || !*value))
return;
+ if (WARN(mode & 0222,
+ "%s() does not support writable files\n", __func__))
+ return;
- debugfs_create_mode_unsafe(name, mode, parent, value, &fops_str,
- &fops_str_ro, &fops_str_wo);
+ debugfs_create_file_unsafe(name, mode, parent, value, &fops_str);
}
EXPORT_SYMBOL_GPL(debugfs_create_str);
--
2.51.0
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only
2026-08-07 10:00 [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only Yichong Chen
` (2 preceding siblings ...)
2026-08-07 10:00 ` [PATCH v3 3/3] debugfs: make debugfs_create_str() read-only Yichong Chen
@ 2026-10-01 12:51 ` Greg KH
2026-10-01 13:10 ` Danilo Krummrich
3 siblings, 1 reply; 8+ messages in thread
From: Greg KH @ 2026-10-01 12:51 UTC (permalink / raw)
To: Yichong Chen
Cc: rafael, dakr, djakov, quic_mdtipton, vkoul, yung-chuan.liao,
pierre-louis.bossart, driver-core, linux-kernel, linux-pm,
linux-sound
On Fri, Aug 07, 2026 at 06:00:50PM +0800, Yichong Chen wrote:
> debugfs_create_str() has a generic write implementation that replaces the
> backing string. Concurrent writers can race and free the same old string
> twice.
>
> Instead of adding more locking to the generic helper, convert the existing
> writable in-tree users to local file operations and make
> debugfs_create_str() read-only.
>
> Changes since v2:
> - Use scoped mutex guards in the interconnect and SoundWire conversions.
> - Clarify why GFP_KERNEL is safe in the interconnect conversion after the
> RCU read-side critical section is removed.
> - Drop the unnecessary firmware_file = NULL assignment in the SoundWire
> exit path.
> - Use WARN() instead of WARN_ONCE() so each writable debugfs_create_str()
> caller can be reported.
Sorry for the delay, now applied.
greg k-h
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only
2026-10-01 12:51 ` [PATCH v3 0/3] " Greg KH
@ 2026-10-01 13:10 ` Danilo Krummrich
2026-10-01 13:19 ` Greg KH
0 siblings, 1 reply; 8+ messages in thread
From: Danilo Krummrich @ 2026-10-01 13:10 UTC (permalink / raw)
To: Greg KH
Cc: Yichong Chen, rafael, djakov, quic_mdtipton, vkoul,
yung-chuan.liao, pierre-louis.bossart, driver-core, linux-kernel,
linux-pm, linux-sound
On Thu Oct 1, 2026 at 2:51 PM CEST, Greg KH wrote:
> On Fri, Aug 07, 2026 at 06:00:50PM +0800, Yichong Chen wrote:
>> debugfs_create_str() has a generic write implementation that replaces the
>> backing string. Concurrent writers can race and free the same old string
>> twice.
>>
>> Instead of adding more locking to the generic helper, convert the existing
>> writable in-tree users to local file operations and make
>> debugfs_create_str() read-only.
>>
>> Changes since v2:
>> - Use scoped mutex guards in the interconnect and SoundWire conversions.
>> - Clarify why GFP_KERNEL is safe in the interconnect conversion after the
>> RCU read-side critical section is removed.
>> - Drop the unnecessary firmware_file = NULL assignment in the SoundWire
>> exit path.
>> - Use WARN() instead of WARN_ONCE() so each writable debugfs_create_str()
>> caller can be reported.
>
> Sorry for the delay, now applied.
This series fell through the cracks on my end. I also reported this issue in [1]
and I agree making debugfs_create_str() read-only is the best fix for now.
However, it duplicates code and I think having a proper helper as suggested in
[1] would be nice follow-up.
[1] https://lore.kernel.org/driver-core/DLPDB44JJRGJ.3K6JNS746M7QC@kernel.org/
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only
2026-10-01 13:10 ` Danilo Krummrich
@ 2026-10-01 13:19 ` Greg KH
2026-10-01 13:49 ` Danilo Krummrich
0 siblings, 1 reply; 8+ messages in thread
From: Greg KH @ 2026-10-01 13:19 UTC (permalink / raw)
To: Danilo Krummrich
Cc: Yichong Chen, rafael, djakov, quic_mdtipton, vkoul,
yung-chuan.liao, pierre-louis.bossart, driver-core, linux-kernel,
linux-pm, linux-sound
On Thu, Oct 01, 2026 at 03:10:45PM +0200, Danilo Krummrich wrote:
> On Thu Oct 1, 2026 at 2:51 PM CEST, Greg KH wrote:
> > On Fri, Aug 07, 2026 at 06:00:50PM +0800, Yichong Chen wrote:
> >> debugfs_create_str() has a generic write implementation that replaces the
> >> backing string. Concurrent writers can race and free the same old string
> >> twice.
> >>
> >> Instead of adding more locking to the generic helper, convert the existing
> >> writable in-tree users to local file operations and make
> >> debugfs_create_str() read-only.
> >>
> >> Changes since v2:
> >> - Use scoped mutex guards in the interconnect and SoundWire conversions.
> >> - Clarify why GFP_KERNEL is safe in the interconnect conversion after the
> >> RCU read-side critical section is removed.
> >> - Drop the unnecessary firmware_file = NULL assignment in the SoundWire
> >> exit path.
> >> - Use WARN() instead of WARN_ONCE() so each writable debugfs_create_str()
> >> caller can be reported.
> >
> > Sorry for the delay, now applied.
>
> This series fell through the cracks on my end. I also reported this issue in [1]
> and I agree making debugfs_create_str() read-only is the best fix for now.
>
> However, it duplicates code and I think having a proper helper as suggested in
> [1] would be nice follow-up.
>
> [1] https://lore.kernel.org/driver-core/DLPDB44JJRGJ.3K6JNS746M7QC@kernel.org/
Yes, that would be nice, but for read-only debugfs strings, let's keep
writable ones away if at all possible :)
thanks,
greg k-h
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only
2026-10-01 13:19 ` Greg KH
@ 2026-10-01 13:49 ` Danilo Krummrich
0 siblings, 0 replies; 8+ messages in thread
From: Danilo Krummrich @ 2026-10-01 13:49 UTC (permalink / raw)
To: Greg KH
Cc: Yichong Chen, rafael, djakov, quic_mdtipton, vkoul,
yung-chuan.liao, pierre-louis.bossart, driver-core, linux-kernel,
linux-pm, linux-sound
On Thu Oct 1, 2026 at 3:19 PM CEST, Greg KH wrote:
> On Thu, Oct 01, 2026 at 03:10:45PM +0200, Danilo Krummrich wrote:
>> On Thu Oct 1, 2026 at 2:51 PM CEST, Greg KH wrote:
>> > On Fri, Aug 07, 2026 at 06:00:50PM +0800, Yichong Chen wrote:
>> >> debugfs_create_str() has a generic write implementation that replaces the
>> >> backing string. Concurrent writers can race and free the same old string
>> >> twice.
>> >>
>> >> Instead of adding more locking to the generic helper, convert the existing
>> >> writable in-tree users to local file operations and make
>> >> debugfs_create_str() read-only.
>> >>
>> >> Changes since v2:
>> >> - Use scoped mutex guards in the interconnect and SoundWire conversions.
>> >> - Clarify why GFP_KERNEL is safe in the interconnect conversion after the
>> >> RCU read-side critical section is removed.
>> >> - Drop the unnecessary firmware_file = NULL assignment in the SoundWire
>> >> exit path.
>> >> - Use WARN() instead of WARN_ONCE() so each writable debugfs_create_str()
>> >> caller can be reported.
>> >
>> > Sorry for the delay, now applied.
>>
>> This series fell through the cracks on my end. I also reported this issue in [1]
>> and I agree making debugfs_create_str() read-only is the best fix for now.
>>
>> However, it duplicates code and I think having a proper helper as suggested in
>> [1] would be nice follow-up.
>>
>> [1] https://lore.kernel.org/driver-core/DLPDB44JJRGJ.3K6JNS746M7QC@kernel.org/
>
> Yes, that would be nice, but for read-only debugfs strings, let's keep
> writable ones away if at all possible :)
The two converted subsystems now have identical code that can easily be
generalized. And I think we have other users that open code this too.
For instance, soundwire would collapse to just:
In sdw_debugfs_init():
/* Initialize struct debugfs_string */
ret = debugfs_string_create(&firmware_file, "");
In sdw_debugfs_exit():
/* Free struct debugfs_string */
debugfs_string_free(&firmware_file);
In sdw_slave_debugfs_init():
debugfs_create_str("firmware_file", 0600, d, &firmware_file);
In cmd_go():
scoped_guard(debugfs_string, &firmware_file)
ret = request_firmware(&fw,
debugfs_string_read_locked(&firmware_file),
&slave->dev);
Thanks,
Danilo
^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2026-10-01 13:50 UTC | newest]
Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-07 10:00 [PATCH v3 0/3] debugfs: make debugfs_create_str() read-only Yichong Chen
2026-08-07 10:00 ` [PATCH v3 1/3] interconnect: debugfs: replace writable string helper Yichong Chen
2026-08-07 10:00 ` [PATCH v3 2/3] soundwire: " Yichong Chen
2026-08-07 10:00 ` [PATCH v3 3/3] debugfs: make debugfs_create_str() read-only Yichong Chen
2026-10-01 12:51 ` [PATCH v3 0/3] " Greg KH
2026-10-01 13:10 ` Danilo Krummrich
2026-10-01 13:19 ` Greg KH
2026-10-01 13:49 ` Danilo Krummrich
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®