[PATCH v2] scsi: dc395x: sync the waiting_timer before freeing the host
From: Fan Wu
Date: Thu Sep 10 2026 - 22:07:20 EST
The waiting_timer callback re-arms itself and takes the host lock.
adapter_uninit() currently stops it with timer_delete(), which does not
wait for a callback already running on another CPU. The final
scsi_host_put() that frees the host (and the host lock the callback
dereferences) runs right after adapter_uninit(), so a concurrent or just
re-armed callback can fire after the free, leaving a potential
use-after-free window.
Replace timer_delete() with timer_shutdown_sync() at the top of
adapter_uninit(), before the host-lock section: the timer is dequeued,
a running callback is waited for and rearming is blocked before the chip
is halted, so it cannot fire at all once the adapter has ceased to
function. Waiting outside the lock avoids the self-deadlock that would
result from syncing a callback blocked on the lock we still hold.
No shutdown is needed for selto_timer because it has no reachable armer
or callback.
This issue was found by an in-house static analysis tool.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Cc: stable@xxxxxxxxxxxxxxx
Cc: Jamie Lenehan <lenehan@xxxxxxxxxxx>
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01@xxxxxxxxxx>
---
v2:
- Move timer_shutdown_sync() before adapter_uninit_chip(), as
suggested by Oliver Neukum.
v1: https://lore.kernel.org/all/20260810055028.119525-1-fanwu01@xxxxxxxxxx/
drivers/scsi/dc395x.c | 10 ++++------
1 file changed, 4 insertions(+), 6 deletions(-)
diff --git a/drivers/scsi/dc395x.c b/drivers/scsi/dc395x.c
index 6183ce05d..fcd4c0029 100644
--- a/drivers/scsi/dc395x.c
+++ b/drivers/scsi/dc395x.c
@@ -3814,13 +3814,11 @@ static void adapter_uninit_chip(struct AdapterCtlBlk *acb)
static void adapter_uninit(struct AdapterCtlBlk *acb)
{
unsigned long flags;
- DC395x_LOCK_IO(acb->scsi_host, flags);
- /* remove timers */
- if (timer_pending(&acb->waiting_timer))
- timer_delete(&acb->waiting_timer);
- if (timer_pending(&acb->selto_timer))
- timer_delete(&acb->selto_timer);
+ /* Drain the self-rearming timer; must not run under host_lock. */
+ timer_shutdown_sync(&acb->waiting_timer);
+
+ DC395x_LOCK_IO(acb->scsi_host, flags);
adapter_uninit_chip(acb);
adapter_remove_and_free_all_devices(acb);
--
2.34.1