Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 54a20552 authored by Eric Northup's avatar Eric Northup Committed by Paolo Bonzini
Browse files

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: default avatarEric Northup <digitaleric@google.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent d0e536d8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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" }, \
+8 −0
Original line number Diff line number Diff line
@@ -1019,6 +1019,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);
@@ -1707,6 +1708,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);
@@ -3270,6 +3277,7 @@ static int (*const 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,
+4 −1
Original line number Diff line number Diff line
@@ -1639,7 +1639,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))
@@ -5261,6 +5261,9 @@ static int handle_exception(struct kvm_vcpu *vcpu)
		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 &