linux-scsi.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1] scsi: scsi_debug: Drain RCU callbacks before module exit
@ 2026-09-12  7:47 Yibo Tan
  2026-09-12  8:02 ` sashiko-bot
  0 siblings, 1 reply; 2+ messages in thread
From: Yibo Tan @ 2026-09-12  7:47 UTC (permalink / raw)
  To: James E.J. Bottomley, Martin K. Petersen
  Cc: Wenchao Hao, Douglas Gilbert, linux-scsi, linux-kernel, stable

Replacing or removing a debugfs error-injection rule queues
sdebug_err_free() through call_rcu(). Device teardown also queues this
callback for every remaining rule. The callback resides in scsi_debug
module text, but scsi_debug_exit() does not wait for queued callbacks
before returning.

With lazy, offloaded RCU callbacks enabled, two runs replaced the same
error-injection rule 16 times and successfully unloaded scsi_debug.
Eleven seconds later rcuop/0 executed at the former module text base plus
0x1f0, the exact ELF offset of sdebug_err_free(), and hit the module
unload poison.

Call rcu_barrier() after teardown has stopped future callback submissions
so that all queued callbacks finish before the module text is released.
Two runs with the fix completed the 30-second post-unload observation
without an Oops, KASAN report, warning or panic.

The tested scsi_debug.c is byte-identical to the file in current mainline
and the current SCSI for-next branch.

A source reproducer, kernel configuration, complete serial logs and the
vulnerable/fixed result table are available at:

https://github.com/kimaiden1984-boop/linux-kernel-poc-collections/tree/main/cases/scsi-debug-rcu-callback-after-unload

Fixes: a9996d722b11 ("scsi: scsi_debug: Add interface to manage error injection for a single device")
Cc: stable@vger.kernel.org
Assisted-by: Codex:GPT-5
Signed-off-by: Yibo Tan <lhfff@tju.edu.cn>
---
 drivers/scsi/scsi_debug.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index 3346562275f8..2fdb1cbe470b 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -8676,6 +8676,7 @@ static void __exit scsi_debug_exit(void)
 	sdebug_erase_all_stores(false);
 	xa_destroy(per_store_ap);
 	debugfs_remove(sdebug_debugfs_root);
+	rcu_barrier();
 }
 
 device_initcall(scsi_debug_init);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 2+ messages in thread

* Re: [PATCH v1] scsi: scsi_debug: Drain RCU callbacks before module exit
  2026-09-12  7:47 [PATCH v1] scsi: scsi_debug: Drain RCU callbacks before module exit Yibo Tan
@ 2026-09-12  8:02 ` sashiko-bot
  0 siblings, 0 replies; 2+ messages in thread
From: sashiko-bot @ 2026-09-12  8:02 UTC (permalink / raw)
  To: Yibo Tan; +Cc: linux-scsi

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:

Pre-existing issues:
- [High] The RCU-protected pointer `err` is dereferenced after dropping `rcu_read_unlock()`, leading to a use-after-free.
--

commit b240d3e53ad8297843c17afca537b20b652bc674
Author: Yibo Tan <lhfff@tju.edu.cn>

scsi: scsi_debug: Drain RCU callbacks before module exit

Replacing or removing a debugfs error-injection rule queues callbacks
through call_rcu() during device teardown. This commit adds a call to
rcu_barrier() in scsi_debug_exit() to ensure all queued callbacks
finish before the module text is released. This prevents a crash when
executing module unload procedures.

Link: https://github.com/kimaiden1984-boop/linux-kernel-poc-collections/tree/main/cases/scsi-debug-rcu-callback-after-unload

> diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
> --- a/drivers/scsi/scsi_debug.c
> +++ b/drivers/scsi/scsi_debug.c

[ ... ]

> @@ -8844,6 +8844,7 @@ static void __exit scsi_debug_exit(void)
>  	sdebug_erase_all_stores(false);
>  	xa_destroy(per_store_ap);
>  	debugfs_remove(sdebug_debugfs_root);
> +	rcu_barrier();
>  }

While reviewing the RCU changes in this file, I noticed a separate issue
in sdebug_fail_cmd():

drivers/scsi/scsi_debug.c:sdebug_fail_cmd() {
    ...
    rcu_read_unlock();
    goto out_handle;
    ...
out_handle:
    if (err->cnt < 0)
        err->cnt++;
    mk_sense_buffer(cmnd, err->sense_key, err->asc, err->asq);
    result = err->status_byte | err->host_byte << 16 | err->driver_byte << 24;
    *info = *err;
    ...
}

[Severity: High]
This is a pre-existing issue, but does dropping the RCU read lock before 
dereferencing the RCU-protected pointer err lead to a use-after-free?

If a user writes to the debugfs error injection file to remove or replace 
a rule, the structure could be freed concurrently. Since the reader drops 
the RCU read lock before it finishes accessing err, could this result in 
reading from freed memory and returning corrupted sense data?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260912074737.972055-1-lhfff@tju.edu.cn?part=1

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-09-12  8:02 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-12  7:47 [PATCH v1] scsi: scsi_debug: Drain RCU callbacks before module exit Yibo Tan
2026-09-12  8:02 ` sashiko-bot

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).