]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
KVM: x86: work around infinite loop in microcode when #AC is delivered
authorEric Northup <digitaleric@google.com>
Tue, 3 Nov 2015 17:03:53 +0000 (18:03 +0100)
committerZefan Li <lizefan@huawei.com>
Mon, 21 Mar 2016 01:17:55 +0000 (09:17 +0800)
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>
[lizf: Backported to 3.4:
 - adjust filename
 - adjust context
 - add definition of AC_VECTOR]
Signed-off-by: Zefan Li <lizefan@huawei.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/svm.c
arch/x86/kvm/trace.h
arch/x86/kvm/vmx.c

index d60facb1a9d484eedbf374aa94236fed3962b171..493b0267f23e8e68d864399ce70c1b38a4c84cf2 100644 (file)
@@ -87,6 +87,7 @@
 #define GP_VECTOR 13
 #define PF_VECTOR 14
 #define MF_VECTOR 16
+#define AC_VECTOR 17
 #define MC_VECTOR 18
 
 #define SELECTOR_TI_MASK (1 << 2)
index 86c74c0cd876fe4305abd8a3290a636c08d35385..56dd88ab65b86181c12fbbecc4ee7350f5af5568 100644 (file)
@@ -1081,6 +1081,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);
@@ -1776,6 +1777,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);
@@ -3291,6 +3298,7 @@ static int (*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,
index 911d2641f14c5cba355abc25e00f38f07ced1df9..d26a7e24464e66eded8182235b65142239330bcf 100644 (file)
@@ -244,6 +244,7 @@ TRACE_EVENT(kvm_apic,
        { 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" }, \
index 4ad0d7171d6cf3b0e67c8433bd371bf7af552352..defd510486fd7b6bff4923dbb21776e6d9018c9b 100644 (file)
@@ -1169,7 +1169,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))
@@ -4260,6 +4260,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
 
        ex_no = intr_info & INTR_INFO_VECTOR_MASK;
        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 &