Skip to content

Commit 28cf497

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86/mmu: Add lockdep assert to enforce safe usage of kvm_unmap_gfn_range()
Add a lockdep assertion in kvm_unmap_gfn_range() to ensure that either mmu_invalidate_in_progress is elevated, or that the range is being zapped due to memslot removal (loosely detected by slots_lock being held). Zapping SPTEs without mmu_invalidate_{in_progress,seq} protection is unsafe as KVM's page fault path snapshots state before acquiring mmu_lock, and thus can create SPTEs with stale information if vCPUs aren't forced to retry faults (due to seeing an in-progress or past MMU invalidation). Memslot removal is a special case, as the memslot is retrieved outside of mmu_invalidate_seq, i.e. doesn't use the "standard" protections, and instead relies on SRCU synchronization to ensure any in-flight page faults are fully resolved before zapping SPTEs. Signed-off-by: Sean Christopherson <[email protected]> Message-ID: <[email protected]> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent 58a20a9 commit 28cf497

File tree

1 file changed

+11
-0
lines changed

1 file changed

+11
-0
lines changed

arch/x86/kvm/mmu/mmu.c

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1556,6 +1556,17 @@ bool kvm_unmap_gfn_range(struct kvm *kvm, struct kvm_gfn_range *range)
15561556
{
15571557
bool flush = false;
15581558

1559+
/*
1560+
* To prevent races with vCPUs faulting in a gfn using stale data,
1561+
* zapping a gfn range must be protected by mmu_invalidate_in_progress
1562+
* (and mmu_invalidate_seq). The only exception is memslot deletion;
1563+
* in that case, SRCU synchronization ensures that SPTEs are zapped
1564+
* after all vCPUs have unlocked SRCU, guaranteeing that vCPUs see the
1565+
* invalid slot.
1566+
*/
1567+
lockdep_assert_once(kvm->mmu_invalidate_in_progress ||
1568+
lockdep_is_held(&kvm->slots_lock));
1569+
15591570
if (kvm_memslots_have_rmaps(kvm))
15601571
flush = __kvm_rmap_zap_gfn_range(kvm, range->slot,
15611572
range->start, range->end,

0 commit comments

Comments
 (0)