Commit 15462e37 authored by David Hildenbrand's avatar David Hildenbrand Committed by Christian Borntraeger

KVM: s390: reinjection of irqs can fail in the tpi handler

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: default avatarDavid Hildenbrand <dahi@linux.vnet.ibm.com>
Cc: stable@vger.kernel.org # 3.16+
Signed-off-by: default avatarChristian Borntraeger <borntraeger@de.ibm.com>
parent 261520dc
...@@ -1332,10 +1332,10 @@ int kvm_s390_inject_vm(struct kvm *kvm, ...@@ -1332,10 +1332,10 @@ int kvm_s390_inject_vm(struct kvm *kvm,
return rc; 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) struct kvm_s390_interrupt_info *inti)
{ {
__inject_vm(kvm, inti); return __inject_vm(kvm, inti);
} }
int s390int_to_s390irq(struct kvm_s390_interrupt *s390int, int s390int_to_s390irq(struct kvm_s390_interrupt *s390int,
......
...@@ -151,8 +151,8 @@ int __must_check kvm_s390_inject_vcpu(struct kvm_vcpu *vcpu, ...@@ -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); 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, struct kvm_s390_interrupt_info *kvm_s390_get_io_int(struct kvm *kvm,
u64 cr6, u64 schid); u64 cr6, u64 schid);
void kvm_s390_reinject_io_int(struct kvm *kvm, int kvm_s390_reinject_io_int(struct kvm *kvm,
struct kvm_s390_interrupt_info *inti); struct kvm_s390_interrupt_info *inti);
int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked); int kvm_s390_mask_adapter(struct kvm *kvm, unsigned int id, bool masked);
/* implemented in intercept.c */ /* implemented in intercept.c */
......
...@@ -279,7 +279,10 @@ static int handle_tpi(struct kvm_vcpu *vcpu) ...@@ -279,7 +279,10 @@ static int handle_tpi(struct kvm_vcpu *vcpu)
* instruction is suppressed from the guest's view: reinject the * instruction is suppressed from the guest's view: reinject the
* interrupt. * 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 */ /* don't set the cc, a pgm irq was injected or we drop to user space */
return rc ? -EFAULT : 0; return rc ? -EFAULT : 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment