CVE-2026-45855

ata: libata-scsi: avoid Non-NCQ command starvation

published May 27, 2026

CVSS
—
EPSS
0%
Percentile
6.2
In the wild
Unconfirmed
What it is

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

ata: libata-scsi: avoid Non-NCQ command starvation

When a non-NCQ command is issued while NCQ commands are being executed,

ata_scsi_qc_issue() indicates to the SCSI layer that the command issuing

should be deferred by returning SCSI_MLQUEUE_XXX_BUSY. This command

deferring is correct and as mandated by the ACS specifications since

NCQ and non-NCQ commands cannot be mixed.

However, in the case of a host adapter using multiple submission queues,

when the target device is under a constant load of NCQ commands, there

are no guarantees that requeueing the non-NCQ command will be executed

later and it may be deferred again repeatedly as other submission queues

can constantly issue NCQ commands from different CPUs ahead of the

non-NCQ command. This can lead to very long delays for the execution of

non-NCQ commands, and even complete starvation for these commands in the

worst case scenario.

Since the block layer and the SCSI layer do not distinguish between

queueable (NCQ) and non queueable (non-NCQ) commands, libata-scsi SAT

implementation must ensure forward progress for non-NCQ commands in the

presence of NCQ command traffic. This is similar to what SAS HBAs with a

hardware/firmware based SAT implementation do.

Implement such forward progress guarantee by limiting requeueing of

non-NCQ commands from ata_scsi_qc_issue(): when a non-NCQ command is

received and NCQ commands are in-flight, do not force a requeue of the

non-NCQ command by returning SCSI_MLQUEUE_XXX_BUSY and instead return 0

to indicate that the command was accepted but hold on to the qc using

the new deferred_qc field of struct ata_port.

This deferred qc will be issued using the work item deferred_qc_work

running the function ata_scsi_deferred_qc_work() once all in-flight

commands complete, which is checked with the port qc_defer() callback

return value indicating that no further delay is necessary. This check

is done using the helper function ata_scsi_schedule_deferred_qc() which

is called from ata_scsi_qc_complete(). This thus excludes this mechanism

from all internal non-NCQ commands issued by ATA EH.

When a port deferred_qc is non NULL, that is, the port has a command

waiting for the device queue to drain, the issuing of all incoming

commands (both NCQ and non-NCQ) is deferred using the regular busy

mechanism. This simplifies the code and also avoids potential denial of

service problems if a user issues too many non-NCQ commands.

Finally, whenever ata EH is scheduled, regardless of the reason, a

deferred qc is always requeued so that it can be retried once EH

completes. This is done by calling the function

ata_scsi_requeue_deferred_qc() from ata_eh_set_pending(). This avoids

the need for any special processing for the deferred qc in case of NCQ

error, link or device reset, or device timeout.

The record
Technical detail
CVSS
Not scored
CVSS v4.0
Not supplied
EPSS
0.00172 · 6.2th percentile
Published
2026-05-27T12:15Z
EPSS history
Timeline
  • 27 MAY 12:15Z
    ata: libata-scsi: avoid Non-NCQ command starvation
    cvelistv5