Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Eric Northup and committed by
Paolo Bonzini
54a20552 d0e536d8

+13 -1
+1
arch/x86/include/uapi/asm/svm.h
··· 100 100 { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ 101 101 { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ 102 102 { SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM excp" }, \ 103 + { SVM_EXIT_EXCP_BASE + AC_VECTOR, "AC excp" }, \ 103 104 { SVM_EXIT_EXCP_BASE + MC_VECTOR, "MC excp" }, \ 104 105 { SVM_EXIT_INTR, "interrupt" }, \ 105 106 { SVM_EXIT_NMI, "nmi" }, \
+8
arch/x86/kvm/svm.c
··· 1019 1019 set_exception_intercept(svm, PF_VECTOR); 1020 1020 set_exception_intercept(svm, UD_VECTOR); 1021 1021 set_exception_intercept(svm, MC_VECTOR); 1022 + set_exception_intercept(svm, AC_VECTOR); 1022 1023 1023 1024 set_intercept(svm, INTERCEPT_INTR); 1024 1025 set_intercept(svm, INTERCEPT_NMI); ··· 1705 1704 er = emulate_instruction(&svm->vcpu, EMULTYPE_TRAP_UD); 1706 1705 if (er != EMULATE_DONE) 1707 1706 kvm_queue_exception(&svm->vcpu, UD_VECTOR); 1707 + return 1; 1708 + } 1709 + 1710 + static int ac_interception(struct vcpu_svm *svm) 1711 + { 1712 + kvm_queue_exception_e(&svm->vcpu, AC_VECTOR, 0); 1708 1713 return 1; 1709 1714 } 1710 1715 ··· 3277 3270 [SVM_EXIT_EXCP_BASE + PF_VECTOR] = pf_interception, 3278 3271 [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception, 3279 3272 [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception, 3273 + [SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception, 3280 3274 [SVM_EXIT_INTR] = intr_interception, 3281 3275 [SVM_EXIT_NMI] = nmi_interception, 3282 3276 [SVM_EXIT_SMI] = nop_on_interception,
+4 -1
arch/x86/kvm/vmx.c
··· 1639 1639 u32 eb; 1640 1640 1641 1641 eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) | 1642 - (1u << NM_VECTOR) | (1u << DB_VECTOR); 1642 + (1u << NM_VECTOR) | (1u << DB_VECTOR) | (1u << AC_VECTOR); 1643 1643 if ((vcpu->guest_debug & 1644 1644 (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) == 1645 1645 (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ··· 5261 5261 return handle_rmode_exception(vcpu, ex_no, error_code); 5262 5262 5263 5263 switch (ex_no) { 5264 + case AC_VECTOR: 5265 + kvm_queue_exception_e(vcpu, AC_VECTOR, error_code); 5266 + return 1; 5264 5267 case DB_VECTOR: 5265 5268 dr6 = vmcs_readl(EXIT_QUALIFICATION); 5266 5269 if (!(vcpu->guest_debug &