CVE-2026-89856
HighCVSS 8.4Summary
In the Linux kernel scsi: qla2xxx driver, the queue count derived from the MSI-X vector count (msix_count - 1) is stored in a u8 field, causing truncation. With 257 MSI-X vectors the result 256 truncates to 0, and in target mode a further decrement underflows 0 to 255. When the count is 0, the allocation returns ZERO_SIZE_PTR, which is not NULL, so the check passes and the pointer is dereferenced, corrupting memory or crashing the kernel.
Risk Assessment
The vulnerability can lead to kernel memory corruption or a kernel crash (panic), causing a denial of service. The risk is especially relevant with hot-plugged devices or configurations that can advertise a large number of MSI-X vectors.
Recommendation
Update the Linux kernel to a version containing the fix that introduces qla_calc_queue_count() to clamp the derived value into [1, QLA_MAX_QUEUES - 1]. If updating is not possible, restrict the ability to hot-plug untrusted qla2xxx devices.
Other vulnerabilities in Linux kernel (qla2xxx)
See all- CVE-2026-89855Unknown
In the Linux kernel scsi: qla2xxx driver, the sysfs reset operation "update cache versions without reset" (0x20261) calls get_flash_version(), which reads hardware flash registers, without holding ha->optrom_mutex. The VPD update path serializes the same call under optrom_mutex, so the reset path can interleave its flash register accesses with a concurrent VPD or optrom flash operation and corrupt the reads.
- CVE-2026-89854High
In the Linux kernel scsi: qla2xxx driver, qla84xx_put_chip() drops the last reference to ha->cs84xx and frees it via __qla84xx_chip_release() without clearing ha->cs84xx. During teardown it ran before scsi_remove_host(), which removes the 84xx_fw_version host sysfs attribute. A concurrent read of that attribute in the window between the two calls executes qla24xx_84xx_fw_version_show(), which dereferences the freed ha->cs84xx, resulting in a use-after-free.
- CVE-2026-89853Unknown
In the Linux kernel scsi: qla2xxx driver, qla2x00_free_fce_trace() freed and cleared ha->fce while holding only fce_mutex. The firmware-dump consumers qla27xx_fwdt_entry_t264() and qla25xx_copy_fce() read ha->fce (NULL check followed by a copy of the buffer) under hardware_lock and never take fce_mutex. A debugfs FCE disable could therefore free the DMA buffer between a dump's NULL check and its copy, resulting in a use-after-free.
- CVE-2026-89852Unknown
In the Linux kernel scsi: qla2xxx driver, the mbx_cmd_t struct is allocated on the stack but left uninitialized. qla2x00_mailbox_command() has several early-return paths (PCI permanent failure, device failed, EEH busy, ISP abort pending, mailbox access timeout, purge mbox) that return without writing the input mailbox registers back into mcp->mb[]. qla2x00_get_firmware_state() then unconditionally copies mcp->mb[1..6] (and mb[12]) into the caller's states[] array regardless of the return value.
- CVE-2026-89851Unknown
In the Linux kernel scsi: qla2xxx driver, qla2x00_dfs_fce_write() called kstrtoul() with a NULL result pointer, so a successful parse would dereference NULL and oops. Worse, the int return value (0 on success, negative errno on failure) was assigned to the unsigned long enable flag, inverting the intended logic: a valid number was treated as "disable" while a parse failure enabled FCE.
Original NVD description (English source)
In the Linux kernel, the following vulnerability has been resolved: scsi: qla2xxx: Clamp MSI-X derived queue counts to avoid truncation ha->msix_count is u16, but ha->max_req_queues, ha->max_rsp_queues and ha->max_qpairs are u8. Deriving the queue count as "ha->max_req_queues = ha->msix_count - 1" therefore truncates: a board (or a misconfigured/malicious hot-plugged device) advertising 257 MSI-X vectors yields msix_count - 1 == 256, which truncates to 0. An MSI-X count of 1 zeroes it as well, and in target mode the subsequent "ha->max_req_queues--" then underflows 0 to 255. When the count is 0, qla2x00_alloc_queues() calls kzalloc_objs(struct req_que *, 0), which returns ZERO_SIZE_PTR. That is not NULL, so the allocation check passes and the following "ha->req_q_map[0] = req" dereferences ZERO_SIZE_PTR, corrupting memory or crashing the kernel. Add qla_calc_queue_count() to clamp the derived value into [1, QLA_MAX_QUEUES - 1] so it always fits in u8 and is never zero, and use it at all three derivation sites (qla25xx_iospace_config(), qla83xx_iospace_config() and qla24xx_enable_msix()). Also guard the target-mode decrement so it cannot reintroduce a zero (which would in turn underflow max_qpairs).

