OSDN Git Service

KVM: s390: Do not leak kernel stack data in the KVM_S390_INTERRUPT ioctl
[android-x86/kernel.git] / arch / s390 / kvm / kvm-s390.c
index 2032ab8..ea20b60 100644 (file)
@@ -3105,7 +3105,7 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
        }
        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)))
@@ -3288,21 +3288,28 @@ void kvm_arch_commit_memory_region(struct kvm *kvm,
                                const struct kvm_memory_slot *new,
                                enum kvm_mr_change change)
 {
-       int rc;
-
-       /* If the basics of the memslot do not change, we do not want
-        * to update the gmap. Every update causes several unnecessary
-        * segment translation exceptions. This is usually handled just
-        * fine by the normal fault handler + gmap, but it will also
-        * cause faults on the prefix page of running guest CPUs.
-        */
-       if (old->userspace_addr == mem->userspace_addr &&
-           old->base_gfn * PAGE_SIZE == mem->guest_phys_addr &&
-           old->npages * PAGE_SIZE == mem->memory_size)
-               return;
+       int rc = 0;
 
-       rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
-               mem->guest_phys_addr, mem->memory_size);
+       switch (change) {
+       case KVM_MR_DELETE:
+               rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
+                                       old->npages * PAGE_SIZE);
+               break;
+       case KVM_MR_MOVE:
+               rc = gmap_unmap_segment(kvm->arch.gmap, old->base_gfn * PAGE_SIZE,
+                                       old->npages * PAGE_SIZE);
+               if (rc)
+                       break;
+               /* FALLTHROUGH */
+       case KVM_MR_CREATE:
+               rc = gmap_map_segment(kvm->arch.gmap, mem->userspace_addr,
+                                     mem->guest_phys_addr, mem->memory_size);
+               break;
+       case KVM_MR_FLAGS_ONLY:
+               break;
+       default:
+               WARN(1, "Unknown KVM MR CHANGE: %d\n", change);
+       }
        if (rc)
                pr_warn("failed to commit memory region\n");
        return;