Skip to content

Commit ad44aa4

Browse files
committed
KVM: TDX: Bug the VM if extending the initial measurement fails
WARN and terminate the VM if TDH_MR_EXTEND fails, as extending the measurement should fail if and only if there is a KVM bug, or if the S-EPT mapping is invalid. Now that KVM makes all state transitions mutually exclusive via tdx_vm_state_guard, it should be impossible for S-EPT mappings to be removed between kvm_tdp_mmu_map_private_pfn() and tdh_mr_extend(). Holding slots_lock prevents zaps due to memslot updates, filemap_invalidate_lock() prevents zaps due to guest_memfd PUNCH_HOLE, vcpu->mutex locks prevents updates from other vCPUs, kvm->lock prevents VM-scoped ioctls from creating havoc (e.g. by creating new vCPUs), and all usage of kvm_zap_gfn_range() is mutually exclusive with S-EPT entries that can be used for the initial image. For kvm_zap_gfn_range(), the call from sev.c is obviously mutually exclusive, TDX disallows KVM_X86_QUIRK_IGNORE_GUEST_PAT so the same goes for kvm_noncoherent_dma_assignment_start_or_stop(), and __kvm_set_or_clear_apicv_inhibit() is blocked by virtue of holding all VM and vCPU mutexes (and the APIC page has its own KVM-internal memslot that is never created for TDX VMs, and so can't possibly be used for the initial image, which means that too is mutually exclusive irrespective of locking). Opportunistically return early if the region doesn't need to be measured in order to reduce line lengths and avoid wraps. Similarly, immediately and explicitly return if TDH_MR_EXTEND fails to make it clear that KVM needs to bail entirely if extending the measurement fails. Reviewed-by: Binbin Wu <binbin.wu@linux.intel.com> Reviewed-by: Kai Huang <kai.huang@intel.com> Reviewed-by: Yan Zhao <yan.y.zhao@intel.com> Tested-by: Yan Zhao <yan.y.zhao@intel.com> Tested-by: Kai Huang <kai.huang@intel.com> Link: https://patch.msgid.link/20251030200951.3402865-28-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 15945e9 commit ad44aa4

File tree

1 file changed

+13
-11
lines changed

1 file changed

+13
-11
lines changed

arch/x86/kvm/vmx/tdx.c

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3133,21 +3133,23 @@ static int tdx_gmem_post_populate(struct kvm *kvm, gfn_t gfn, kvm_pfn_t pfn,
31333133

31343134
put_page(src_page);
31353135

3136-
if (ret)
3136+
if (ret || !(arg->flags & KVM_TDX_MEASURE_MEMORY_REGION))
31373137
return ret;
31383138

3139-
if (arg->flags & KVM_TDX_MEASURE_MEMORY_REGION) {
3140-
for (i = 0; i < PAGE_SIZE; i += TDX_EXTENDMR_CHUNKSIZE) {
3141-
err = tdh_mr_extend(&kvm_tdx->td, gpa + i, &entry,
3142-
&level_state);
3143-
if (err) {
3144-
ret = -EIO;
3145-
break;
3146-
}
3147-
}
3139+
/*
3140+
* Note, MR.EXTEND can fail if the S-EPT mapping is somehow removed
3141+
* between mapping the pfn and now, but slots_lock prevents memslot
3142+
* updates, filemap_invalidate_lock() prevents guest_memfd updates,
3143+
* mmu_notifier events can't reach S-EPT entries, and KVM's internal
3144+
* zapping flows are mutually exclusive with S-EPT mappings.
3145+
*/
3146+
for (i = 0; i < PAGE_SIZE; i += TDX_EXTENDMR_CHUNKSIZE) {
3147+
err = tdh_mr_extend(&kvm_tdx->td, gpa + i, &entry, &level_state);
3148+
if (TDX_BUG_ON_2(err, TDH_MR_EXTEND, entry, level_state, kvm))
3149+
return -EIO;
31483150
}
31493151

3150-
return ret;
3152+
return 0;
31513153
}
31523154

31533155
static int tdx_vcpu_init_mem_region(struct kvm_vcpu *vcpu, struct kvm_tdx_cmd *cmd)

0 commit comments

Comments
 (0)