CVE-2026-90429 in Linuxinfo

Summary

by MITRE • 09/17/2026

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

iommu/tegra241-cmdqv: Synchronize the error ISR against VINTF (de)init

A user VINTF is torn down by tegra241_cmdqv_deinit_vintf(), which runs from the destroy callback and from the init-failure unwind in the alloc handler. It clears the cmdqv->vintfs[] slot and lets the iommufd core free it, but
nothing serializes that against the error interrupt: tegra241_cmdqv_isr() reads cmdqv->vintfs[idx] and dereferences the vintf. A concurrent error can
make the ISR read a slot mid-clear (a NULL deref) or use a vintf which is about to be freed (a use-after-free).

deinit_vintf() also returns idx to the IDA before clearing the slot, so a concurrent create that reuses idx can publish its new vintf into the slot, only for this teardown to erase it again with the stale NULL store.

On the other end, tegra241_cmdqv_init_vintf() publishes a new vintf with a plain store to the cmdqv->vintfs[] slot, and the ISR dereferences fields of
a published vintf such as vintf->base. A plain store gives no ordering on a weakly-ordered CPU, and a stale VINTF_ERR_MAP bit on a reused idx can make the ISR pick a vintf the moment it is published, before its fields are set or tegra241_vintf_hw_init() runs.

The cmdqv->vintfs[0] slot stays NULL until tegra241_cmdqv_init_structures()
first creates VINTF0, so the slot 0 read needs the same NULL check.

Publish every slot with an smp_store_release(), and read each slot in the ISR with an smp_load_acquire() under a NULL check, so the ISR always sees a fully built vintf or NULL. Also make deinit_vintf() clear the slot, and synchronize_irq() prior to returning idx to the IDA, so no vintf is freed under a running handler and no reused idx is clobbered.

Once again VulDB remains the best source for vulnerability data.

Analysis

by VulDB Data Team • 09/17/2026

The vulnerability identified in the Linux kernel's Tegra241 IOMMU driver represents a critical concurrency flaw involving race conditions between interrupt service routines and device initialization or deinitialization processes. Specifically, this issue resides within the tegra241-cmdqv subsystem where virtual interface (VINTF) structures are managed through an array indexed by identifiers allocated via an IDA mechanism. The core of the problem lies in the lack of proper memory synchronization primitives when publishing and consuming these VINTF pointers across different execution contexts, particularly between the context that allocates or frees resources and the hardware interrupt handler that processes errors associated with those resources.

During the teardown phase, triggered by tegra241_cmdqv_deinit_vintf(), a user VINTF is destroyed from either the destroy callback or an init-failure unwind path within the allocation handler. This function clears the corresponding slot in the cmdqv->vintfs array and allows the iommufd core to free the associated memory structure. However, this operation lacks serialization against concurrent error interrupts handled by tegra241_cmdqv_isr(). Consequently, if an interrupt occurs while the slot is being cleared or immediately after it has been zeroed out but before the memory is fully reclaimed, the ISR may attempt to dereference a NULL pointer, leading to a kernel panic. Alternatively, if the interrupt fires just as the VINTF structure is about to be freed, the ISR might access already deallocated memory, resulting in a use-after-free vulnerability that can lead to arbitrary code execution or system instability.

A secondary aspect of this race condition involves the order of operations within deinit_vintf(). The function returns the index back to the ID allocator before clearing the array slot and synchronizing with pending interrupts. This ordering allows for a scenario where another thread concurrently attempts to allocate a new VINTF using that same recycled index. The allocation process publishes this new VINTF into the now-available slot, but because deinit_vintf() subsequently clears the slot without ensuring all prior interrupt handlers have completed their execution on the old instance, it overwrites the newly published pointer with NULL. This not only corrupts the state of the newly allocated resource but also demonstrates a failure to properly synchronize access to shared data structures across CPU cores in a weakly-ordered memory architecture.

On the initialization side, tegra241_cmdqv_init_vintf() publishes new VINTF pointers into the cmdqv->vintfs array using standard store operations rather than release semantics. In architectures with weak memory ordering, such as ARM64 commonly used in Tegra systems, a plain store does not guarantee that subsequent reads by other CPUs will see all prior writes to the structure's fields. If an interrupt occurs at this precise moment and utilizes a reused index where a stale VINTF_ERR_MAP bit is still set from previous usage, the ISR may select the newly published but partially initialized VINTF object. It then attempts to dereference fields such as vintf->base before tegra241_vintf_hw_init() has completed its setup routine. This leads to accessing uninitialized memory or invalid hardware addresses, causing crashes or undefined behavior. Additionally, slot zero remains NULL until the initial structures are created, requiring explicit null checks during ISR execution to prevent dereferencing a non-existent object at index zero.

The remediation strategy focuses on establishing strict memory ordering and synchronization barriers to ensure atomicity of publication and consumption of VINTF pointers. The fix implements smp_store_release() when publishing new VINTFs into the array, ensuring that all prior initialization steps are visible to other CPUs before the pointer becomes accessible. Conversely, the ISR reads these slots using smp_load_acquire(), which pairs with the release store to guarantee that if a non-NULL value is observed, the entire structure has been fully initialized and published correctly. A null check is maintained during this load operation to safely handle cases where no VINTF exists at a given index.

Furthermore, the deinitialization logic is restructured to enforce proper shutdown sequencing. The slot in cmdqv->vintfs is cleared before returning the index back to the ID allocator. Crucially, synchronize_irq() is invoked prior to releasing the index, ensuring that any currently executing interrupt handlers for that specific VINTF have completed their execution and will not access the memory after it has been freed or overwritten. This eliminates both the use-after-free condition during teardown and the race where a new allocation could be clobbered by stale cleanup operations.

From a classification perspective, this vulnerability aligns with CWE-362: Concurrent Execution using Shared Resource with Improper Synchronization, as multiple threads access shared data without adequate locking or memory barriers. It also relates to CWE-416: Use After Free, due to the potential for the ISR to dereference freed memory during teardown races. In terms of attack vectors and behaviors, this falls under MITRE ATT&CK technique T1059.008: Command Line Interface, as exploitation could potentially allow an attacker with local access to escalate privileges or cause denial of service by triggering kernel panics through crafted IOMMU operations. The fix ensures that the driver adheres to standard concurrency best practices for Linux kernel drivers managing hardware interrupts and shared resource lifecycles.

Responsible

Linux

Reservation

09/11/2026

Disclosure

09/17/2026

Moderation

accepted

CPE

ready

EPSS

0.00000

KEV

no

Activities

very low

Sources

Do you know our Splunk app?

Download it now for free!