KVM translates guest virtual addresses to host physical addresses through two fundamentally different mechanisms. Understanding which mechanism is active — and why nested virtualization forces a switch to the legacy software path — is essential to understanding where Januscape lives and why it is triggerable on both Intel and AMD hosts despite being pure in-kernel KVM code.Documentation Index
Fetch the complete documentation index at: https://mintlify.com/V4bel/Januscape/llms.txt
Use this file to discover all available pages before exploring further.
Two Address-Translation Modes in x86 KVM
Hardware Two-Stage Paging (TDP MMU)
Intel EPT and AMD NPT let the hardware handle both GVA→GPA and GPA→HPA translation. This is the default on modern hosts (
kvm-intel.ept=1, tdp_mmu=Y). KVM uses the TDP MMU for this path, which bypasses the legacy shadow MMU entirely.Shadow Paging (Shadow MMU)
KVM shadows guest page tables in software. Each level of the guest PT is represented by a
struct kvm_mmu_page (a shadow page), whose backing 4KB page is sp->spt. The shadow MMU walks the guest-controlled PT tree and creates or links a shadow page for each level.Why Nested Virtualization Forces Shadow Paging
Level notation: L0 is the bare-metal host kernel running KVM. L1 is the first-level guest — the VM the attacker controls. L2 is the nested guest that L1 (acting as a hypervisor) launches inside itself. The bug fires on L0 while L0 processes faults generated by L2 execution.
ept=1 is set on the host. This is the code path that Januscape exploits.
The relevant initialization confirms this clearly:
guest_mmu) at [16] shadows guest-controlled page tables, so its root_role.direct is false. KVM therefore installs the legacy ept_page_fault handler at [17], not kvm_tdp_page_fault. is_tdp_mmu_active at [18] also returns false because the root role is non-direct — the TDP MMU lockless fast path is bypassed entirely. On AMD, kvm_init_shadow_npt_mmu applies the same logic with the same result.
This means the bug path is active on any default
ept=1 host — as long as the guest has nested virtualization exposed and uses it to run L2. The host never needs to have shadow paging explicitly configured.This Is Pure In-Kernel KVM
Unlike many published VM-escape vulnerabilities that involve QEMU device emulation, Januscape lives entirely inside in-kernel KVM. The faults that occur as L1 builds its nested EPT and runs L2 are handled entirely by the host kernel’s KVM module and never reach userspace. QEMU is not involved and is not a prerequisite. This also means the vulnerability threatens cloud providers that have replaced QEMU with their own VMM.struct kvm_mmu_page and Shadow Page Roles
Each level of the shadowed page table tree is represented by a struct kvm_mmu_page. The key field for understanding this bug is role, a packed bitfield of type union kvm_mmu_page_role that encodes what kind of shadow page this is:
role.direct bit is the critical field for this vulnerability:
role.direct | Meaning |
|---|---|
0 (indirect) | This shadow page shadows an actual guest page table. The guest controls the contents of the page it maps. |
1 (direct split) | This shadow page was split by KVM from a large page (2MB) into 4KB mappings. KVM controls it; there is no corresponding guest PT. |
gfn simultaneously under certain conditions — and the bug arises precisely when the kernel fails to distinguish them during reuse decisions.