ITScape (CVE-2026-46316): KVM/ARM64 VM escape

_ananos_1 pts1 comments

When the bug is real but the path isn't: ITScape (CVE-2026-46316) and the case for minimal runtimes · NOFire

Talk to us

Blog/Engineering<br>Engineering12 Jun 20265 min read<br>When the bug is real but the path isn't: ITScape (CVE-2026-46316) and the case for minimal runtimes

Anastassios NanosCo-founder & Chief Scientist

CVE-2026-46316 ("ITScape"). Reported by Hyunwoo Kim (@v4bel). This post discusses the vulnerability and its mitigations at a conceptual level using already-public information: no gadget offsets, no heap-spray primitives beyond what the author's own write-up discloses.

TL;DR

ITScape is the first publicly documented guest-to-host escape on KVM/arm64. It abuses a race condition in the in-kernel vGIC-ITS emulation to reach host-kernel code execution from inside an unprivileged guest. We reproduced it on a Jetson AGX Orin running kernel v7.1-rc6.

The defensive story is more nuanced and more honest than "unikernels are safe":

urunc is safe by design : urunc's seccomp filter blocks KVM_CREATE_DEVICE for the ITS type before the virtual GIC ITS object is ever created. To prove this is the active mechanism, we deliberately stripped that filter and confirmed the ITS becomes reachable immediately. The vulnerability follows directly.

Every other VMM we tested exposes GIC ITS : QEMU (-M virt), Cloud Hypervisor v41.0.0, Dragonball (kata runtime-rs), Firecracker ≥ v1.13.0, Kata-QEMU, and Kata-Firecracker ≥ v1.13.0 all create the ITS device unconditionally. The IIDR read confirms 0x4b00043b in each case.

Firecracker ≤ v1.12.1 is the one architectural exception : that codebase contains zero ITS-related symbols. From v1.13.0 onward, PR #5364 introduced ITS unconditionally as a PCIe prerequisite, without a CHANGELOG entry.

The broader lesson is sharper than "minimal runtimes are safe": every modern VMM on aarch64 now exposes GIC ITS. urunc's seccomp filter is the only runtime default that blocks the attack surface. That filter is operational, not architectural: one config change away from exposure. Firecracker ≤ v1.12.1 is the only VMM where the absence is structural.

1. The vulnerability

ITScape is a race condition in the in-kernel KVM arm64 interrupt controller emulation, specifically in vgic_its_invalidate_cache() combined with vgic_its_process_commands() in arch/arm64/kvm/vgic/. A guest with EL1 (kernel) privilege drives the virtual GIC ITS via MMIO; two concurrent accesses to the same vgic_irq refcount produce a double-put, leading to a use-after-free on a kmalloc-96 object in the host kernel.

What makes it notable:

In-kernel KVM, not QEMU. Most published VM escapes are bugs in the userspace device model and grant at most QEMU-process privileges. ITScape runs in the host kernel's context; success is a full host-kernel compromise.

Guest-driven. No host-side action is needed; the guest triggers it through ordinary MMIO writes.

arm64-specific. The bug is in arch/arm64/kvm/vgic/. x86 is unaffected.

Affected range: 8201d1028caa (2024-04-25) → 13031fb6b835 (2026-06-05, the fix).

The full exploit chain on v7.1-rc6 with nokaslr on the Jetson AGX Orin:

Race INT commands vs GICR_CTLR.EnableLPIs toggle → double-put on vgic_irq → UAF

64 MB guest_memfd cross-cache spray reclaims freed kmalloc-96 slot with a fake vgic_irq

Leak target_vcpu pointer from fake object → kimage_voffset = 0x0 (nokaslr)

Arbitrary write via ed_deschedule+0xf4 gadget: ldr x0,[x1,#32]; cbz; ldr x1,[x1,#40]; str x1,[x0,#40]; ret

Overwrite poweroff_cmd = "/bin/touch /ITScape" and arp_tbl.gc_work.func = orderly_poweroff

Neigh-GC timer fires → orderly_poweroff() → usermode helper runs /bin/touch /ITScape as uid=0 on the host

The race at the heart of the bug looks like this in the host kernel:

/* Thread A (guest INT command handler) */<br>irq = vgic_its_check_cache(its, device_id, event_id);<br>vgic_put_irq(kvm, irq); // refcount--; may reach 0 -> kfree()

/* Thread B (guest GICR_CTLR.EnableLPIs toggle) */<br>vgic_its_invalidate_cache(its); // iterates cache, calls vgic_put_irq()<br>vgic_put_irq(kvm, irq); // second put on same object -> UAF<br>Both threads are driven by ordinary guest MMIO writes with no host-side action required. The freed kmalloc-96 object is then reclaimed via a cross-cache spray from guest_memfd, giving the attacker a controlled fake vgic_irq in host-kernel memory.

Figure 1: the full chain from guest MMIO writes to host-root UMH execution

2. Reproduction on Jetson AGX Orin

Platform: Jetson AGX Orin · kernel v7.1-rc6 · GCC 11.4 · nokaslr · GICv3+GIC-600 hardware

The itscape:latest container image is a FROM scratch image carrying three binaries: guest_exploit (the in-guest ITS trigger), host_exploit (the full KVM-selftest PoC), and the exploit kernel Image. It is built with GCC 13 inside a Ubuntu 22.04 builder stage. GCC 13 is required for the specific ed_deschedule+0xf4 gadget codegen. Kernel addresses are patched at build time by patch_addresses.py for the v7.1-rc6 / GCC 11.4 / nokaslr build.

The guest-side trigger...

kernel guest host itscape from arm64

Related Articles