CVE-2026-74568

Source
https://cve.org/CVERecord?id=CVE-2026-74568
Import Source
https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-74568.json
JSON Data
https://api.osv.dev/v1/vulns/CVE-2026-74568
Downstream
Published
2026-08-15T12:28:08.859Z
Modified
2026-08-17T03:47:36.022826928Z
Summary
KVM: arm64: vgic: Fix race between LPI release and re-registration
Details

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->lpixa). When the reference count of an LPI structure drops to zero, vgicreleaselpilocked() 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 vgicaddlpi() 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, vgicreleaselpilocked() is called from two distinct paths: direct release via vgicputirq(), and deferred release via vgicreleasedeletedlpis(). During direct release, the issue can result in deleting a newly registered LPI from the xarray:

CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgicputirq() __vgicputirq() refcountdecandtest() vgicaddlpi() xalockirqsave() oldirq = xaload(.., intid) vgictrygetirqref(oldirq) == false new IRQ inserted --> __xastore(.., intid, ..) xaunlockirqrestore() xalockirqsave(); vgicreleaselpilocked() _xaerase(.., irq->intid) <-- BUG: new IRQ is erased kfreercu(oldirq)

During the deferred release path, the old IRQ can be leaked:

CPU0 (Releasing LPI) CPU1 (Adding new LPI) ==================== ===================== vgicputirq_norelease() __vgicputirq() refcountdecandtest() irq->pendingrelease = true vgicaddlpi() xalockirqsave() oldirq = xaload(.., intid) vgictrygetirqref(oldirq) == false BUG: old IRQ overwritten --> _xastore(.., intid, ..) xaunlockirqrestore()

vgicreleasedeletedlpis() xalockirqsave() xaforeach() { .. } <-- old IRQ with pendingrelease = 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 vgicaddlpi() 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 vgicaddlpi(), 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 pendingrelease field is no longer safe from use-after-free. Delete all uses of the flag, and update vgicreleasedeletedlpis() to identify orphaned LPIs purely based on their refcount.

Database specific
{
    "osv_generated_from": "https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/74xxx/CVE-2026-74568.json",
    "cna_assigner": "Linux"
}
References

Affected packages

Git / git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Affected ranges

Type
GIT
Repo
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
Events
Introduced
3a08a6ca7c373198c84e2a8c025c395ee966ff8a
Fixed
292e80a159aa88635bf668a7212cfdf526b8bd52
Fixed
cbfe2b24a1ea9de35032dbdd100fdc700f5be92d

Database specific

source
"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-74568.json"

Linux / Kernel

Package

Name
Kernel

Affected ranges

Type
ECOSYSTEM
Events
Introduced
6.17.0
Fixed
7.1.8

Database specific

source
"https://storage.googleapis.com/cve-osv-conversion/osv-output/CVE-2026-74568.json"