]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
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)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 6 May 2015 20:01:41 +0000 (22:01 +0200)
commit 15462e37ca848abac7477dece65f8af25febd744 upstream.

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>
Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
arch/s390/kvm/interrupt.c
arch/s390/kvm/kvm-s390.h
arch/s390/kvm/priv.c

index f512cffbf84e4132ed3b91c1280a35393411c5a2..154a7b6c486a1d7c68f5bbd5921dbfb92f059ad5 100644 (file)
@@ -1287,10 +1287,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 a8f3d9b71c1159aeb35659b2a3dbbdb3cf531ee1..2c1ea12ed55d7f464f7917b2977f640dd395aa00 100644 (file)
@@ -146,8 +146,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 df2493361b6c119e78d781783728ff79f5fff19a..bc4ce47bcf76caf4d9f0b6e8521402c974e6ec5e 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;
 }