From: sashiko-bot@kernel.org
To: "Nilesh Javali" <njavali@marvell.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v2 10/13] scsi: qla2xxx: Fix use-after-free races during vport deletion
Date: Fri, 23 Oct 2026 10:53:50 +0000 [thread overview]
Message-ID: <sashiko-outbox-182709@kernel.org> (raw)
In-Reply-To: <20261023101600.1431179-11-njavali@marvell.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] scsi: qla2xxx: infinite loop and UAF in vp_list loops with list_del_init()
- [High] scsi: qla2xxx: missing vport validation and tvp refresh in vp_list loops
--
commit 24f27bc8c1d9341721d99c592298135dfbc0b9d5
Author: Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Fix use-after-free races during vport deletion
This commit adds vport validation checks (vp_idx, delete_progress, and
VPORT_DELETE) to several ha->vp_list traversals and switches
qla24xx_deallocate_vp_id() from list_del() to list_del_init() to prevent
use-after-free crashes during vport deletion.
> diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
> index 7898521b76d4d..c02571a6f0c71 100644
> --- a/drivers/scsi/qla2xxx/qla_init.c
> +++ b/drivers/scsi/qla2xxx/qla_init.c
> @@ -7573,15 +7573,17 @@ qla2x00_abort_isp_cleanup(scsi_qla_host_t *vha)
>
> spin_lock_irqsave(&ha->vport_slock, flags);
> list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
> - atomic_inc(&vp->vref_count);
> - spin_unlock_irqrestore(&ha->vport_slock, flags);
> + if (vp->vp_idx && !vp->flags.delete_progress) {
> + atomic_inc(&vp->vref_count);
> + spin_unlock_irqrestore(&ha->vport_slock, flags);
>
> - qla2x00_mark_all_devices_lost(vp);
> + qla2x00_mark_all_devices_lost(vp);
>
> - spin_lock_irqsave(&ha->vport_slock, flags);
> - /* Check if vp is still valid before accessing it */
> - if (vp->vp_idx && !vp->flags.delete_progress)
> + spin_lock_irqsave(&ha->vport_slock, flags);
> + /* Reference held under vport_slock keeps vp valid. */
> atomic_dec(&vp->vref_count);
> + wake_up(&vp->vref_waitq);
> + }
> }
> spin_unlock_irqrestore(&ha->vport_slock, flags);
[Severity: High]
The commit message notes that it validates vp_idx and delete_progress across
all remaining vp_list traversals, but what about qla2x00_quiesce_io() and
qla82xx_restart_isp() in drivers/scsi/qla2xxx/qla_init.c?
In qla2x00_quiesce_io(), ha->vp_list is traversed and ha->vport_slock is
dropped without checking vp->vp_idx or !vp->flags.delete_progress, and
without waking vp->vref_waitq:
drivers/scsi/qla2xxx/qla_init.c:qla2x00_quiesce_io() {
...
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_mark_all_devices_lost(vp);
spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
...
}
Similarly, qla82xx_restart_isp() checks vp->vp_idx (which is not cleared by
qla24xx_deallocate_vp_id()), but does not check !vp->flags.delete_progress or
call wake_up(&vp->vref_waitq):
drivers/scsi/qla2xxx/qla_init.c:qla82xx_restart_isp() {
...
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_vp_abort_isp(vp);
spin_lock_irqsave(&ha->vport_slock, flags);
atomic_dec(&vp->vref_count);
}
}
spin_unlock_irqrestore(&ha->vport_slock, flags);
...
}
Since NPIV is supported on QLA8031, QLA82XX, and QLA8044 adapters, if
qla24xx_vport_delete() runs concurrently with qla2x00_quiesce_io() or
qla82xx_restart_isp() and deletes the prefetched next entry tvp while
ha->vport_slock is dropped, won't the next iteration advance vp to the
removed and freed tvp, enter the loop body because !vp->flags.delete_progress
is not checked, and access freed vp and vp->vp_fcports memory in
qla2x00_mark_all_devices_lost(vp) or qla2x00_vp_abort_isp(vp)?
> diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
> index 90f09d36705a6..754c806dac807 100644
> --- a/drivers/scsi/qla2xxx/qla_mid.c
> +++ b/drivers/scsi/qla2xxx/qla_mid.c
> @@ -79,7 +79,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
> for (i = 0; i < 500; i++) {
> spin_lock_irqsave(&ha->vport_slock, flags);
> if (atomic_read(&vha->vref_count) == 0) {
> - list_del(&vha->list);
> + list_del_init(&vha->list);
> qla_update_vp_map(vha, RESET_VP_IDX);
> bailout = 1;
> }
> @@ -94,7 +94,7 @@ qla24xx_deallocate_vp_id(scsi_qla_host_t *vha)
> ql_log(ql_log_info, vha, 0xfffa,
> "vha->vref_count=%u timeout\n", vha->vref_count.counter);
> spin_lock_irqsave(&ha->vport_slock, flags);
> - list_del(&vha->list);
> + list_del_init(&vha->list);
> qla_update_vp_map(vha, RESET_VP_IDX);
> spin_unlock_irqrestore(&ha->vport_slock, flags);
> }
[Severity: Critical]
Can changing list_del(&vha->list) to list_del_init(&vha->list) in
qla24xx_deallocate_vp_id() still trigger a use-after-free and also cause an
infinite loop with interrupts disabled in the list_for_each_entry_safe()
traversals?
When ha->vp_list is traversed using list_for_each_entry_safe(vp, tvp,
&ha->vp_list, list) in qla2x00_abort_isp_cleanup(), qla2x00_abort_isp(),
qla_pci_error_cleanup(), qla2x00_do_dpc_all_vps(), qla2x00_alert_all_vps(),
qla2x00_quiesce_io(), and qla82xx_restart_isp(), the macro prefetches the
next entry tvp = list_next_entry(vp, list) before running the loop body. The
loop body only increments vp->vref_count (leaving tvp->vref_count at 0) and
then drops ha->vport_slock.
While ha->vport_slock is dropped during vp processing, a concurrent
qla24xx_vport_delete() -> qla24xx_deallocate_vp_id(tvp) can acquire
ha->vport_slock, observe atomic_read(&tvp->vref_count) == 0, unlink tvp with
list_del_init(&tvp->list), and release ha->vport_slock, after which
qla24xx_vport_delete() frees tvp via scsi_host_put(tvp->host).
When the traversal thread finishes processing vp, re-acquires ha->vport_slock
with spin_lock_irqsave(), and advances the loop (vp = tvp, tvp =
list_next_entry(tvp, list)):
1. It dereferences tvp after it has been unlinked and potentially freed by
scsi_host_put(tvp->host), causing a use-after-free on tvp->list.next and
subsequently on vp->vp_idx, vp->flags.delete_progress, or vp->dpc_flags.
2. Because list_del_init(&tvp->list) sets tvp->list.next = &tvp->list,
list_next_entry(tvp, list) evaluates to tvp itself. Since &tvp->list !=
&ha->vp_list, the loop termination condition is never met, and subsequent
iterations skip the body (because delete_progress or VPORT_DELETE is set)
without dropping ha->vport_slock, spinning forever on the self-linked entry
with local interrupts disabled.
A follow-up commit in the series, commit a9b1443e24db ("scsi: qla2xxx:
Re-acquire vport_slock and refresh tvp during vport DPC"), refreshes tvp =
list_next_entry(vp, list) after re-acquiring ha->vport_slock in
qla2x00_do_dpc_all_vps() and qla2x00_alert_all_vps(), but leaves the
list_for_each_entry_safe() loops in qla2x00_abort_isp_cleanup(),
qla2x00_abort_isp(), qla_pci_error_cleanup(), qla2x00_quiesce_io(), and
qla82xx_restart_isp() without tvp refreshes. Should tvp be refreshed after
re-acquiring ha->vport_slock in all of those loops as well?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023101600.1431179-1-njavali@marvell.com?part=10
next prev parent reply other threads:[~2026-10-23 10:53 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-23 10:15 [PATCH v2 00/13] scsi: qla2xxx: Misc. Bug fixes Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 01/13] scsi: qla2xxx: Update MAINTAINERS with new FC storage alias Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 02/13] scsi: qla2xxx: Update few AENs for 29xx handling Nilesh Javali
2026-10-23 10:36 ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 03/13] Revert "scsi: qla2xxx: Validate BSG request_len before reading vendor_cmd[]" Nilesh Javali
2026-10-23 10:33 ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 04/13] scsi: qla2xxx: Wait for session deletion before full-login LIP Nilesh Javali
2026-10-23 10:35 ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 05/13] scsi: qla2xxx: Fix double addition of fcport to gnl.fcport list Nilesh Javali
2026-10-23 10:38 ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 06/13] scsi: qla2xxx: Fix scan state machine race and IRQ-unsafe sp_unmap Nilesh Javali
2026-10-23 10:34 ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 07/13] scsi: qla2xxx: Skip vport DPC processing during vport deletion Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 08/13] scsi: qla2xxx: Add validation check for base vport index during delete Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 09/13] scsi: qla2xxx: Validate vport before deletion Nilesh Javali
2026-10-23 10:15 ` [PATCH v2 10/13] scsi: qla2xxx: Fix use-after-free races during vport deletion Nilesh Javali
2026-10-23 10:53 ` sashiko-bot [this message]
2026-10-23 10:15 ` [PATCH v2 11/13] scsi: qla2xxx: Re-acquire vport_slock and refresh tvp during vport DPC Nilesh Javali
2026-10-23 10:53 ` sashiko-bot
2026-10-23 10:15 ` [PATCH v2 12/13] scsi: qla2xxx: Fix purex IOCB copy size on non-29xx adapters Nilesh Javali
2026-10-23 10:43 ` sashiko-bot
2026-10-23 10:16 ` [PATCH v2 13/13] scsi: qla2xxx: Update version to 12.00.00.2610b1 Nilesh Javali
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-182709@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=linux-scsi@vger.kernel.org \
--cc=njavali@marvell.com \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.