[PATCH v1] i2c: slave-testunit: prevent work requeueing during remove
From: Yibo Tan
Date: Sat Sep 12 2026 - 12:23:47 EST
i2c_slave_testunit_remove() cancels the delayed worker while the slave
callback is still registered. An adapter callback which is already in
flight can subsequently handle I2C_SLAVE_STOP and queue the worker after
the cancellation has completed.
Remove then unregisters the slave callback and returns. Device-managed
cleanup frees the containing struct testunit_data, leaving the delayed
worker to dereference freed memory.
Use disable_delayed_work_sync() to drain the worker and reject queue
attempts which race with removal.
The issue was reproduced with the real slave-testunit module and its
normal sysfs create/delete path on a four-CPU KASAN kernel. A virtual
slave-capable adapter supplied standard I2C slave events without calling
driver-private functions. The unmodified driver completed 1000 removal
cycles and produced 111 slab-use-after-free reports in
i2c_slave_testunit_work(). The fixed driver completed the same 1000
cycles, including 993 transactions which reached STOP after target
unregistration began, without a KASAN report, warning, Oops or panic.
The reproducer uses administrator-only backend creation and removal. An
external I2C master can supply the command and STOP timing but cannot
independently remove the Linux test backend. No unprivileged or remote
security boundary is claimed.
Fixes: a8335c64c5f0 ("i2c: add slave testunit driver")
Assisted-by: Codex:GPT-5
Signed-off-by: Yibo Tan <lhfff@xxxxxxxxxx>
---
drivers/i2c/i2c-slave-testunit.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/i2c/i2c-slave-testunit.c b/drivers/i2c/i2c-slave-testunit.c
index 4a1bf1aa504b..97a7542fa8b0 100644
--- a/drivers/i2c/i2c-slave-testunit.c
+++ b/drivers/i2c/i2c-slave-testunit.c
@@ -265,7 +265,7 @@ static void i2c_slave_testunit_remove(struct i2c_client *client)
{
struct testunit_data *tu = i2c_get_clientdata(client);
- cancel_delayed_work_sync(&tu->worker);
+ disable_delayed_work_sync(&tu->worker);
i2c_slave_unregister(client);
}
--
2.39.5