Sceawere
Vulnerability Detail
CVE-2026-74568UPDATED Verified Sceawere Triage Sources: NVD / CISA KEV
KVM arm64 vgic LPI Race Condition
Vulnerability Metadata
- Severity
- Critical
- Score / CVSS
- 9.3
- Creation Date
- 1d ago
- Vendor
- Linux
- Product
- Linux
- Attack Type
- N/A
- Vector String
- CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
- Attack Complexity
- LOW
Narrative and Response
Description
In the Linux kernel, the following vulnerability has been resolved: KVM: arm64: vgic: Fix race between LPI release and re-registration Fix a potential race between decrementing an LPI's reference count and evicting that structure from the LPI xarray. LPI structures are maintained in the VGIC LPI xarray (dist->lpi_xa). When the reference count of an LPI structure drops to zero, vgic_release_lpi_locked() removes the structure from the xarray and frees it under the xarray lock. However, the release of an LPI can race with a concurrent LPI re-registration with the same INTID via vgic_add_lpi() on another CPU, since the reference count drop and the xarray eviction are not performed in a single atomic step. This can happen e.g. if the guest issues a DISCARD while the LPI is still referenced from a vCPU's active-pending list (ap_list), and the same INTID is re-mapped via MAPTI. Particularly, vgic_release_lpi_locked() is called from two distinct paths: direct release via vgic_put_irq(), and deferred release via vgic_release_deleted_lpis(). During direct release, the issue can result in deleting a newly registered LPI from the xarray: CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgic_put_irq() __vgic_put_irq() refcount_dec_and_test() vgic_add_lpi() xa_lock_irqsave() old_irq = xa_load(.., intid) vgic_try_get_irq_ref(old_irq) == false new IRQ inserted --> __xa_store(.., intid, ..) xa_unlock_irqrestore() xa_lock_irqsave(); vgic_release_lpi_locked() __xa_erase(.., irq->intid) <-- BUG: new IRQ is erased kfree_rcu(old_irq) During the deferred release path, the old IRQ can be leaked: CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgic_put_irq_norelease() __vgic_put_irq() refcount_dec_and_test() irq->pending_release = true vgic_add_lpi() xa_lock_irqsave() old_irq = xa_load(.., intid) vgic_try_get_irq_ref(oldirq) == false BUG: old IRQ overwritten --> __xa_store(.., intid, ..) xa_unlock_irqrestore() vgic_release_deleted_lpis() xa_lock_irqsave() xa_for_each() { .. } <-- old IRQ with pending_release = true is gone, so it cannot be released To fix the direct release path, move the reference count drop inside the xarray lock, making sure that vgic_add_lpi() never encounters the to-be-released LPI. In the deferred release path, the refcount drop must happen under a raw spinlock, so the xarray lock cannot be grabbed, and the same solution does not work. Instead, update vgic_add_lpi(), so that if it evicts an LPI from the xarray, it takes on the responsibility of freeing it. Consequently, an LPI may now be freed concurrently after a deferred release drops the refcount, so accessing the pending_release field is no longer safe from use-after-free. Delete all uses of the flag, and update vgic_release_deleted_lpis() to identify orphaned LPIs purely based on their refcount.
Executive Summary
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Technical Details
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Mitigations
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
References
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
Additional Metadata
{
"score": "9.3",
"pubDate": "2026-08-15T13:18:02.370Z",
"pubdate": "2026-08-15T13:18:02.370Z",
"executiveSummary": "A race condition vulnerability exists in the Linux kernel's KVM subsystem for the arm64 architecture, specifically within the Virtual Generic Interrupt Controller (VGIC) handling of Locality-specific Peripheral Interrupts (LPIs). The flaw occurs due to a lack of atomicity between decrementing an LPI structure's reference count and evicting or updating that structure within the LPI xarray (dist->lpi_xa).\nThis vulnerability can lead to memory corruption issues such as use-after-free conditions, premature deletion of newly registered LPIs, or memory leaks. An attacker or a guest operating system capable of issuing specific interrupt management commands, such as a DISCARD followed by a MAPTI for the same INTID, can trigger this race condition across multiple CPUs.\nThe affected component is the KVM arm64 VGIC LPI management code in the Linux kernel. Successful exploitation can compromise the stability and integrity of the host kernel, potentially resulting in a denial of service or unexpected hypervisor behavior.\nExploitation requires the ability to execute guest code that can manipulate LPI states concurrently with release operations managed by the host. Remediation requires applying the official kernel patch that ensures proper locking and atomic handling during LPI registration, release, and xarray eviction.",
"technicalDetails": "The vulnerability arises from a race condition between decrementing an LPI's reference count and evicting that structure from the LPI xarray (dist->lpi_xa) in the Linux kernel's KVM arm64 vgic implementation. LPI structures are tracked via an xarray. When an LPI structure's reference count drops to zero, vgic_release_lpi_locked() is responsible for removing the structure from the xarray and freeing it under the xarray lock.\nHowever, the reference count drop and the xarray eviction are not performed in a single atomic step. This allows a race condition to occur when an LPI release races with a concurrent LPI re-registration via vgic_add_lpi() on another CPU for the same INTID. This scenario can be triggered if a guest issues a DISCARD command while the LPI is still referenced from a vCPU's active-pending list (ap_list), followed by re-mapping the same INTID via MAPTI.\nTwo distinct paths lead to vgic_release_lpi_locked(): direct release via vgic_put_irq() and deferred release via vgic_release_deleted_lpis(). In the direct release path, CPU0 drops the reference count via refcount_dec_and_test() outside the lock. Meanwhile, CPU1 executes vgic_add_lpi(), fails to get the old IRQ reference, and inserts a new IRQ into the xarray via __xa_store(). Subsequently, CPU0 acquires the xarray lock and executes vgic_release_lpi_locked(), which erroneously calls __xa_erase() on the newly inserted IRQ and frees the old IRQ via kfree_rcu(), deleting the newly registered LPI.\nIn the deferred release path using vgic_put_irq_norelease(), the reference count drop sets irq->pending_release = true. CPU1's vgic_add_lpi() then overwrites the old IRQ in the xarray. When vgic_release_deleted_lpis() later executes, the old IRQ is already gone from the xarray, resulting in a memory leak as it cannot be released, and subsequent attempts to access pending_release lead to use-after-free conditions.\nTo address the direct release path, the reference count drop must be moved inside the xarray lock so vgic_add_lpi() never encounters a to-be-released LPI. For the deferred release path, since the refcount drop must occur under a raw spinlock where the xarray lock cannot be grabbed, vgic_add_lpi() is updated to take on the responsibility of freeing an LPI if it evicts it from the xarray. Additionally, the pending_release flag is eliminated, and vgic_release_deleted_lpis() is updated to identify orphaned LPIs purely based on their refcount."
}