From: sashiko-bot@kernel.org
To: "Nilesh Javali" <njavali@marvell.com>
Cc: linux-scsi@vger.kernel.org
Subject: Re: [PATCH v2 11/13] scsi: qla2xxx: Re-acquire vport_slock and refresh tvp during vport DPC
Date: Fri, 23 Oct 2026 10:53:07 +0000 [thread overview]
Message-ID: <sashiko-outbox-182708@kernel.org> (raw)
In-Reply-To: <20261023101600.1431179-12-njavali@marvell.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Critical] scsi: qla2xxx: use-after-free on vp in qla2x00_do_dpc_all_vps() on timeout
- [Critical] scsi: qla2xxx: unrefreshed tvp in vp_list loops causes hard lockup and UAF
--
commit a9b1443e24db2e5c7bc6bc02893d52ce93b6f5cf
Author: Nilesh Javali <njavali@marvell.com>
scsi: qla2xxx: Re-acquire vport_slock and refresh tvp during vport DPC
This commit re-acquires vport_slock using a spin_trylock_irqsave() and
cond_resched() loop in qla2x00_do_dpc_all_vps(), refreshes the next list entry
tvp after re-locking in qla2x00_do_dpc_all_vps() and qla2x00_alert_all_vps(),
and adds a cond_resched() before qla2x00_loop_resync() in qla2x00_do_dpc_vp().
> diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
> index 754c806dac807..65dcfc1b04ef9 100644
> --- a/drivers/scsi/qla2xxx/qla_mid.c
> +++ b/drivers/scsi/qla2xxx/qla_mid.c
> @@ -315,6 +315,10 @@ qla2x00_alert_all_vps(struct rsp_que *rsp, uint16_t *mb)
> /* Reference held under vport_slock keeps vha valid. */
> atomic_dec(&vha->vref_count);
> wake_up(&vha->vref_waitq);
> + /* refresh tvp from the current list state */
> + if (list_empty(&vha->list))
> + break;
> + tvp = list_next_entry(vha, list);
> }
> i++;
> }
[ ... ]
> @@ -446,11 +451,28 @@ qla2x00_do_dpc_all_vps(scsi_qla_host_t *vha)
> spin_unlock_irqrestore(&ha->vport_slock, flags);
>
> qla2x00_do_dpc_vp(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)
> - atomic_dec(&vp->vref_count);
> + cond_resched();
> +
> + /* Re-acquire lock with yield to avoid hard lockup if holder is delayed */
> + while (!spin_trylock_irqsave(&ha->vport_slock, flags))
> + cond_resched();
> + /* Reference held under vport_slock keeps vp valid. */
> + atomic_dec(&vp->vref_count);
> + wake_up(&vp->vref_waitq);
> + /*
> + * While the lock was dropped, the next entry (tvp) may
> + * have been removed via list_del_init(), making its
> + * list.next point to itself. list_for_each_entry_safe
> + * would then loop infinitely since the self-referencing
> + * pointer never matches the list head.
> + *
> + * If vp itself was removed (deallocate timeout), we
> + * cannot continue iterating from it, break out.
> + * Otherwise refresh tvp from the current list state.
> + */
> + if (list_empty(&vp->list))
> + break;
[Severity: Critical]
Can accessing vp here (and vha in qla2x00_alert_all_vps() above) trigger a
use-after-free when qla24xx_deallocate_vp_id() times out?
Neither qla2x00_do_dpc_all_vps() nor qla2x00_alert_all_vps() takes a
Scsi_Host reference via scsi_host_get() before dropping ha->vport_slock.
If a concurrent vport deletion in qla24xx_vport_delete() calls
qla24xx_deallocate_vp_id() and the wait for vref_count to reach zero times
out, qla24xx_deallocate_vp_id() forcibly removes vha from ha->vp_list even
while vref_count is still non-zero:
drivers/scsi/qla2xxx/qla_mid.c:qla24xx_deallocate_vp_id() {
...
if (!bailout) {
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_init(&vha->list);
qla_update_vp_map(vha, RESET_VP_IDX);
spin_unlock_irqrestore(&ha->vport_slock, flags);
}
}
Immediately after qla24xx_deallocate_vp_id() returns, qla24xx_vport_delete()
frees vha's resources and drops the final host reference:
drivers/scsi/qla2xxx/qla_attr.c:qla24xx_vport_delete() {
...
qla24xx_deallocate_vp_id(vha);
...
scsi_host_put(vha->host);
}
Because list_empty(&vp->list) only becomes true while vref_count > 0 when that
deallocate timeout occurs, wouldn't vp (or vha in qla2x00_alert_all_vps())
already be freed or in the middle of being freed by the time this thread
re-acquires ha->vport_slock and accesses vp->vref_count, vp->vref_waitq, and
vp->list?
> + tvp = list_next_entry(vp, list);
[Severity: Critical]
What about the other list_for_each_entry_safe(vp, tvp, &ha->vp_list, list)
loops that drop and re-acquire ha->vport_slock without refreshing tvp?
Since qla24xx_deallocate_vp_id() uses list_del_init(&vha->list) when
vref_count == 0, any concurrent deletion of the prefetched next entry tvp
while ha->vport_slock is dropped sets tvp->list.next to point to itself and
frees tvp via qla24xx_vport_delete() -> scsi_host_put().
The following functions still iterate over ha->vp_list with
list_for_each_entry_safe(), drop ha->vport_slock inside the loop body, and do
not refresh tvp after re-acquiring the lock:
drivers/scsi/qla2xxx/qla_init.c:qla2x00_quiesce_io()
drivers/scsi/qla2xxx/qla_init.c:qla2x00_abort_isp_cleanup() (two loops)
drivers/scsi/qla2xxx/qla_init.c:qla2x00_abort_isp()
drivers/scsi/qla2xxx/qla_init.c:qla82xx_restart_isp()
drivers/scsi/qla2xxx/qla_os.c:qla_pci_error_cleanup() (two loops)
For example, in qla2x00_abort_isp():
drivers/scsi/qla2xxx/qla_init.c:qla2x00_abort_isp() {
...
spin_lock_irqsave(&ha->vport_slock, flags);
list_for_each_entry_safe(vp, tvp, &ha->vp_list, list) {
if (vp->vp_idx && !vp->flags.delete_progress) {
atomic_inc(&vp->vref_count);
spin_unlock_irqrestore(&ha->vport_slock, flags);
qla2x00_vp_abort_isp(vp);
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);
}
If tvp is deleted while ha->vport_slock is dropped in any of those loops,
won't the next iteration dereference the freed tvp and then spin forever with
interrupts disabled because tvp->list.next points to itself?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261023101600.1431179-1-njavali@marvell.com?part=11
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
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 [this message]
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-182708@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.