소스 검색

KVM: Close minor race in signal handling

We need to check for signals inside the critical section, otherwise a
signal can be sent which we will not notice.  Also move the check
before entry, so that if the signal happens before the first entry,
we exit immediately instead of waiting for something to happen to the
guest.

Signed-off-by: Avi Kivity <avi@qumranet.com>
Avi Kivity 18 년 전
부모
커밋
7e66f350cf
2개의 변경된 파일22개의 추가작업 그리고 20개의 파일을 삭제
  1. 10 9
      drivers/kvm/svm.c
  2. 12 11
      drivers/kvm/vmx.c

+ 10 - 9
drivers/kvm/svm.c

@@ -1398,11 +1398,19 @@ again:
 	if (unlikely(r))
 		return r;
 
+	clgi();
+
+	if (signal_pending(current)) {
+		stgi();
+		++vcpu->stat.signal_exits;
+		post_kvm_run_save(svm, kvm_run);
+		kvm_run->exit_reason = KVM_EXIT_INTR;
+		return -EINTR;
+	}
+
 	if (!vcpu->mmio_read_completed)
 		do_interrupt_requests(svm, kvm_run);
 
-	clgi();
-
 	vcpu->guest_mode = 1;
 	if (vcpu->requests)
 		if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests))
@@ -1582,13 +1590,6 @@ again:
 
 	r = handle_exit(svm, kvm_run);
 	if (r > 0) {
-		if (signal_pending(current)) {
-			++vcpu->stat.signal_exits;
-			post_kvm_run_save(svm, kvm_run);
-			kvm_run->exit_reason = KVM_EXIT_INTR;
-			return -EINTR;
-		}
-
 		if (dm_request_for_irq_injection(svm, kvm_run)) {
 			++vcpu->stat.request_irq_exits;
 			post_kvm_run_save(svm, kvm_run);

+ 12 - 11
drivers/kvm/vmx.c

@@ -2066,9 +2066,6 @@ again:
 
 	preempt_disable();
 
-	if (!vcpu->mmio_read_completed)
-		do_interrupt_requests(vcpu, kvm_run);
-
 	vmx_save_host_state(vmx);
 	kvm_load_guest_fpu(vcpu);
 
@@ -2079,6 +2076,18 @@ again:
 
 	local_irq_disable();
 
+	if (signal_pending(current)) {
+		local_irq_enable();
+		preempt_enable();
+		r = -EINTR;
+		kvm_run->exit_reason = KVM_EXIT_INTR;
+		++vcpu->stat.signal_exits;
+		goto out;
+	}
+
+	if (!vcpu->mmio_read_completed)
+		do_interrupt_requests(vcpu, kvm_run);
+
 	vcpu->guest_mode = 1;
 	if (vcpu->requests)
 		if (test_and_clear_bit(KVM_TLB_FLUSH, &vcpu->requests))
@@ -2227,14 +2236,6 @@ again:
 
 	r = kvm_handle_exit(kvm_run, vcpu);
 	if (r > 0) {
-		/* Give scheduler a change to reschedule. */
-		if (signal_pending(current)) {
-			r = -EINTR;
-			kvm_run->exit_reason = KVM_EXIT_INTR;
-			++vcpu->stat.signal_exits;
-			goto out;
-		}
-
 		if (dm_request_for_irq_injection(vcpu, kvm_run)) {
 			r = -EINTR;
 			kvm_run->exit_reason = KVM_EXIT_INTR;