The bug sits squarely in vgic_its_invalidate_cache(), which walks the per-ITS translation cache with xa_for_each() and calls vgic_put_irq() on the iterated pointer rather than on the value safely returned by xa_erase(). Multiple contexts can enter this function under different locks, so the race is entirely reachable from a guest by mixing ITS command handling, a GITS_CTLR write, and clearing EnableLPIs in a redistributor
.
While guest-to-host escapes are rare, they are the most dangerous class of hypervisor bug because they shatter the isolation boundary that cloud computing depends on. Previous public KVM escapes targeted x86, usually via QEMU or AMD-specific code . ITScape is the first working exploit to demonstrate a breakout from an unprivileged arm64 guest VM through the in-kernel KVM code itself — no userspace emulator bugs required
.
For cloud providers running Graviton, Ampere Altra, or any arm64 KVM host with multi-tenant workloads, a guest can:
The vulnerable code sits in the LPI translation cache invalidation path. When the kernel needs to flush cache entries, it iterates through the XArray with xa_for_each() and calls vgic_put_irq() to release the reference count on each entry. The problem is that xa_for_each() returns entries that may have already been erased by a concurrent operation — such as a DISCARD ITS command issued from a different vCPU. The invalidate loop still drops the reference on that already-removed entry, causing a double-put and ultimately a use-after-free
.
An earlier vulnerability in the same code, CVE-2024-26598, had partially addressed a UAF in the LPI translation cache hit path by raising the refcount inside vgic_its_check_cache() before dropping the lock. That fix did not cover the invalidate path, leaving the race exploitable through a different trigger sequence
.
The upstream fix modifies vgic_its_invalidate_cache() so that vgic_put_irq() is called only on the value returned by xa_erase(), not on every entry the iterator touches. The commit message reads: "KVM: arm64: vgic-its: Drop the translation cache reference only for the erased entry"
.
Because xa_erase() atomically removes and returns the old entry — or returns NULL if the entry was already gone — the fix ensures the reference count is decremented exactly once, eliminating the double-free window. The patch landed in the upstream kernel in early June 2026 and was rapidly pulled into the 6.x stable series around June 8–10, 2026
. Major distributions including Red Hat, SUSE, and Debian have issued backported fixes for their supported kernel branches
.
Hyunwoo Kim publicly released a working exploit on GitHub around June 9–10, 2026. The repository includes full source code, step-by-step reproduction instructions, and a technical description of the exploitation technique . The exploit triggers the race by coordinating vCPU threads that simultaneously issue DISCARD commands and LPI translation cache lookups, precisely landing the use-after-free for host code execution.
The public availability of a reliable PoC means that commodity exploit scanners and real-world attackers can weaponize the vulnerability with minimal effort, shortening the window between disclosure and active attacks.
If you operate multi-tenant arm64 KVM infrastructure — AWS Graviton, Ampere Altra, or any similar platform — treat this as an immediate emergency patch cycle.
Comments
0 comments