Commit e1b6c3c9 authored by Eric Northup's avatar Eric Northup Committed by Zefan Li

KVM: x86: work around infinite loop in microcode when #AC is delivered

commit 54a20552 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: default avatarEric Northup <digitaleric@google.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
[lizf: Backported to 3.4:
 - adjust filename
 - adjust context
 - add definition of AC_VECTOR]
Signed-off-by: default avatarZefan Li <lizefan@huawei.com>
parent 59c8392f
...@@ -87,6 +87,7 @@ ...@@ -87,6 +87,7 @@
#define GP_VECTOR 13 #define GP_VECTOR 13
#define PF_VECTOR 14 #define PF_VECTOR 14
#define MF_VECTOR 16 #define MF_VECTOR 16
#define AC_VECTOR 17
#define MC_VECTOR 18 #define MC_VECTOR 18
#define SELECTOR_TI_MASK (1 << 2) #define SELECTOR_TI_MASK (1 << 2)
......
...@@ -1081,6 +1081,7 @@ static void init_vmcb(struct vcpu_svm *svm) ...@@ -1081,6 +1081,7 @@ static void init_vmcb(struct vcpu_svm *svm)
set_exception_intercept(svm, PF_VECTOR); set_exception_intercept(svm, PF_VECTOR);
set_exception_intercept(svm, UD_VECTOR); set_exception_intercept(svm, UD_VECTOR);
set_exception_intercept(svm, MC_VECTOR); set_exception_intercept(svm, MC_VECTOR);
set_exception_intercept(svm, AC_VECTOR);
set_intercept(svm, INTERCEPT_INTR); set_intercept(svm, INTERCEPT_INTR);
set_intercept(svm, INTERCEPT_NMI); set_intercept(svm, INTERCEPT_NMI);
...@@ -1776,6 +1777,12 @@ static int ud_interception(struct vcpu_svm *svm) ...@@ -1776,6 +1777,12 @@ static int ud_interception(struct vcpu_svm *svm)
return 1; 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) static void svm_fpu_activate(struct kvm_vcpu *vcpu)
{ {
struct vcpu_svm *svm = to_svm(vcpu); struct vcpu_svm *svm = to_svm(vcpu);
...@@ -3291,6 +3298,7 @@ static int (*svm_exit_handlers[])(struct vcpu_svm *svm) = { ...@@ -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 + PF_VECTOR] = pf_interception,
[SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception, [SVM_EXIT_EXCP_BASE + NM_VECTOR] = nm_interception,
[SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception, [SVM_EXIT_EXCP_BASE + MC_VECTOR] = mc_interception,
[SVM_EXIT_EXCP_BASE + AC_VECTOR] = ac_interception,
[SVM_EXIT_INTR] = intr_interception, [SVM_EXIT_INTR] = intr_interception,
[SVM_EXIT_NMI] = nmi_interception, [SVM_EXIT_NMI] = nmi_interception,
[SVM_EXIT_SMI] = nop_on_interception, [SVM_EXIT_SMI] = nop_on_interception,
......
...@@ -244,6 +244,7 @@ TRACE_EVENT(kvm_apic, ...@@ -244,6 +244,7 @@ TRACE_EVENT(kvm_apic,
{ SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \ { SVM_EXIT_EXCP_BASE + UD_VECTOR, "UD excp" }, \
{ SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \ { SVM_EXIT_EXCP_BASE + PF_VECTOR, "PF excp" }, \
{ SVM_EXIT_EXCP_BASE + NM_VECTOR, "NM 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_EXCP_BASE + MC_VECTOR, "MC excp" }, \
{ SVM_EXIT_INTR, "interrupt" }, \ { SVM_EXIT_INTR, "interrupt" }, \
{ SVM_EXIT_NMI, "nmi" }, \ { SVM_EXIT_NMI, "nmi" }, \
......
...@@ -1169,7 +1169,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu) ...@@ -1169,7 +1169,7 @@ static void update_exception_bitmap(struct kvm_vcpu *vcpu)
u32 eb; u32 eb;
eb = (1u << PF_VECTOR) | (1u << UD_VECTOR) | (1u << MC_VECTOR) | 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 & if ((vcpu->guest_debug &
(KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) == (KVM_GUESTDBG_ENABLE | KVM_GUESTDBG_USE_SW_BP)) ==
(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) ...@@ -4260,6 +4260,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
ex_no = intr_info & INTR_INFO_VECTOR_MASK; ex_no = intr_info & INTR_INFO_VECTOR_MASK;
switch (ex_no) { switch (ex_no) {
case AC_VECTOR:
kvm_queue_exception_e(vcpu, AC_VECTOR, error_code);
return 1;
case DB_VECTOR: case DB_VECTOR:
dr6 = vmcs_readl(EXIT_QUALIFICATION); dr6 = vmcs_readl(EXIT_QUALIFICATION);
if (!(vcpu->guest_debug & if (!(vcpu->guest_debug &
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment