[PATCH] scsi: mvsas: fix tasklet use-after-free in mvs_pci_remove

Fan Wu <[email protected]> Tue, 11 Aug 2026 02:52:12 +0000
Newsgroups gmane.linux.scsi,gmane.linux.kernel,gmane.linux.kernel.stable
Message-ID <[email protected]>
The tasklet is killed before the device IRQ is freed. The IRQ handler
schedules the tasklet, so an interrupt after tasklet_kill() can
reschedule it to run after its backing data has been freed, and the
tasklet re-enables the interrupt on exit. Move tasklet_kill() below
free_irq() and disable the interrupt again once it has drained.

This issue was found by an in-house static analysis tool.

Fixes: 6f8ac161b8b3 ("[SCSI] mvsas: Add support for interrupt tasklet")
Cc: [email protected]
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <[email protected]>
---
 drivers/scsi/mvsas/mv_init.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/drivers/scsi/mvsas/mv_init.c b/drivers/scsi/mvsas/mv_init.c
--- a/drivers/scsi/mvsas/mv_init.c
+++ b/drivers/scsi/mvsas/mv_init.c
@@ -588,13 +588,14 @@ static void mvs_pci_remove(struct pci_dev *pdev)
 	core_nr = ((struct mvs_prv_info *)sha->lldd_ha)->n_host;
 	mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[0];

-#ifdef CONFIG_SCSI_MVSAS_TASKLET
-	tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
-#endif
-
 	sas_unregister_ha(sha);
 	sas_remove_host(mvi->shost);

 	MVS_CHIP_DISP->interrupt_disable(mvi);
 	free_irq(mvi->pdev->irq, sha);
+#ifdef CONFIG_SCSI_MVSAS_TASKLET
+	/* drain after free_irq(): the tasklet re-enables the IRQ on exit */
+	tasklet_kill(&((struct mvs_prv_info *)sha->lldd_ha)->mv_tasklet);
+	MVS_CHIP_DISP->interrupt_disable(mvi);
+#endif
 	for (i = 0; i < core_nr; i++) {
 		mvi = ((struct mvs_prv_info *)sha->lldd_ha)->mvi[i];
 		mvs_free(mvi);
--
2.39.5