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>
This commit is contained in:
		
							parent
							
								
									d0e536d893
								
							
						
					
					
						commit
						54a20552e1
					
				| @ -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" }, \ | ||||
|  | ||||
| @ -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, | ||||
|  | ||||
| @ -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 & | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user