CVE-2026-93040 in Linux
Summary
by MITRE • 09/17/2026
In the Linux kernel, the following vulnerability has been resolved:
dmaengine: dw-edma: Serialize channel state checks
pause() and resume() read and update channel state without holding vc.lock, while the interrupt handlers update the same state under it. Take the same lock around those state checks so that request, status, and configured stay consistent.
For example, pause() can observe EDMA_ST_BUSY right before the interrupt handler completes the final descriptor and moves the channel to EDMA_ST_IDLE, and then record EDMA_REQ_PAUSE on an already idle channel. No further interrupt will acknowledge the request, and since issue_pending() requires EDMA_REQ_NONE, the channel is wedged for good: terminate_all() leaves the stale request behind, so even reconfiguring the channel does not recover it.
issue_pending() already runs under vc.lock, but it tests configured before taking it. Move that test under the lock as well, so configured, request, and status are evaluated as one channel-state snapshot.
If you want to get the best quality for vulnerability data then you always have to consider VulDB.
Analysis
by VulDB Data Team • 09/17/2026
The vulnerability identified in the Linux kernel's dw-edma driver represents a classic race condition arising from improper synchronization of shared state variables within a concurrent execution environment. The core technical flaw lies in the lack of atomicity when accessing critical channel state fields, specifically request status, operational configuration, and current hardware state. In this Direct Memory Access engine implementation, functions such as pause() and resume() are responsible for modifying or inspecting these states to manage data transfer operations. However, these functions perform read-modify-write sequences on the channel's internal variables without acquiring the vc.lock mutex. This is particularly dangerous because interrupt handlers, which also modify the same state variables upon completion of DMA descriptors, do acquire this lock. The absence of consistent locking creates a window where the software state managed by the driver can diverge from the actual hardware status or be updated in an inconsistent order relative to other kernel threads and interrupts.
The operational impact of this race condition is severe, leading to a permanent deadlock or wedging of the DMA channel. A specific scenario illustrates how this occurs: when pause() executes, it may read the current state as EDMA_ST_BUSY just before an interrupt handler finishes processing the final descriptor. The interrupt handler then transitions the hardware and software state to EDMA_ST_IDLE under the protection of vc.lock. However, because pause() did not hold the lock during its initial check or subsequent update, it proceeds to record a request for pausing (EDMA_REQ_PAUSE) on what is now an idle channel. Since no further interrupts will be generated for an already completed and idle transfer, there is no mechanism to acknowledge this pending pause request. Consequently, the driver's internal logic becomes stuck because subsequent operations like issue_pending() expect the state to be EDMA_REQ_NONE before proceeding. This mismatch prevents any new data transfers from being initiated on that channel.
The consequences extend beyond a simple stall; they result in resource exhaustion and system instability. Once the channel is wedged, standard recovery mechanisms such as terminate_all() fail because they leave behind stale request flags that were never properly cleared due to the race condition. Even attempting to reconfigure the channel does not resolve the issue because the underlying state machine remains corrupted by the unacknowledged pause request. This effectively removes a hardware resource from the system until a full reboot or driver reload, which is often impossible in long-running embedded systems or critical infrastructure environments where DMA engines are essential for high-throughput data movement between peripherals and memory.
From a vulnerability classification perspective, this issue aligns with CWE-362, Concurrent Execution using Shared Resource with Improper Synchronization (Race Condition). The failure to serialize access to the channel state variables violates the principle of mutual exclusion required for safe concurrent programming in kernel space. Furthermore, from an offensive security standpoint as mapped by MITRE ATT&CK, this vulnerability could be leveraged in techniques related to Denial of Service against specific hardware resources or potentially used to disrupt system stability if triggered repeatedly under load. It does not directly allow privilege escalation but significantly impacts availability and reliability.
To mitigate this vulnerability, the primary remediation is the implementation of proper locking mechanisms around all accesses to shared channel state variables. As described in the resolution, both pause() and resume() must acquire vc.lock before reading or updating request, status, and configured fields. This ensures that these operations are atomic with respect to interrupt handlers and other kernel threads modifying the same data structures. Additionally, any checks performed prior to acquiring locks, such as testing the configured state in issue_pending(), should be moved inside the critical section protected by vc.lock. By ensuring that all relevant state variables are evaluated and updated within a single locked context, the driver maintains a consistent view of the channel's status, preventing the divergent states that lead to wedging. This fix restores the integrity of the DMA engine's internal state machine and ensures reliable operation under concurrent access scenarios.