In regmap_debugfs_init the initialisation of the debugfs is delayed
if the root node isn't ready yet. Most callers of regmap_debugfs_init
pass the name from the regmap_config, which is considered temporary
ie. may be unallocated after the regmap_init call returns. This leads
to a potential use after free, where config->name has been freed by
the time it is used in regmap_debugfs_initcall.
This situation can be seen on Zynq, where the architecture init_irq
callback registers a syscon device, using a local variable for the
regmap_config. As init_irq is very early in the platform bring up the
regmap debugfs root isn't ready yet. Although this doesn't crash it
does result in the debugfs entry not having the correct name.
Signed-off-by: Charles Keepax <[email protected]>
---
drivers/base/regmap/regmap-debugfs.c | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index f58baff2be0af..184fc327192bf 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -569,7 +569,12 @@ void regmap_debugfs_init(struct regmap *map, const char *name)
if (!node)
return;
node->map = map;
- node->name = name;
+ node->name = kstrdup(name, GFP_KERNEL);
+ if (!node->name) {
+ kfree(node);
+ return;
+ }
+
mutex_lock(®map_debugfs_early_lock);
list_add(&node->link, ®map_debugfs_early_list);
mutex_unlock(®map_debugfs_early_lock);
@@ -681,6 +686,7 @@ void regmap_debugfs_initcall(void)
list_for_each_entry_safe(node, tmp, ®map_debugfs_early_list, link) {
regmap_debugfs_init(node->map, node->name);
list_del(&node->link);
+ kfree(node->name);
kfree(node);
}
mutex_unlock(®map_debugfs_early_lock);
--
2.11.0
On Wed, Sep 16, 2020 at 04:44:33PM +0100, Charles Keepax wrote:
> - node->name = name;
> + node->name = kstrdup(name, GFP_KERNEL);
> + if (!node->name) {
Two things here - one is that this should be kstrdup_const(), the other
is that we already took a copy of the name in __regmap_init() so the
thing to do here is to change the regmap_debugfs_init() call there to
use the copy we just made rather than the copy in the config.