Get a Demo

Let's Patch It!

Book a short call with one our specialists, we'll walk you through how Endor Patches work, and ask you a few questions about your environment (like your primary programming languages and repository management). We'll also send you an email right after you fill out the form, feel free to reply with any questions you have in advance!

CVE

CVE-2026-74568

KVM: arm64: vgic: Fix race between LPI release and re-registration
Back to all
CVE

CVE-2026-74568

KVM: arm64: vgic: Fix race between LPI release and re-registration

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,

vgicreleaselpi_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 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, vgicreleaselpi_locked() is called from two distinct

paths: direct release via vgicputirq(), and deferred release via

vgicreleasedeleted_lpis(). During direct release, the issue can result

in deleting a newly registered LPI from the xarray:

  CPU0 (Releasing LPI)                    CPU1 (Adding new LPI)

  ====================                    =====================

  vgicputirq()

      _vgicput_irq()

          refcountdecand_test()

                                          vgicaddlpi()

                                              xalockirqsave()

                                              oldirq = xaload(.., intid)

                                              vgictrygetirqref(old_irq) == false

                        new IRQ inserted -->  _xastore(.., intid, ..)

                                              xaunlockirqrestore()

  xalockirqsave();

  vgicreleaselpi_locked()

      _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()

      _vgicput_irq()

          refcountdecand_test()

      irq->pending_release = true

                                          vgicaddlpi()

                                              xalockirqsave()

                                              oldirq = xaload(.., intid)

                                              vgictrygetirqref(oldirq) == false

                 BUG: old IRQ overwritten --> _xastore(.., intid, ..)

                                              xaunlockirqrestore()

  vgicreleasedeleted_lpis()

      xalockirqsave()

      xaforeach() { .. } <-- 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 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 pending_release field is no

longer safe from use-after-free. Delete all uses of the flag, and update

vgicreleasedeleted_lpis() to identify orphaned LPIs purely based on

their refcount.

Package Versions Affected

Package Version
patch Availability
No items found.

Automatically patch vulnerabilities without upgrading

Fix Without Upgrading
Detect compatible fix
Apply safe remediation
Fix with a single pull request

CVSS Version

Severity
Base Score
CVSS Version
Score Vector
C
H
U
9.3
-
3.1
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
C
H
U
0
-
3.1
CVSS:3.1/AV:L/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
C
H
U
-

Related Resources

No items found.

References

https://git.kernel.org/stable/c/292e80a159aa88635bf668a7212cfdf526b8bd52, https://git.kernel.org/stable/c/cbfe2b24a1ea9de35032dbdd100fdc700f5be92d, https://github.com/CVEProject/cvelistV5/tree/main/cves/2026/74xxx/CVE-2026-74568.json, https://nvd.nist.gov/vuln/detail/CVE-2026-74568, https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git

Severity

9.3

CVSS Score
0
10

Basic Information

Base CVSS
9.3
EPSS Probability
0.00122%
EPSS Percentile
0.02215%
Introduced Version
3a08a6ca7c373198c84e2a8c025c395ee966ff8a,6.17.0,0
Fix Available
cbfe2b24a1ea9de35032dbdd100fdc700f5be92d,7.1.8

Fix Critical Vulnerabilities Instantly

Secure your app without upgrading.
Fix Without Upgrading