* [PATCH] gpio: virtuser: remove the debugfs files before freeing the line data
@ 2026-11-02 7:57 Yu Zhang
0 siblings, 0 replies; only message in thread
From: Yu Zhang @ 2026-11-02 7:57 UTC (permalink / raw)
To: Bartosz Golaszewski, Linus Walleij; +Cc: linux-gpio, linux-kernel, stable
gpio_virtuser_probe() registers the devm action that removes the debugfs
directory before it allocates the per-line and per-array data that the
debugfs files point to. devres releases resources in reverse order, so
on unbind the line data is freed, the consumer_lock mutex is destroyed
and the GPIO descriptors are put first, and the debugfs files are only
removed afterwards.
A read or write of any of the per-line debugfs files (value, direction,
consumer, interrupts, ...) that runs in that window dereferences the
freed data. debugfs_remove_recursive() waits for in-flight file
operations, but by then the data has already been freed.
Running eight threads that read the per-line debugfs files while
another task writes 1 and 0 to the configfs "live" attribute triggers
this within a second on a KASAN kernel, with gpio-sim as the provider:
BUG: KASAN: slab-use-after-free in gpio_virtuser_value_get+0x19/0x60
Read of size 8 at addr ffff888005109e38 by task vu_race/3479
Call Trace:
gpio_virtuser_value_get+0x19/0x60
simple_attr_read+0x109/0x290
debugfs_attr_read+0x5e/0x80
full_proxy_read+0xae/0xe0
vfs_read+0x1bc/0x7a0
Allocated by task 1:
devm_kmalloc+0x89/0x1d0
gpio_virtuser_probe+0x56f/0x910
Freed by task 1:
kfree+0x196/0x430
release_nodes+0x77/0xa0
devres_release_all+0xf3/0x150
device_unbind_cleanup+0x18/0x130
...
platform_device_unregister+0x3c/0x50
gpio_virtuser_device_deactivate+0x3c/0xc0
The same run also reports use-after-free on the freed consumer_lock
from the consumer attribute.
Register the debugfs removal action after the line data has been set
up, so that it runs first on unbind, and remove the directory by hand
on the probe error paths before that point.
Fixes: 91581c4b3f29 ("gpio: virtuser: new virtual testing driver for the GPIO API")
Cc: stable@vger.kernel.org
Signed-off-by: Yu Zhang <yuz08559@gmail.com>
---
drivers/gpio/gpio-virtuser.c | 46 +++++++++++++++++++++++-------------
1 file changed, 29 insertions(+), 17 deletions(-)
diff --git a/drivers/gpio/gpio-virtuser.c b/drivers/gpio/gpio-virtuser.c
index 70ddccc..03fa951 100644
--- a/drivers/gpio/gpio-virtuser.c
+++ b/drivers/gpio/gpio-virtuser.c
@@ -927,38 +927,50 @@ static int gpio_virtuser_probe(struct platform_device *pdev)
"Failed to get the IDs of GPIOs to request\n");
dbgfs_entry = debugfs_create_dir(dev_name(dev), gpio_virtuser_dbg_root);
- ret = devm_add_action_or_reset(dev, gpio_virtuser_debugfs_remove,
- dbgfs_entry);
- if (ret)
- return ret;
for (i = 0; i < num_ids; i++) {
descs = devm_gpiod_get_array(dev, ids[i], GPIOD_ASIS);
- if (IS_ERR(descs))
- return dev_err_probe(dev, PTR_ERR(descs),
- "Failed to request the '%s' GPIOs\n",
- ids[i]);
+ if (IS_ERR(descs)) {
+ ret = dev_err_probe(dev, PTR_ERR(descs),
+ "Failed to request the '%s' GPIOs\n",
+ ids[i]);
+ goto err_remove_debugfs;
+ }
ret = gpio_virtuser_dbgfs_init_line_array_attrs(dev, descs,
ids[i],
dbgfs_entry);
- if (ret)
- return dev_err_probe(dev, ret,
- "Failed to setup the debugfs array interface for the '%s' GPIOs\n",
- ids[i]);
+ if (ret) {
+ dev_err_probe(dev, ret,
+ "Failed to setup the debugfs array interface for the '%s' GPIOs\n",
+ ids[i]);
+ goto err_remove_debugfs;
+ }
for (j = 0; j < descs->ndescs; j++) {
ret = gpio_virtuser_dbgfs_init_line_attrs(dev,
descs->desc[j], ids[i],
j, dbgfs_entry);
- if (ret)
- return dev_err_probe(dev, ret,
- "Failed to setup the debugfs line interface for the '%s' GPIOs\n",
- ids[i]);
+ if (ret) {
+ dev_err_probe(dev, ret,
+ "Failed to setup the debugfs line interface for the '%s' GPIOs\n",
+ ids[i]);
+ goto err_remove_debugfs;
+ }
}
}
- return 0;
+ /*
+ * The debugfs files point to the devres-managed line data allocated
+ * above. Register the removal last so that it runs first on unbind,
+ * before any of that data is released.
+ */
+ return devm_add_action_or_reset(dev, gpio_virtuser_debugfs_remove,
+ dbgfs_entry);
+
+err_remove_debugfs:
+ debugfs_remove_recursive(dbgfs_entry);
+ return ret;
}
static const struct of_device_id gpio_virtuser_of_match[] = {
--
2.43.0
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2026-11-02 7:57 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-02 7:57 [PATCH] gpio: virtuser: remove the debugfs files before freeing the line data Yu Zhang
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®