| From 53936b5bf35e140ae27e4bbf0447a61063f400da Mon Sep 17 00:00:00 2001 |
| From: Thomas Huth <thuth@redhat.com> |
| Date: Thu, 12 Sep 2019 13:54:38 +0200 |
| Subject: KVM: s390: Do not leak kernel stack data in the KVM_S390_INTERRUPT ioctl |
| |
| From: Thomas Huth <thuth@redhat.com> |
| |
| commit 53936b5bf35e140ae27e4bbf0447a61063f400da upstream. |
| |
| When the userspace program runs the KVM_S390_INTERRUPT ioctl to inject |
| an interrupt, we convert them from the legacy struct kvm_s390_interrupt |
| to the new struct kvm_s390_irq via the s390int_to_s390irq() function. |
| However, this function does not take care of all types of interrupts |
| that we can inject into the guest later (see do_inject_vcpu()). Since we |
| do not clear out the s390irq values before calling s390int_to_s390irq(), |
| there is a chance that we copy random data from the kernel stack which |
| could be leaked to the userspace later. |
| |
| Specifically, the problem exists with the KVM_S390_INT_PFAULT_INIT |
| interrupt: s390int_to_s390irq() does not handle it, and the function |
| __inject_pfault_init() later copies irq->u.ext which contains the |
| random kernel stack data. This data can then be leaked either to |
| the guest memory in __deliver_pfault_init(), or the userspace might |
| retrieve it directly with the KVM_S390_GET_IRQ_STATE ioctl. |
| |
| Fix it by handling that interrupt type in s390int_to_s390irq(), too, |
| and by making sure that the s390irq struct is properly pre-initialized. |
| And while we're at it, make sure that s390int_to_s390irq() now |
| directly returns -EINVAL for unknown interrupt types, so that we |
| immediately get a proper error code in case we add more interrupt |
| types to do_inject_vcpu() without updating s390int_to_s390irq() |
| sometime in the future. |
| |
| Cc: stable@vger.kernel.org |
| Reviewed-by: David Hildenbrand <david@redhat.com> |
| Reviewed-by: Christian Borntraeger <borntraeger@de.ibm.com> |
| Reviewed-by: Janosch Frank <frankja@linux.ibm.com> |
| Signed-off-by: Thomas Huth <thuth@redhat.com> |
| Link: https://lore.kernel.org/kvm/20190912115438.25761-1-thuth@redhat.com |
| Signed-off-by: Christian Borntraeger <borntraeger@de.ibm.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/s390/kvm/interrupt.c | 10 ++++++++++ |
| arch/s390/kvm/kvm-s390.c | 2 +- |
| 2 files changed, 11 insertions(+), 1 deletion(-) |
| |
| --- a/arch/s390/kvm/interrupt.c |
| +++ b/arch/s390/kvm/interrupt.c |
| @@ -1701,6 +1701,16 @@ int s390int_to_s390irq(struct kvm_s390_i |
| case KVM_S390_MCHK: |
| irq->u.mchk.mcic = s390int->parm64; |
| break; |
| + case KVM_S390_INT_PFAULT_INIT: |
| + irq->u.ext.ext_params = s390int->parm; |
| + irq->u.ext.ext_params2 = s390int->parm64; |
| + break; |
| + case KVM_S390_RESTART: |
| + case KVM_S390_INT_CLOCK_COMP: |
| + case KVM_S390_INT_CPU_TIMER: |
| + break; |
| + default: |
| + return -EINVAL; |
| } |
| return 0; |
| } |
| --- a/arch/s390/kvm/kvm-s390.c |
| +++ b/arch/s390/kvm/kvm-s390.c |
| @@ -3730,7 +3730,7 @@ long kvm_arch_vcpu_ioctl(struct file *fi |
| } |
| case KVM_S390_INTERRUPT: { |
| struct kvm_s390_interrupt s390int; |
| - struct kvm_s390_irq s390irq; |
| + struct kvm_s390_irq s390irq = {}; |
| |
| r = -EFAULT; |
| if (copy_from_user(&s390int, argp, sizeof(s390int))) |