CVE-2026-89857 in Linuxinfo

Summary

by MITRE • 09/16/2026

In the Linux kernel, the following vulnerability has been resolved:

scsi: qla2xxx: Hold qpair lock when sending NVMe LS reject

qla_nvme_ls_reject_iocb() allocates from and advances the request ring through __qla2x00_alloc_iocbs() (which assumes the hardware_lock is held) and qla2x00_start_iocbs() (which advances the ring and rings the request-in doorbell), but takes no lock itself. Two of its callers invoke it without the producer lock held:

- qla_nvme_xmt_ls_rsp(), the NVMe-FC .xmt_ls_rsp transport callback, on its error path, and

- qla2xxx_process_purls_pkt(), run from the purex work/DPC context.

Both use ha->base_qpair, whose qp_lock_ptr is hardware_lock, so they can run concurrently with normal I/O submission on the base ring and corrupt the ring producer state, leading to duplicated or dropped commands. The third caller, qla2xxx_process_purls_iocb(), runs inside qla24xx_process_response_queue() with the qpair lock already held and is safe; that is also why the lock cannot be taken inside the helper itself (it would recursively re-acquire hardware_lock on the response path).

Take qp_lock_ptr around the two unlocked callers and document the helper as caller-locked. Both run in process context, so spin_lock_irqsave() is used and nothing in the locked region sleeps.

If you want to get best quality of vulnerability data, you may have to visit VulDB.

Analysis

by VulDB Data Team • 09/16/2026

The Linux kernel driver for QLogic Fibre Channel adapters, specifically qla2xxx, contained a concurrency vulnerability within its NVMe over Fabrics implementation that could lead to data corruption or command loss. The core issue resided in the function qla_nvme_ls_reject_iocb(), which is responsible for sending an NVMe Link Service reject message. This internal helper function performs critical operations on the hardware request ring, including allocating IOCBs and advancing the producer index through __qla2x00_alloc_iocbs() and qla2x00_start_iocbs(). These underlying functions operate under the strict assumption that the hardware_lock is held to ensure atomicity of ring modifications. However, qla_nvme_ls_reject_iocb() itself did not acquire this lock, relying instead on its callers to provide it. This design created a race condition when callers failed to uphold their responsibility for synchronization.

Two specific code paths invoked qla_nvme_ls_reject_iocb() without holding the necessary producer lock. The first path is found in qla_nvme_xmt_ls_rsp(), which serves as the NVMe-FC transport callback for transmitting link service responses, particularly on error handling paths. The second vulnerable path is located within qla2xxx_process_purls_pkt(), a function executed from the purex work or deferred procedure call context. Both of these execution contexts utilize ha->base_qpair, where the queue pair lock pointer resolves to hardware_lock. Because neither caller acquired this lock before invoking the helper, concurrent access could occur between normal I/O submission threads and these error handling paths. This lack of mutual exclusion allowed multiple threads to modify the ring producer state simultaneously, violating the atomicity requirements of the hardware interface.

The operational impact of this race condition is severe for system stability and data integrity. When the request ring producer index is corrupted due to unsynchronized updates, it can result in duplicated commands being sent to the storage device or valid commands being dropped entirely. Duplicated commands may cause redundant processing at the target end, potentially leading to inconsistent state if not handled idempotently by the storage array. More critically, dropped commands represent a loss of I/O operations that must be recovered through higher-level timeout mechanisms, resulting in increased latency and potential application errors. In worst-case scenarios, severe corruption of ring indices could lead to driver crashes or kernel panics due to out-of-bounds memory access when interpreting queue entries.

The vulnerability is classified under CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition). From a tactical perspective, this aligns with ATT&CK techniques related to resource manipulation and potential denial of service through system instability. The root cause was not an inherent flaw in the helper function logic but rather a failure in caller-side synchronization protocols. It is important to note that one other caller, qla2xxx_process_purls_iocb(), operates safely because it runs inside qla24xx_process_response_queue() where the qpair lock is already held. This existing safe path prevented developers from simply adding the lock acquisition directly into qla_nvme_ls_reject_iocb(), as doing so would result in a recursive deadlock when attempting to re-acquire hardware_lock on the response processing path.

To mitigate this vulnerability, the fix involves explicitly acquiring the queue pair lock around the invocations of qla_nvme_ls_reject_iocb() within the two vulnerable callers: qla_nvme_xmt_ls_rsp and qla2xxx_process_purls_pkt. Since these functions run in process context rather than interrupt context, spin_lock_irqsave is utilized to disable local interrupts while holding the lock, ensuring complete protection against concurrent access from other processors or interrupt handlers that might also interact with the base queue pair. The helper function itself remains unchanged but is documented as caller-locked to enforce correct usage patterns for future maintenance. This approach resolves the race condition without introducing new deadlock risks associated with nested locking on the same mutex resource, thereby restoring reliable operation of NVMe over Fabrics connections using QLogic hardware.

Responsible

Linux

Reservation

09/11/2026

Disclosure

09/16/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Do you need the next level of professionalism?

Upgrade your account now!