qla2x00t-32gbit: Fix cs84xx use-after-free on host teardown

qla84xx_put_chip() drops the last reference to ha->cs84xx and frees it via
__qla84xx_chip_release() without clearing ha->cs84xx. During teardown it ran
before scsi_remove_host(), which is what removes the 84xx_fw_version host
sysfs attribute. A concurrent read of that attribute in the window between
the two calls executes qla24xx_84xx_fw_version_show(), which dereferences
the freed ha->cs84xx, resulting in a use-after-free.

Move qla84xx_put_chip() to after scsi_remove_host() in both
qla2x00_remove_one() and qla2x00_disable_board_on_pci_error(). Once
scsi_remove_host() returns, the sysfs attribute is gone and kernfs has
drained any in-flight show(), so no reader can touch cs84xx; the put still
runs before the host and ha are freed.

Fixes: fe1b806f4f71 ("[SCSI] qla2xxx: Refactor shutdown code so some functionality can be reused.")
Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-dev@google.com>
Signed-off-by: Nilesh Javali <njavali@marvell.com>
Link: https://patch.msgid.link/20260730155838.2119230-7-njavali@marvell.com
Signed-off-by: Martin K. Petersen (Oracle) <mkp@kernel.org>

[ commit 33d102102d925357c5fd172dd6672a27d74b3215 upstream ]
This commit is contained in:
Nilesh Javali
2026-10-19 17:38:13 +03:00
committed by Gleb Chesnokov
parent 52e1503088
commit a6cf4570a0
+4 -4
View File
@@ -4178,8 +4178,6 @@ qla2x00_remove_one(struct pci_dev *pdev)
qla2x00_dfs_remove(base_vha);
qla84xx_put_chip(base_vha);
/* Disable timer */
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
@@ -4204,6 +4202,8 @@ qla2x00_remove_one(struct pci_dev *pdev)
scsi_remove_host(base_vha->host);
qla84xx_put_chip(base_vha);
qla2x00_free_device(base_vha);
qla2x00_clear_drv_active(ha);
@@ -7142,8 +7142,6 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
qla2x00_dfs_remove(base_vha);
qla84xx_put_chip(base_vha);
if (base_vha->timer_active)
qla2x00_stop_timer(base_vha);
@@ -7161,6 +7159,8 @@ qla2x00_disable_board_on_pci_error(struct work_struct *work)
scsi_remove_host(base_vha->host);
qla84xx_put_chip(base_vha);
base_vha->flags.init_done = 0;
qla25xx_delete_queues(base_vha);
qla2x00_free_fcports(base_vha);