Zapscape: The KVM Escape Bug That Sat in Plain Sight for Six Years
Zapscape: The KVM Escape Bug That Sat in Plain Sight for Six Years
You spin up a $5 VM on your cloud provider. The physical box you land on is also hosting a dozen other tenants—startups, banks, maybe a competitor. KVM draws the line between you and them. Your memory, their memory. Your keys, their keys. Never the twain shall meet.
That line held until Zapscape.
CVE-2026-64561, found by Hyunwoo Kim (@v4bel), lets a guest break out to the host with kernel-level privileges. One compromised VM owns the entire physical machine—and every other VM sitting on it.
The bug lived in the Linux kernel from July 2020 to July 2026. Six years, nobody noticed.
The bug, explained without the kernel jargon
Nested virtualization—a VM inside a VM—asks for more address translation than the hardware can do on its own. So KVM builds software shadow page tables to track what L1's page tables say about L2's memory.
Each shadow page has a struct called kvm_mmu_page. Two fields matter here:
root_count: how many vCPUs are using this page as their root. Anything above zero means the reclaimer leaves it alone.
parent_ptes: a pointer to the parent page table. When the last parent goes away, the child can be cleaned up.
Normal reclamation works like you'd expect: memory runs low → walk the active list → skip pages with root_count > 0 → zap the rest. Clean, safe.
There's a second path, though. When KVM removes a parent page table entry, it checks whether the child is in nested guest mode and has no remaining parents; if both hold, it recursively zaps the child. And here's the kicker: that path never checks root_count.
So an attacker engineers a single shadow page X that is simultaneously a child of one nested page table and the root of another. Clean up X's parent, watch the recursive path zap X, and vCPUs keep writing into freed memory. That's your use-after-free.
The rest of the chain gets creative: two cross-cache operations to stretch the UAF, a KASLR bypass, then a hop through the kernel's log_wait, SRCU workqueue, and usermode helper to drop a root-owned file on the host. The PoC writes /Zapscape. Swapping that for a reverse shell is an afternoon's work.
An analogy. Think of a co-working space. Each company gets a locked floor. Building management (KVM) has one rule: don't touch occupied meeting rooms. But one janitor (the recursive reclamation path) never checks the booking system—they only look at whether the company nameplate has been scratched off the door. The attacker hangs two nameplates on the same room. The janitor sees one scratched off, assumes the room is free, and dismantles it mid-meeting. Now the attacker walks through the debris into the server room and grabs the master key.
Not just AMD. Intel too.
The public PoC targets AMD SVM/NPT on Linux 7.1.3, but the vulnerable code sits in the shared shadow MMU that Intel and AMD both use. Triggering it on Intel needs L1 to expose EPT page walk lengths of both 4 and 5—hardly an exotic configuration.
Then there's the part that annoys me most. On RHEL and derivatives, /dev/kvm ships with permissions 0666: any local user can open it. That turns Zapscape from a cloud escape into a plain local privilege escalation, no VM required. Those permission bits have been indefensible for years, and Zapscape just made the bill come due.
What's actually at stake
Running KVM as a provider? Patch now, patch everywhere. Every KVM/x86 host with nested virtualization enabled is in scope.
Building on someone else's cloud? Your security boundary is their kernel version. Ask them. Then ask again next quarter.
Self-hosting KVM? You have the most to lose and the slowest patch cycle. Move this to the top of the list.
v4bel's own words: the public PoC isn't a drop-in cloud weapon, but "moving the L1 actions into a guest kernel module and porting the exploit to match the host kernel's kconfig is not a difficult task." That's researcher-speak for "someone has probably already done it."
The pattern that should worry you
Zapscape isn't v4bel's first KVM escape. Earlier this year the same researcher published Januscape (CVE-2026-53359)—another escape, also in the shadow MMU. Two escapes, one subsystem, one year, one researcher.
That's not bad luck. That's a signal.
Shadow MMU code has been running in production kernels for decades without the sustained security scrutiny newer subsystems attract. My bet: there's more in there, and we hear about it before the year is out.
What you should do today
Check your kernel.
uname -r
If the July 21 fix isn't in, patch. On cloud VMs, check the provider's status page—and don't assume "managed" means "already handled."
Kill nested virtualization where you don't need it.
lsmod | grep kvm
Running KVM inside a VM is niche. If you didn't turn it on deliberately, turn it off.
Lock down /dev/kvm.
ls -la /dev/kvm
0666 is a local root waiting to happen. 0660 covers most setups.
Virtualization isn't magic. Your sandbox is only as strong as the code enforcing it, and that code missed a root_count check for six years.
Run those three checks today. Then go find the next thing you've been trusting without ever verifying it.
Sources:
- Zapscape on GitHub (PoC + technical write-up)
- Kernel fix commit
- Januscape (CVE-2026-53359) - prior KVM escape by the same author
✨ Draft generated by DeepSeek, reviewed and polished by Claude.