This CVE reveals a silent type-confusion bug in KVM's shadow page cache. The vulnerability lives in the gap between what the cache lookup validates and what downstream code assumes about the returned shadow page.

The shadow page cache in kvm_mmu_get_child_sp() uses only the guest frame number (GFN) as its lookup key. However, the role field — specifically the direct flag — determines how kvm_mmu_page_get_gfn() computes addresses for rmap operations. When the direct flag is set (backing a 2MB large page), the address computation differs fundamentally from when it's clear (backing a 4KB page requiring translation). The cache lookup never verifies the role matches what the caller expects.

This creates a window where a shadow page with direct=1 can be silently returned for an operation expecting direct=0, or vice versa. The returned page has a valid GFN but incorrect internal state for the operation being performed. Downstream code then computes rmap addresses based on the wrong role, corrupting the rmap chain. When the memslot is later torn down, the code walks this corrupted rmap structure and dereferences a freed pointer — the use-after-free that triggers the crash.

What makes this insidious is that the memory remains valid throughout. Standard sanitizers won't catch it because there's no memory corruption at the moment of the role mismatch — only semantic incorrectness in how addresses are computed. The corruption propagates forward through every downstream caller: dirty logging, MMU notifier invalidation, and any subsequent page table walk that hits that GFN.

The immediate fix is to make the shadow page cache lookup check both GFN and the full role (including direct flag) before returning a cached page. This ensures the semantic assumptions of the caller are validated at the cache layer. Audit other kvm_mmu_page_get_gfn() call sites to verify they aren't making similar implicit role assumptions that could be violated by cached pages in the wrong state.

The deeper issue: this bug emerged because the original fix addressed only the visible symptom (GFN mismatch) without recognizing that role is a co-determinate of correctness for address computation. Any refactoring must make role comparison explicit and enforced, not just in the zap path but across all shadow page reuse decisions.