Joerg Roedel 3916df
From: Paolo Bonzini <pbonzini@redhat.com>
Joerg Roedel 3916df
Date: Fri, 17 Apr 2020 12:21:06 -0400
Joerg Roedel 3916df
Subject: KVM: SVM: avoid infinite loop on NPF from bad address
Joerg Roedel 3916df
Git-commit: e72436bc3a5206f95bb384e741154166ddb3202e
Joerg Roedel 3916df
Patch-mainline: v5.8-rc1
Joerg Roedel 3916df
References: CVE-2020-36310 bsc#1184512
Joerg Roedel 3916df
Joerg Roedel 3916df
When a nested page fault is taken from an address that does not have
Joerg Roedel 3916df
a memslot associated to it, kvm_mmu_do_page_fault returns RET_PF_EMULATE
Joerg Roedel 3916df
(via mmu_set_spte) and kvm_mmu_page_fault then invokes svm_need_emulation_on_page_fault.
Joerg Roedel 3916df
Joerg Roedel 3916df
The default answer there is to return false, but in this case this just
Joerg Roedel 3916df
causes the page fault to be retried ad libitum.  Since this is not a
Joerg Roedel 3916df
fast path, and the only other case where it is taken is an erratum,
Joerg Roedel 3916df
just stick a kvm_vcpu_gfn_to_memslot check in there to detect the
Joerg Roedel 3916df
common case where the erratum is not happening.
Joerg Roedel 3916df
Joerg Roedel 3916df
This fixes an infinite loop in the new set_memory_region_test.
Joerg Roedel 3916df
Joerg Roedel 3916df
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Joerg Roedel 3916df
Acked-by: Joerg Roedel <jroedel@suse.de>
Joerg Roedel 3916df
---
Joerg Roedel 3916df
 arch/x86/kvm/svm.c  |    7 +++++++
Joerg Roedel 3916df
 virt/kvm/kvm_main.c |    1 +
Joerg Roedel 3916df
 2 files changed, 8 insertions(+)
Joerg Roedel 3916df
Joerg Roedel 3916df
--- a/arch/x86/kvm/svm.c
Joerg Roedel 3916df
+++ b/arch/x86/kvm/svm.c
Joerg Roedel 3916df
@@ -7204,6 +7204,13 @@ static bool svm_need_emulation_on_page_f
Joerg Roedel 3916df
 	bool is_user = svm_get_cpl(vcpu) == 3;
Joerg Roedel 3916df
 
Joerg Roedel 3916df
 	/*
Joerg Roedel 3916df
+	 * If RIP is invalid, go ahead with emulation which will cause an
Joerg Roedel 3916df
+	 * internal error exit.
Joerg Roedel 3916df
+	 */
Joerg Roedel 3916df
+	if (!kvm_vcpu_gfn_to_memslot(vcpu, kvm_rip_read(vcpu) >> PAGE_SHIFT))
Joerg Roedel 3916df
+		return true;
Joerg Roedel 3916df
+
Joerg Roedel 3916df
+	/*
Joerg Roedel 3916df
 	 * Detect and workaround Errata 1096 Fam_17h_00_0Fh.
Joerg Roedel 3916df
 	 *
Joerg Roedel 3916df
 	 * Errata:
Joerg Roedel 3916df
--- a/virt/kvm/kvm_main.c
Joerg Roedel 3916df
+++ b/virt/kvm/kvm_main.c
Joerg Roedel 3916df
@@ -1369,6 +1369,7 @@ struct kvm_memory_slot *kvm_vcpu_gfn_to_
Joerg Roedel 3916df
 {
Joerg Roedel 3916df
 	return __gfn_to_memslot(kvm_vcpu_memslots(vcpu), gfn);
Joerg Roedel 3916df
 }
Joerg Roedel 3916df
+EXPORT_SYMBOL_GPL(kvm_vcpu_gfn_to_memslot);
Joerg Roedel 3916df
 
Joerg Roedel 3916df
 bool kvm_is_visible_gfn(struct kvm *kvm, gfn_t gfn)
Joerg Roedel 3916df
 {