]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
regmap: debugfs: fix race condition in dummy name allocation
authorZxyan Zhu <zxyan0222@gmail.com>
Thu, 9 Apr 2026 03:50:15 +0000 (11:50 +0800)
committerMark Brown <broonie@kernel.org>
Thu, 9 Apr 2026 19:50:54 +0000 (20:50 +0100)
Use IDA instead of a simple counter for generating unique dummy names.
The previous implementation used dummy_index++ which is not atomic,
leading to potential duplicate names when multiple threads call
regmap_debugfs_init() concurrently with name="dummy".

Signed-off-by: Zxyan Zhu <zxyan0222@gmail.com>
Link: https://patch.msgid.link/20260409035015.950764-1-zxyan0222@gmail.com
Signed-off-by: Mark Brown <broonie@kernel.org>
drivers/base/regmap/internal.h
drivers/base/regmap/regmap-debugfs.c

index c77f3a49a89e23d8bf5e514665996bbb7a8bff68..55273a6178f8d773ddf1d3f0fd800299fd444033 100644 (file)
@@ -84,6 +84,7 @@ struct regmap {
        bool debugfs_disable;
        struct dentry *debugfs;
        const char *debugfs_name;
+       int debugfs_dummy_id;
 
        unsigned int debugfs_reg_len;
        unsigned int debugfs_val_len;
index 5a46ce5fee72a3621020bd20a296fea7ed080045..18f1c60749fed572d357f3f33ce7d6a7f520740c 100644 (file)
@@ -12,6 +12,7 @@
 #include <linux/uaccess.h>
 #include <linux/device.h>
 #include <linux/list.h>
+#include <linux/idr.h>
 
 #include "internal.h"
 
@@ -20,7 +21,7 @@ struct regmap_debugfs_node {
        struct list_head link;
 };
 
-static unsigned int dummy_index;
+static DEFINE_IDA(dummy_ida);
 static struct dentry *regmap_debugfs_root;
 static LIST_HEAD(regmap_debugfs_early_list);
 static DEFINE_MUTEX(regmap_debugfs_early_lock);
@@ -539,6 +540,7 @@ void regmap_debugfs_init(struct regmap *map)
        struct regmap_range_node *range_node;
        const char *devname = "dummy";
        const char *name = map->name;
+       int id;
 
        /*
         * Userspace can initiate reads from the hardware over debugfs.
@@ -567,6 +569,7 @@ void regmap_debugfs_init(struct regmap *map)
 
        INIT_LIST_HEAD(&map->debugfs_off_cache);
        mutex_init(&map->cache_lock);
+       map->debugfs_dummy_id = -1;
 
        if (map->dev)
                devname = dev_name(map->dev);
@@ -585,12 +588,16 @@ void regmap_debugfs_init(struct regmap *map)
 
        if (!strcmp(name, "dummy")) {
                kfree(map->debugfs_name);
-               map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d",
-                                               dummy_index);
-               if (!map->debugfs_name)
+               id = ida_alloc(&dummy_ida, GFP_KERNEL);
+               if (id < 0)
                        return;
+               map->debugfs_name = kasprintf(GFP_KERNEL, "dummy%d", id);
+               if (!map->debugfs_name) {
+                       ida_free(&dummy_ida, id);
+                       return;
+               }
+               map->debugfs_dummy_id = id;
                name = map->debugfs_name;
-               dummy_index++;
        }
 
        map->debugfs = debugfs_create_dir(name, regmap_debugfs_root);
@@ -660,6 +667,10 @@ void regmap_debugfs_exit(struct regmap *map)
                mutex_lock(&map->cache_lock);
                regmap_debugfs_free_dump_cache(map);
                mutex_unlock(&map->cache_lock);
+               if (map->debugfs_dummy_id >= 0) {
+                       ida_free(&dummy_ida, map->debugfs_dummy_id);
+                       map->debugfs_dummy_id = -1;
+               }
                kfree(map->debugfs_name);
                map->debugfs_name = NULL;
        } else {