Linux SCSI subsystem development
 help / color / mirror / Atom feed
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

  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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox