[PATCH] scsi: qla4xxx: Fix NULL pointer dereference in qla4xxx_abort_active_cmds()
From: Yang Zi
Date: Tue Aug 25 2026 - 05:12:14 EST
qla4xxx_probe_adapter()'s failure path first calls scsi_remove_host(),
which drops the SCSI host's tag set reference and frees tag_set.tags via
scsi_mq_free_tags() -> blk_mq_free_tag_set(). It then falls through to
qla4xxx_free_adapter(), which calls qla4xxx_abort_active_cmds(). That
function walks ha->host->can_queue entries and, for each one, calls
qla4xxx_del_from_active_array() -> scsi_host_find_tag(), which
dereferences shost->tag_set.tags -- now NULL -- resulting in a NULL
pointer dereference.
KASAN report:
BUG: KASAN: null-ptr-deref in scsi_host_find_tag include/scsi/scsi_tcq.h:33 [inline] [qla4xxx]
BUG: KASAN: null-ptr-deref in qla4xxx_del_from_active_array drivers/scsi/qla4xxx/ql4_os.c:9095 [inline] [qla4xxx]
BUG: KASAN: null-ptr-deref in qla4xxx_abort_active_cmds+0x10b/0x610 drivers/scsi/qla4xxx/ql4_os.c:4816 [qla4xxx]
Guard qla4xxx_abort_active_cmds() so that it returns early when the SCSI
host has not been set up yet or its tag set has already been released:
in both cases there are no outstanding commands left to abort, and
scsi_host_find_tag() must not dereference a NULL tag_set.tags pointer.
This covers both the failed-probe cleanup path and the normal
qla4xxx_remove_adapter() path.
This patch addresses two reports with the same root cause (tracking IDs
115 and 139).
Signed-off-by: Yang Zi <2959243019@xxxxxx>
---
drivers/scsi/qla4xxx/ql4_os.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index d598ab4126f8..2277f48fede8 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -4811,6 +4811,15 @@ static void qla4xxx_abort_active_cmds(struct scsi_qla_host *ha, int res)
int i;
unsigned long flags;
+ /*
+ * The SCSI host may not be fully set up yet, or its tag set may
+ * already have been released by scsi_remove_host(). In either case
+ * there are no outstanding commands to abort, and scsi_host_find_tag()
+ * would dereference a NULL tag_set.tags pointer.
+ */
+ if (!ha->host || !ha->host->tag_set.tags)
+ return;
+
spin_lock_irqsave(&ha->hardware_lock, flags);
for (i = 0; i < ha->host->can_queue; i++) {
srb = qla4xxx_del_from_active_array(ha, i);