[PATCH] bus: moxtet: fix use-after-free in debugfs files on unbind
From: Cengiz Can
Date: Mon Jul 27 2026 - 19:14:17 EST
moxtet exposes two debugfs files, "input" and "output", whose handlers
dereference the per-device struct moxtet. They are created with
debugfs_create_file_unsafe(), and the handlers never take a debugfs
reference. Nothing keeps the object alive while a handler runs.
The struct moxtet is allocated with devm_kzalloc(). devres frees it when
the SPI device is unbound. debugfs_create_file_unsafe() installs no
full_proxy wrapper, so debugfs_remove_recursive() in moxtet_remove() does
not wait for an in-flight handler. moxtet_remove() then destroys
moxtet->lock. A read or write that races an unbind therefore touches
freed memory and unlocks a destroyed mutex:
output_write() moxtet_remove()
moxtet = file->private_data
mutex_lock(&moxtet->lock)
spi_write() [sleeps]
moxtet_unregister_debugfs()
debugfs_remove_recursive() [no wait]
mutex_destroy(&moxtet->lock)
(remove returns; devres frees moxtet)
<resumes on freed moxtet>
The race is reachable by root via /sys/bus/spi/drivers/moxtet/unbind.
Create the files with debugfs_create_file() instead. Its full_proxy
wrapper makes debugfs_remove_recursive() drain any in-flight handler
before it returns, so the object cannot be freed under a handler.
The mechanism is confirmed under KASAN with a minimal reproducer of the
same debugfs_create_file_unsafe() plus devm_kzalloc() pattern (available
on request); it produces a slab-use-after-free in the handler.
Fixes: 5bc7f990cd98 ("bus: Add support for Moxtet bus")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Cengiz Can <cengiz.can@xxxxxxxxxxxxx>
---
drivers/bus/moxtet.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/bus/moxtet.c b/drivers/bus/moxtet.c
index 0d68c1a9f493..5087aa7d2e5b 100644
--- a/drivers/bus/moxtet.c
+++ b/drivers/bus/moxtet.c
@@ -560,13 +560,13 @@ static int moxtet_register_debugfs(struct moxtet *moxtet)
if (IS_ERR(root))
return PTR_ERR(root);
- entry = debugfs_create_file_unsafe("input", 0444, root, moxtet,
- &input_fops);
+ entry = debugfs_create_file("input", 0444, root, moxtet,
+ &input_fops);
if (IS_ERR(entry))
goto err_remove;
- entry = debugfs_create_file_unsafe("output", 0644, root, moxtet,
- &output_fops);
+ entry = debugfs_create_file("output", 0644, root, moxtet,
+ &output_fops);
if (IS_ERR(entry))
goto err_remove;
--
2.43.0