| From 54a20552e1eae07aa240fa370a0293e006b5faed Mon Sep 17 00:00:00 2001 |
| From: Eric Northup <digitaleric@google.com> |
| Date: Tue, 3 Nov 2015 18:03:53 +0100 |
| Subject: KVM: x86: work around infinite loop in microcode when #AC is delivered |
| |
| From: Eric Northup <digitaleric@google.com> |
| |
| commit 54a20552e1eae07aa240fa370a0293e006b5faed upstream. |
| |
| 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> |
| Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| 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(-) |
| |
| --- 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" }, \ |
| --- a/arch/x86/kvm/svm.c |
| +++ b/arch/x86/kvm/svm.c |
| @@ -1105,6 +1105,7 @@ static void init_vmcb(struct vcpu_svm *s |
| 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); |
| @@ -1791,6 +1792,12 @@ static int ud_interception(struct vcpu_s |
| 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); |
| @@ -3361,6 +3368,7 @@ static int (*const svm_exit_handlers[])( |
| [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, |
| --- a/arch/x86/kvm/vmx.c |
| +++ b/arch/x86/kvm/vmx.c |
| @@ -1567,7 +1567,7 @@ static void update_exception_bitmap(stru |
| 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)) |
| @@ -5127,6 +5127,9 @@ static int handle_exception(struct kvm_v |
| 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 & |