KVM: s390: reinjection of irqs can fail in the tpi handler
authorDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Wed, 4 Feb 2015 14:59:11 +0000 (15:59 +0100)
committerChristian Borntraeger <borntraeger@de.ibm.com>
Fri, 6 Mar 2015 12:40:37 +0000 (13:40 +0100)
The reinjection of an I/O interrupt can fail if the list is at the limit
and between the dequeue and the reinjection, another I/O interrupt is
injected (e.g. if user space floods kvm with I/O interrupts).

This patch avoids this memory leak and returns -EFAULT in this special
case. This error is not recoverable, so let's fail hard. This can later
be avoided by not dequeuing the interrupt but working directly on the
locked list.

Signed-off-by: David Hildenbrand <dahi@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org # 3.16+
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c

index 073b5f387d1dd3484186dd69dcfc5aae63d90b21..e7a46e81787429a457ea835dfee5b56b19439382 100644 (file)
@@ -1332,10 +1332,10 @@ int kvm_s390_inject_vm(struct kvm *kvm,
        return rc;
 }
 
-void kvm_s390_reinject_io_int(struct kvm *kvm,
+int kvm_s390_reinject_io_int(struct kvm *kvm,
                              struct kvm_s390_interrupt_info *inti)
 {
-       __inject_vm(kvm, inti);
+       return __inject_vm(kvm, inti);
 }
 
 int s390int_to_s390irq(struct kvm_s390_interrupt *s390int,
index c34109aa552d9b1a6e5ea66f172b5c3e30ad001b..6995a3080a0e3ada9726da586e418603923fc0bd 100644 (file)
@@ -151,8 +151,8 @@ int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu,
 int __must_check kvm_s390_inject_program_int(struct kvm_vcpu *vcpu, u16 code);
 struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
                                                    u64 cr6, u64 schid);
-void kvm_s390_reinject_io_int(struct kvm *kvm,
-                             struct kvm_s390_interrupt_info *inti);
+int kvm_s390_reinject_io_int(struct kvm *kvm,
+                            struct kvm_s390_interrupt_info *inti);
 int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked);
 
 /* implemented in intercept.c */
index be7138e8435144e0188d6a827188823479291e16..b982fbca34dfa45e4c0f2a4dfa8810eb9e378ffb 100644 (file)
@@ -279,7 +279,10 @@ reinject_interrupt:
         * instruction is suppressed from the guest's view: reinject the
         * interrupt.
         */
-       kvm_s390_reinject_io_int(vcpu->kvm, inti);
+       if (kvm_s390_reinject_io_int(vcpu->kvm, inti)) {
+               kfree(inti);
+               rc = -EFAULT;
+       }
        /* don't set the cc, a pgm irq was injected or we drop to user space */
        return rc ? -EFAULT : 0;
 }