1 commit 54a20552e1eae07aa240fa370a0293e006b5faed
2 Author: Eric Northup <digitaleric@google.com>
3 Date: Tue Nov 3 18:03:53 2015 +0100
5 KVM: x86: work around infinite loop in microcode when #AC is delivered
7 It was found that a guest can DoS a host by triggering an infinite
8 stream of "alignment check" (#AC) exceptions. This causes the
9 microcode to enter an infinite loop where the core never receives
10 another interrupt. The host kernel panics pretty quickly due to the
11 effects (CVE-2015-5307).
13 Signed-off-by: Eric Northup <digitaleric@google.com>
14 Cc: stable@vger.kernel.org
15 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
17 diff --git a/arch/x86/include/asm/kvm.h b/arch/x86/include/asm/kvm.h
18 --- a/arch/x86/include/asm/kvm.h
19 +++ b/arch/x86/include/asm/kvm.h
27 /* Select x86 specific features in <linux/kvm.h> */
28 diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h
29 index b5d7640..8a4add8 100644
30 --- a/arch/x86/include/asm/svm.h
31 +++ b/arch/x86/include/asm/svm.h
33 { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
34 { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
35 { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \
36 + { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \
37 { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \
38 { SVM_EXIT_INTR, "interrupt" }, \
39 { SVM_EXIT_NMI, "nmi" }, \
40 diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
41 index f2ba919..1839264 100644
42 --- a/arch/x86/kvm/svm.c
43 +++ b/arch/x86/kvm/svm.c
44 @@ -1019,7 +1019,8 @@ static void init_vmcb(struct vcpu_svm *svm)
46 control->intercept_exceptions = (1 << PF_VECTOR) |
52 control->intercept = (1ULL << INTERCEPT_INTR) |
53 (1ULL << INTERCEPT_NMI) |
54 @@ -1707,6 +1708,12 @@ static int ud_interception(struct vcpu_svm *svm)
58 +static int ac_interception(struct vcpu_svm *svm)
60 + kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0);
64 static int nm_interception(struct vcpu_svm *svm)
66 svm->vmcb->control.intercept_exceptions &= ~(1 << NM_VECTOR);
67 @@ -3270,6 +3277,7 @@ static int (*const svm_exit_handlers[])(struct vcpu_svm *svm) = {
68 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception,
69 [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
70 [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
71 + [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
72 [SVM_EXIT_INTR] = intr_interception,
73 [SVM_EXIT_NMI] = nmi_interception,
74 [SVM_EXIT_SMI] = nop_on_interception,
75 diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
76 index b765b03..89aaedd 100644
77 --- a/arch/x86/kvm/vmx.c
78 +++ b/arch/x86/kvm/vmx.c
79 @@ -1639,7 +1639,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
82 eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR)
83 - | (1u << NM_VECTOR);
84 + | (1u << NM_VECTOR) | (1u << AC_VECTOR);
86 * Unconditionally intercept #DB so we can maintain dr6 without
87 * reading it every exit.
88 @@ -5261,6 +5261,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
89 return handle_rmode_exception(vcpu, ex_no, error_code);
93 + kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
96 dr6 = vmcs_readl(EXIT_QUALIFICATION);
97 if (!(vcpu->guest_debug &