Januscape (CVE-2026-53359): The 16-Year-Old KVM Bug That Lets a Guest VM Take Down Its Host

The CyberSec Guru

Updated on:

Januscape (CVE-2026-53359)

If you like this post, then please share it:

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Why your support matters: Zero paywalls: Keep the main content 100% free for learners worldwide.

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

A bug that has been sitting in the Linux kernel since August 2010 just got a name, a public proof of concept, and a patch. Researcher Hyunwoo Kim, who goes by v4bel, calls it Januscape. The rest of the world knows it as CVE-2026-53359, and if you run KVM hosts with nested virtualization turned on, it deserves your attention this week, not next sprint.

The short version: a guest VM with root inside itself can trigger a use-after-free in the host kernel’s shadow paging code. The public exploit panics the host. Kim says a second, unreleased exploit turns the same bug into full code execution as root on the host, which would put every other tenant on that physical machine inside the blast radius. No QEMU involvement required. No hardware bug. Just sixteen years of a validation check that compared the wrong fields.

Where the bug lives

KVM has two ways of translating guest-physical addresses to host-physical addresses. On modern Intel and AMD chips, it leans on hardware, EPT on Intel, NPT on AMD, and the CPU does the second layer of translation for free. But the moment you turn on nested virtualization, so a guest can run its own guests, KVM drops back to software: shadow paging.

In shadow paging mode, the hypervisor keeps its own private set of page tables that mirror whatever the guest thinks its page tables look like. Each of these tracking structures is a struct kvm_mmu_page, and two fields on it matter for this story: the guest frame number (gfn) it represents, and its role, a bundle of flags that includes whether the page is direct (a straight, large mapping) or not (a proper multi-level shadow of the guest’s own page table). When KVM needs a shadow page for a given address, it checks whether it can reuse one it already has lying around. That reuse decision is where this whole thing falls apart.

The first fix, and the vulnerability it left behind

This isn’t Januscape’s first appearance. Back in May, a related vulnerability, CVE-2026-46113, was fixed by commit 0cb2af2ea66ad, titled “KVM: x86: Fix shadow paging use-after-free due to unexpected GFN.” That bug worked like this: an attacker inside the guest modifies a page-directory entry (PDE) from outside the guest’s own view of things, then deletes a memslot. The cleanup routine, rmap_remove(), is supposed to walk every reverse-mapped entry and tear it down, but it missed entries created after the PDE change, because the gfn of the leaf shadow page-table entry no longer matched the gfn recorded on the kvm_mmu_page that owned it. Stale entries survived. The structure they pointed to got freed anyway. Classic use-after-free.

That fix added a gfn check and closed the leaf case. What it didn’t cover is what happens when the modified PDE points to a non-leaf page instead of a leaf. In that scenario, an attacker can arrange things so the gfn matches perfectly, sailing right through the newly added check, while the role quietly doesn’t. The original mapping was a large 2MB page, built with direct=1. The new mapping needs a 4KB shadow, which requires direct=0. Two structurally different objects, same gfn.

The function responsible for deciding whether to reuse a shadow page, kvm_mmu_get_child_sp(), only ever compared the gfn. It never looked at role. So it happily handed back the old, wrong-typed page, cleanup missed the entries it should have caught for the same reason as before, and the kernel eventually freed a kvm_mmu_page structure that was still being referenced elsewhere. Anything that later touches that dangling pointer is operating on freed memory. That’s the use-after-free at the center of CVE-2026-53359.

The May patch checked one field. This one required checking two. Identity, in this code path, was never fully described by the gfn alone, and nobody noticed for a decade and a half because triggering the non-leaf variant needs a fairly specific sequence: modify a PDE mapping from outside the guest’s normal path, delete the right memslot, and land in exactly the state where gfn matches but role doesn’t.

Who found it, and why this keeps happening to the same researcher

Kim’s Januscape write-up frames it as the first publicly documented guest-to-host exploit that works on both Intel and AMD from the same trigger, with the last, hardest step of turning corruption into full control differing slightly by vendor. He reported it through Google’s kvmCTF program, the controlled reward program Google runs specifically because KVM sits underneath both Android and large chunks of Google Cloud, and he says the submission counted as a zero-day at the time he sent it in, meaning there was no public patch yet. That’s worth separating from “exploited in the wild”: kvmCTF is a bug bounty environment, not an active-attacker campaign, and there’s no evidence of Januscape being used maliciously outside of that controlled setting.

What’s harder to shrug off is Kim’s recent output. Januscape is his third Linux kernel disclosure in about two months. In May he published Dirty Frag (CVE-2026-43284 and CVE-2026-43500), a page-cache write chain in the same rough lineage as Dirty Pipe and Copy Fail. In June, ITScape (CVE-2026-46316) became the first publicly demonstrated KVM guest-to-host escape on arm64, exploiting a race condition and use-after-free in the vGIC-ITS interrupt controller code, specifically in vgic_its_invalidate_cache(). Januscape closes out the trilogy on the x86 side. Three different subsystems, three different bug classes, one researcher, ten weeks. However you want to read that, it’s not a slow year for KVM.

Disclosure followed the usual private channel: Kim reported CVE-2026-53359 to the linux-distros mailing list, an embargo ran while distributions prepared backports, and once it lapsed the writeup went out on oss-security along with the GitHub repository. His own repo notes the vulnerable window runs from commit 2032a93d66fa, dated August 1, 2010, straight through to the fix, commit 81ccda30b4e8, merged in mid-June 2026. Sixteen years, give or take, is not an exaggeration for effect. It’s the literal commit range.

What it takes to trigger this

Two things have to be true from the guest side. First, the attacker needs root inside the VM, which on a rented cloud instance is usually just the default state of things, not a privilege they need to earn. Second, the host needs nested virtualization enabled and exposed to that guest. That second condition is the one people underestimate. Even hosts that default to hardware-assisted paging fall back into the legacy shadow MMU the instant nested virtualization is turned on, because the inner hypervisor needs shadow paging to virtualize the second layer. Turn on nested virt for convenience, and you’ve quietly reopened a code path with sixteen years of accumulated risk sitting in it.

The exploit doesn’t route through QEMU or any userspace VMM at all. It’s purely an in-kernel KVM bug, which means it threatens any x86 environment building its own virtualization stack on top of KVM, not just QEMU-based deployments. The publicly released PoC reliably panics the host from inside a guest using a loadable kernel module, with the race window running from seconds to a few minutes. That alone is enough to take down every co-tenant VM on a shared physical box. Kim maintains that the withheld full exploit gets further, to root-level code execution on the host, which is the scenario that actually breaks tenant isolation rather than just interrupting it.

There’s a secondary angle too. On distributions where /dev/kvm ships world-writable, RHEL among them, an unprivileged local user can potentially ride this bug to local privilege escalation without ever touching a guest VM. Kim’s own assessment is that this is a minor footnote next to the guest-to-host escape, and I’d agree; if you already have a foothold on the bare host, there are usually easier paths to root than orchestrating a shadow MMU race.

The fix, and why it’s almost insultingly small

The patch itself is close to a one-liner. kvm_mmu_get_child_sp() now checks role.word alongside gfn before deciding a shadow page can be reused, so a page only gets handed back when both the frame number and the role actually match. KVM maintainer Paolo Bonzini wrote the change. It landed in the July 2026 stable rollup across 7.1.3, 6.18.38, 6.12.95, 6.6.144, 6.1.177, 5.15.211, and 5.10.260, all dated July 4, 2026.

NVD published the record the same day, without a severity score attached at first. Red Hat’s own advisory came a day later, on July 5, assigning a CVSS base score of 7. That’s a meaningful jump from “pending” to a number defenders can actually feed into a prioritization model, and it landed inside 48 hours of the CVE going public, which is faster than a lot of kernel CVEs manage.

What to do about it

Patch first, ask questions later. Get your distribution’s July 2026 kernel build or later, one that includes commit 81ccda30b4e8, and reboot into it. Distribution backports rarely match the upstream version number, so check the changelog for the commit hash rather than trusting uname -r.

If you can’t patch today, kill nested virtualization. Setting kvm_intel.nested=0 or kvm_amd.nested=0 removes the code path entirely for untrusted guests. It’s a blunt instrument, and it’ll break anyone actually relying on nested virt, but it closes the door immediately.

Audit who can spin up untrusted guests with nesting enabled. On multi-tenant infrastructure, this is the real exposure surface. A single rented instance with nesting turned on is enough.

Check /dev/kvm permissions on the host. World-writable device nodes turn a guest-side bug into a local privilege escalation path too, independent of the VM escape scenario.

If you already patched ITScape (CVE-2026-46316) or the May shadow paging fix (CVE-2026-46113), don’t assume this one is covered. All three are distinct bugs in adjacent code, and each needed its own patch.

Update: proxmox-kernel-7.0.14-4-pve and proxmox-kernel-6.8.12-33-pve were released today, a few hours ago. They are opt-in releases so make sure to manually patch asap!

The part that actually bothers me

What sticks with me about Januscape isn’t the sixteen years, honestly. Old bugs in complex subsystems are the rule, not the exception, especially in a code path that hardware-assisted paging has quietly pushed to the margins for most of the last decade. What bothers me is that the May fix for CVE-2026-46113 was correct as far as it went, and still left a structurally identical hole one field over. Whoever wrote the original check reasoned about identity in terms of a single attribute, gfn, when the actual invariant the code needed to protect was “this structure represents the same guest mapping in the same way it did before.” That’s a two-field comparison, not a one-field lookup, and the gap between those two framings is exactly where CVE-2026-53359 lived.

Shadow paging in KVM has now produced two separate use-after-frees in the same general area within about sixty days. That’s not proof the subsystem is uniquely broken. It’s proof that legacy code paths kept alive for backward compatibility don’t get the scrutiny that default, hardware-accelerated paths do, right up until someone like Kim goes looking on purpose.

faqs

What is Januscape (CVE-2026-53359)?

Januscape is a use-after-free vulnerability in the Linux KVM hypervisor’s shadow MMU, tracked as CVE-2026-53359. A guest VM with root and nested virtualization enabled can corrupt host kernel memory, crashing the host or, per the researcher, potentially executing code as root on it. The flawed code dates to 2010

Buy me A Coffee!

Support The CyberSec Guru’s Mission

🔐 Fuel the cybersecurity crusade by buying me a coffee! Your contribution powers free tutorials, hands-on labs, and security resources.

Why your support matters:
  • Writeup Access: Get complete writeup access within 12 hours
  • Zero paywalls: Keep the main content 100% free for learners worldwide

Perks for one-time supporters:
☕️ $5: Shoutout in Buy Me a Coffee
🛡️ $8: Fast-track Access to Live Webinars
💻 $10: Vote on future tutorial topics + exclusive AMA access

“Your coffee keeps the servers running and the knowledge flowing in our fight against cybercrime.”☕ Support My Work

Buy Me a Coffee Button

If you like this post, then please share it:

News

Discover more from The CyberSec Guru

Subscribe to get the latest posts sent to your email!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Discover more from The CyberSec Guru

Subscribe now to keep reading and get access to the full archive.

Continue reading