KernelScan.io

CRITICAL Introduced in 6.17

kvm LPI Race

CVE-2026-74568

CVSS 9.3 / 10.0 NVD

CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H

KernelScan AI7.7HIGH

01

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.

02

Engine v0.6.0

Risk summary

A malicious guest VM on an arm64 KVM host can exploit a race condition in the virtual GIC's LPI management to corrupt host kernel memory, potentially escaping the VM sandbox and gaining code execution on the host. Multi-tenant cloud and virtualization environments where untrusted guests run on shared arm64 KVM hosts are most at risk. The bug requires precise timing to trigger but can lead to full host compromise affecting all co-located tenants.

Affectedarch/arm64/kvm/vgic/vgic.c, arch/arm64/kvm/vgic/vgic-its.c (KVM arm64 VGIC)

Vulnerability analysis

A race condition exists in KVM's arm64 virtual GIC interrupt controller where decrementing an LPI structure's reference count and removing it from the xarray are not performed as a single atomic operation. A malicious guest can trigger this by issuing a DISCARD command while the LPI is still on a vCPU's active-pending list and simultaneously re-mapping the same interrupt ID via MAPTI on another CPU. In the direct release path, this causes a newly registered LPI to be erroneously erased from the xarray and its predecessor freed; in the deferred release path, the old structure is overwritten and leaked, and a flag on the freed structure is subsequently accessed in a use-after-free. The fix makes the reference count drop and xarray eviction atomic in the direct path by holding the xarray lock across both operations. For the deferred path, the re-registration function now assumes responsibility for freeing any dead LPI it evicts, the unsafe flag is removed entirely, and orphaned LPIs are identified solely by a zero refcount. This vulnerability is reachable by any guest VM running on an arm64 KVM host with VGICv3 ITS support; no host-side privileges beyond the ability to run a guest are required.

03

BranchIntroducedFixed inPatch commit
7.16.177.1.8292e80a159aa
mainline6.177.2-rc6cbfe2b24a1ea