linux/arch/x86/kvm/mmu
Lai Jiangshan 84e5ffd045 KVM: X86/MMU: Fix shadowing 5-level NPT for 4-level NPT L1 guest
When shadowing 5-level NPT for 4-level NPT L1 guest, the root_sp is
allocated with role.level = 5 and the guest pagetable's root gfn.

And root_sp->spt[0] is also allocated with the same gfn and the same
role except role.level = 4.  Luckily that they are different shadow
pages, but only root_sp->spt[0] is the real translation of the guest
pagetable.

Here comes a problem:

If the guest switches from gCR4_LA57=0 to gCR4_LA57=1 (or vice verse)
and uses the same gfn as the root page for nested NPT before and after
switching gCR4_LA57.  The host (hCR4_LA57=1) might use the same root_sp
for the guest even the guest switches gCR4_LA57.  The guest will see
unexpected page mapped and L2 may exploit the bug and hurt L1.  It is
lucky that the problem can't hurt L0.

And three special cases need to be handled:

The root_sp should be like role.direct=1 sometimes: its contents are
not backed by gptes, root_sp->gfns is meaningless.  (For a normal high
level sp in shadow paging, sp->gfns is often unused and kept zero, but
it could be relevant and meaningful if sp->gfns is used because they
are backed by concrete gptes.)

For such root_sp in the case, root_sp is just a portal to contribute
root_sp->spt[0], and root_sp->gfns should not be used and
root_sp->spt[0] should not be dropped if gpte[0] of the guest root
pagetable is changed.

Such root_sp should not be accounted too.

So add role.passthrough to distinguish the shadow pages in the hash
when gCR4_LA57 is toggled and fix above special cases by using it in
kvm_mmu_page_{get|set}_gfn() and sp_has_gptes().

Signed-off-by: Lai Jiangshan <jiangshan.ljs@antgroup.com>
Message-Id: <20220420131204.2850-3-jiangshanlai@gmail.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2022-04-29 12:50:00 -04:00
..
mmu_internal.h KVM: x86/mmu: Zap invalidated roots via asynchronous worker 2022-03-08 10:55:27 -05:00
mmu.c KVM: X86/MMU: Fix shadowing 5-level NPT for 4-level NPT L1 guest 2022-04-29 12:50:00 -04:00
mmutrace.h KVM: x86/mmu: Add tracepoint for splitting huge pages 2022-02-10 13:50:43 -05:00
page_track.c KVM: use __vcalloc for very large allocations 2022-03-08 09:30:57 -05:00
paging_tmpl.h KVM: X86/MMU: Fix shadowing 5-level NPT for 4-level NPT L1 guest 2022-04-29 12:50:00 -04:00
paging.h KVM: x86/mmu: Do not apply HPA (memory encryption) mask to GPAs 2021-07-14 12:17:56 -04:00
spte.c KVM: x86/mmu: Use enable_mmio_caching to track if MMIO caching is enabled 2022-04-29 12:49:16 -04:00
spte.h KVM: x86/mmu: Use enable_mmio_caching to track if MMIO caching is enabled 2022-04-29 12:49:16 -04:00
tdp_iter.c KVM: x86/mmu: Add helpers to read/write TDP MMU SPTEs and document RCU 2022-03-08 09:31:52 -05:00
tdp_iter.h KVM: x86/mmu: Defer TLB flush to caller when freeing TDP MMU shadow pages 2022-03-08 09:31:57 -05:00
tdp_mmu.c KVM: x86/mmu: replace shadow_root_level with root_role.level 2022-04-29 12:49:58 -04:00
tdp_mmu.h KVM: x86/mmu: Zap only TDP MMU leafs in zap range and mmu_notifier unmap 2022-04-02 05:34:39 -04:00