KVM: Close minor race in signal handling
authorAvi Kivity <avi@qumranet.com>
Wed, 15 Aug 2007 12:23:34 +0000 (15:23 +0300)
committerAvi Kivity <avi@qumranet.com>
Sat, 13 Oct 2007 08:18:23 +0000 (10:18 +0200)
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>
drivers/kvm/svm.c
drivers/kvm/vmx.c

index e3c6d891326b8f70f408c0143e3a71f7849e4517..cc674bfd31d9338a7eb79986e4d84c888f66a710 100644 (file)
@@ -1398,11 +1398,19 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        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 @@ static int svm_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        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);
index 906d4fa13d101f59100ad38f16423ae44cd12f01..a9b4cb51dec8638de9327ec2d37cedc8d6a3c915 100644 (file)
@@ -2066,9 +2066,6 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        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 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        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 @@ static int vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
        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;