93 lines
3.4 KiB
Diff
93 lines
3.4 KiB
Diff
|
From adceca1789584fe567828afb7246bd35a8549e94 Mon Sep 17 00:00:00 2001
|
||
|
From: Eric Northup <digitaleric@google.com>
|
||
|
Date: Tue, 10 Nov 2015 13:22:52 +0100
|
||
|
Subject: [PATCH 1/2] KVM: x86: work around infinite loop in microcode when #AC
|
||
|
is delivered
|
||
|
|
||
|
It was found that a guest can DoS a host by triggering an infinite
|
||
|
stream of "alignment check" (#AC) exceptions. This causes the
|
||
|
microcode to enter an infinite loop where the core never receives
|
||
|
another interrupt. The host kernel panics pretty quickly due to the
|
||
|
effects (CVE-2015-5307).
|
||
|
|
||
|
Signed-off-by: Eric Northup <digitaleric@google.com>
|
||
|
Cc: stable@vger.kernel.org
|
||
|
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
|
||
|
---
|
||
|
arch/x86/include/uapi/asm/svm.h | 1 +
|
||
|
arch/x86/kvm/svm.c | 8 ++++++++
|
||
|
arch/x86/kvm/vmx.c | 5 ++++-
|
||
|
3 files changed, 13 insertions(+), 1 deletion(-)
|
||
|
|
||
|
diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
|
||
|
index b5d7640abc5d..8a4add8e4639 100644
|
||
|
--- a/arch/x86/include/uapi/asm/svm.h
|
||
|
+++ b/arch/x86/include/uapi/asm/svm.h
|
||
|
@@ -100,6 +100,7 @@
|
||
|
{ SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
|
||
|
{ SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
|
||
|
{ SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
|
||
|
+ { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \
|
||
|
{ SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
|
||
|
{ SVM_EXIT_INTR, "interrupt" }, \
|
||
|
{ SVM_EXIT_NMI, "nmi" }, \
|
||
|
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
|
||
|
index f2c8e4917688..7203b3cc71b5 100644
|
||
|
--- a/arch/x86/kvm/svm.c
|
||
|
+++ b/arch/x86/kvm/svm.c
|
||
|
@@ -1110,6 +1110,7 @@ static void init_vmcb(struct vcpu_svm *svm)
|
||
|
set_exception_intercept(svm, PF_VECTOR);
|
||
|
set_exception_intercept(svm, UD_VECTOR);
|
||
|
set_exception_intercept(svm, MC_VECTOR);
|
||
|
+ set_exception_intercept(svm, AC_VECTOR);
|
||
|
|
||
|
set_intercept(svm, INTERCEPT_INTR);
|
||
|
set_intercept(svm, INTERCEPT_NMI);
|
||
|
@@ -1798,6 +1799,12 @@ static int ud_interception(struct vcpu_svm *svm)
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
+static int ac_interception(struct vcpu_svm *svm)
|
||
|
+{
|
||
|
+ kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0);
|
||
|
+ return 1;
|
||
|
+}
|
||
|
+
|
||
|
static void svm_fpu_activate(struct kvm_vcpu *vcpu)
|
||
|
{
|
||
|
struct vcpu_svm *svm = to_svm(vcpu);
|
||
|
@@ -3362,6 +3369,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
|
||
|
[SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
|
||
|
[SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
|
||
|
[SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
|
||
|
+ [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
|
||
|
[SVM_EXIT_INTR] = intr_interception,
|
||
|
[SVM_EXIT_NMI] = nmi_interception,
|
||
|
[SVM_EXIT_SMI] = nop_on_interception,
|
||
|
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
|
||
|
index 5eb56ed77c1f..106aa940d3c0 100644
|
||
|
--- a/arch/x86/kvm/vmx.c
|
||
|
+++ b/arch/x86/kvm/vmx.c
|
||
|
@@ -1631,7 +1631,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
|
||
|
u32 eb;
|
||
|
|
||
|
eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) |
|
||
|
- (1u << NM_VECTOR) | (1u << DB_VECTOR);
|
||
|
+ (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR);
|
||
|
if ((vcpu->guest_debug &
|
||
|
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
|
||
|
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP))
|
||
|
@@ -5266,6 +5266,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
|
||
|
return handle_rmode_exception(vcpu, ex_no, error_code);
|
||
|
|
||
|
switch (ex_no) {
|
||
|
+ case AC_VECTOR:
|
||
|
+ kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
|
||
|
+ return 1;
|
||
|
case DB_VECTOR:
|
||
|
dr6 = vmcs_readl(EXIT_QUALIFICATION);
|
||
|
if (!(vcpu->guest_debug &
|
||
|
--
|
||
|
2.4.3
|
||
|
|