Skip to content

Commit d0bf8e6

Browse files
sean-jcbonzini
authored andcommitted
KVM: x86/mmu: Exit to userspace with -EFAULT if private fault hits emulation
Exit to userspace with -EFAULT / KVM_EXIT_MEMORY_FAULT if a private fault triggers emulation of any kind, as KVM doesn't currently support emulating access to guest private memory. Practically speaking, private faults and emulation are already mutually exclusive, but there are many flow that can result in KVM returning RET_PF_EMULATE, and adding one last check to harden against weird, unexpected combinations and/or KVM bugs is inexpensive. Suggested-by: Yan Zhao <yan.y.zhao@intel.com> Signed-off-by: Sean Christopherson <seanjc@google.com> Message-ID: <20240228024147.41573-2-seanjc@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
1 parent a96cb3b commit d0bf8e6

2 files changed

Lines changed: 19 additions & 8 deletions

File tree

arch/x86/kvm/mmu/mmu.c

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4256,14 +4256,6 @@ static inline u8 kvm_max_level_for_order(int order)
42564256
return PG_LEVEL_4K;
42574257
}
42584258

4259-
static void kvm_mmu_prepare_memory_fault_exit(struct kvm_vcpu *vcpu,
4260-
struct kvm_page_fault *fault)
4261-
{
4262-
kvm_prepare_memory_fault_exit(vcpu, fault->gfn << PAGE_SHIFT,
4263-
PAGE_SIZE, fault->write, fault->exec,
4264-
fault->is_private);
4265-
}
4266-
42674259
static int kvm_faultin_pfn_private(struct kvm_vcpu *vcpu,
42684260
struct kvm_page_fault *fault)
42694261
{

arch/x86/kvm/mmu/mmu_internal.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,14 @@ enum {
279279
RET_PF_SPURIOUS,
280280
};
281281

282+
static inline void kvm_mmu_prepare_memory_fault_exit(struct kvm_vcpu *vcpu,
283+
struct kvm_page_fault *fault)
284+
{
285+
kvm_prepare_memory_fault_exit(vcpu, fault->gfn << PAGE_SHIFT,
286+
PAGE_SIZE, fault->write, fault->exec,
287+
fault->is_private);
288+
}
289+
282290
static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
283291
u32 err, bool prefetch, int *emulation_type)
284292
{
@@ -320,6 +328,17 @@ static inline int kvm_mmu_do_page_fault(struct kvm_vcpu *vcpu, gpa_t cr2_or_gpa,
320328
else
321329
r = vcpu->arch.mmu->page_fault(vcpu, &fault);
322330

331+
/*
332+
* Not sure what's happening, but punt to userspace and hope that
333+
* they can fix it by changing memory to shared, or they can
334+
* provide a better error.
335+
*/
336+
if (r == RET_PF_EMULATE && fault.is_private) {
337+
pr_warn_ratelimited("kvm: unexpected emulation request on private memory\n");
338+
kvm_mmu_prepare_memory_fault_exit(vcpu, &fault);
339+
return -EFAULT;
340+
}
341+
323342
if (fault.write_fault_to_shadow_pgtable && emulation_type)
324343
*emulation_type |= EMULTYPE_WRITE_PF_TO_SP;
325344

0 commit comments

Comments
 (0)