[PATCH] KVM: x86/mmu: WARN and flush TLBs if TDP MMU replaces present SPTE with MMIO SPTE
From: Sean Christopherson
Date: Wed Oct 21 2026 - 22:25:29 EST
If KVM is buggy and manages to replace a shadow-present SPTE with an MMIO
SPTE in the TDP MMU, WARN but emit a TLB flush to prevent a potential use-
after-free. It should be impossible for KVM to resolve a GFN to a memslot
and then later find no memslot, but due to flaws in KVM's handling of GFNs
that can be generated by the guest[*], KVM can/wrap truncate GFNs when
walking SPTEs and resolve two different GFNs to the same SPTE.
Note, this is NOT a fix for the GFN truncation issues, it is purely a
stopgap that also happens to be valuable long-term hardening.
Link: https://lore.kernel.org/all/20260219002241.2908563-1-seanjc@xxxxxxxxxx [*]
Cc: stable@xxxxxxxxxxxxxxx
Reported-by: Stefan Teodorescu <fane@xxxxxxxxxx>
Signed-off-by: Sean Christopherson <seanjc@xxxxxxxxxx>
---
arch/x86/kvm/mmu/tdp_mmu.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 44dad106fad1..2735cbb21293 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -1151,6 +1151,7 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
return RET_PF_RETRY;
else if (is_shadow_present_pte(iter->old_spte) &&
(!is_last_spte(iter->old_spte, iter->level) ||
+ WARN_ON_ONCE(!is_shadow_present_pte(new_spte)) ||
WARN_ON_ONCE(leaf_spte_change_needs_tlb_flush(iter->old_spte, new_spte))))
kvm_flush_remote_tlbs_gfn(vcpu->kvm, iter->gfn, iter->level);
base-commit: 814607cd40df80d5727957adaa857e0feca43497
--
2.56.0.218.g1ec904b173-goog