CVE-2026-99207: scsi: target: Disable interrupts while holding delayed_cmd_lock

Published Oct 28, 2026
·
Updated

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

scsi: target: Disable interrupts while holding delayedcmdlock

targetdodelayedwork() takes dev->delayedcmdlock with a plain spinlock(). It runs from systempercpuwq, so interrupts stay enabled while the lock is held. Every other acquisition of that lock uses spinlockirqsave(): targethandletaskattr() and transportcompleteorderedsync() in targetcoretransport.c, and targetnonorderedrelease() in targetcoredevice.c.

That was safe while every caller of transportcompletetaskattr() ran in process context: targetcompleteokwork() from targetcompletionwq, transportcompleteqf() from dev->qfworkqueue, and transportgenericrequestfailure() from the submit and execute paths.

Since commit 06933066d88a ("scsi: target: Add support for completing commands from backend context") that is no longer true. With completetype=1 on a fabric that sets directcomplsupp, targetcomplete() runs targetcompleteokwork() inline in the backend's completion context, which targetcompletecmdwithsense() documents as "May be called from interrupt context". For iblock that is the bio endio.

targetcompleteokwork() starts with transportcompletetaskattr(), which takes delayedcmdlock in two ways:

- Every ORDERED command is put on dev->delayedcmdlist by targethandletaskattr() and dispatched from there by targetdodelayedwork(), which marks it SCFTASKORDEREDSYNC. Its completion therefore goes through transportcompleteorderedsync().

- A SIMPLE command that completes while an ORDERED command is pending drops the last reference to the killed dev->nonordered, and percpurefput() then runs targetnonorderedrelease() in the completing context.

Both take the lock and, if commands are waiting, call schedulework(&dev->delayedcmdwork), which queues on systempercpuwq, i.e. on the CPU that took the completion. Further completions for the same queue are typically delivered there too, so one arriving while the work holds the lock spins on it forever.

Reaching this needs completetype=1, which is not the default (vhost-scsi, the only fabric with directcomplsupp, defaults to TARGETQUEUECOMPL), a backend whose I/O completes from interrupt context, and ORDERED commands from the initiator. Linux virtioscsi guests send only VIRTIOSCSISSIMPLE and never take the ordered path; any guest that uses the ORDERED task attribute, which vhost-scsi accepts, does.

targetdodelayedwork() is a work item and always runs in process context, so spinlockirq() is sufficient.

Found by inspection; no runtime report. A single ORDERED command goes through both acquisitions, so with CONFIGPROVELOCKING the first one completed through direct completion should produce an inconsistent lock state report on delayedcmdlock (hardirq or softirq, depending on where the backend completes).

Remediation

Recommended actions to resolve this vulnerability, in priority order.

  1. Configuration

    Disable interrupts while holding delayed_cmd_lock by changing target_do_delayed_work() to acquire it with spin_lock_irqsave() instead of plain spin_lock().

    Linux kernel SCSI target delayed_cmd_lock acquisition in target_do_delayed_work() = spin_lock_irqsave()

Event History

Oct 28, 2026
CVE Published
via MITRE·10:36 AM
Data Sourced
via MITRE·10:36 AM
Description
Data Sourced
via NVD·11:17 AM
Description

Contact

SecAlerts Pty Ltd.
132 Wickham Terrace
Fortitude Valley,
QLD 4006, Australia
info@secalerts.co
By using SecAlerts services, you agree to our services end-user license agreement. This website is safeguarded by reCAPTCHA and governed by the Google Privacy Policy and Terms of Service. All names, logos, and brands of products are owned by their respective owners, and any usage of these names, logos, and brands for identification purposes only does not imply endorsement. If you possess any content that requires removal, please get in touch with us.
© 2026 SecAlerts Pty Ltd.
ABN: 70 645 966 203, ACN: 645 966 203