]> Git Repo - linux.git/commitdiff
Merge tag 'kvm-s390-master-4.15-3' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorRadim Krčmář <[email protected]>
Wed, 24 Jan 2018 15:25:53 +0000 (16:25 +0100)
committerRadim Krčmář <[email protected]>
Wed, 24 Jan 2018 15:25:53 +0000 (16:25 +0100)
KVM: s390: another fix for cmma migration

This fixes races and potential use after free in the
cmma migration code.

1  2 
arch/s390/kvm/kvm-s390.c

diff --combined arch/s390/kvm/kvm-s390.c
index 2598cf243b86e08f21ccb6f9ae6ea2e28465d680,52880e980a336a80263cd83c70aeabaad6726ea1..1371dff2b90d14244a52da555d9d4914a1be2f45
@@@ -421,9 -421,6 +421,9 @@@ int kvm_vm_ioctl_check_extension(struc
        case KVM_CAP_S390_GS:
                r = test_facility(133);
                break;
 +      case KVM_CAP_S390_BPB:
 +              r = test_facility(82);
 +              break;
        default:
                r = 0;
        }
@@@ -769,7 -766,7 +769,7 @@@ static void kvm_s390_sync_request_broad
  
  /*
   * Must be called with kvm->srcu held to avoid races on memslots, and with
-  * kvm->lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
+  * kvm->slots_lock to avoid races with ourselves and kvm_s390_vm_stop_migration.
   */
  static int kvm_s390_vm_start_migration(struct kvm *kvm)
  {
  }
  
  /*
-  * Must be called with kvm->lock to avoid races with ourselves and
+  * Must be called with kvm->slots_lock to avoid races with ourselves and
   * kvm_s390_vm_start_migration.
   */
  static int kvm_s390_vm_stop_migration(struct kvm *kvm)
  
        if (kvm->arch.use_cmma) {
                kvm_s390_sync_request_broadcast(kvm, KVM_REQ_STOP_MIGRATION);
+               /* We have to wait for the essa emulation to finish */
+               synchronize_srcu(&kvm->srcu);
                vfree(mgs->pgste_bitmap);
        }
        kfree(mgs);
  static int kvm_s390_vm_set_migration(struct kvm *kvm,
                                     struct kvm_device_attr *attr)
  {
-       int idx, res = -ENXIO;
+       int res = -ENXIO;
  
-       mutex_lock(&kvm->lock);
+       mutex_lock(&kvm->slots_lock);
        switch (attr->attr) {
        case KVM_S390_VM_MIGRATION_START:
-               idx = srcu_read_lock(&kvm->srcu);
                res = kvm_s390_vm_start_migration(kvm);
-               srcu_read_unlock(&kvm->srcu, idx);
                break;
        case KVM_S390_VM_MIGRATION_STOP:
                res = kvm_s390_vm_stop_migration(kvm);
        default:
                break;
        }
-       mutex_unlock(&kvm->lock);
+       mutex_unlock(&kvm->slots_lock);
  
        return res;
  }
@@@ -1754,7 -1751,9 +1754,9 @@@ long kvm_arch_vm_ioctl(struct file *fil
                r = -EFAULT;
                if (copy_from_user(&args, argp, sizeof(args)))
                        break;
+               mutex_lock(&kvm->slots_lock);
                r = kvm_s390_get_cmma_bits(kvm, &args);
+               mutex_unlock(&kvm->slots_lock);
                if (!r) {
                        r = copy_to_user(argp, &args, sizeof(args));
                        if (r)
                r = -EFAULT;
                if (copy_from_user(&args, argp, sizeof(args)))
                        break;
+               mutex_lock(&kvm->slots_lock);
                r = kvm_s390_set_cmma_bits(kvm, &args);
+               mutex_unlock(&kvm->slots_lock);
                break;
        }
        default:
@@@ -2201,8 -2202,6 +2205,8 @@@ int kvm_arch_vcpu_init(struct kvm_vcpu 
        kvm_s390_set_prefix(vcpu, 0);
        if (test_kvm_facility(vcpu->kvm, 64))
                vcpu->run->kvm_valid_regs |= KVM_SYNC_RICCB;
 +      if (test_kvm_facility(vcpu->kvm, 82))
 +              vcpu->run->kvm_valid_regs |= KVM_SYNC_BPBC;
        if (test_kvm_facility(vcpu->kvm, 133))
                vcpu->run->kvm_valid_regs |= KVM_SYNC_GSCB;
        /* fprs can be synchronized via vrs, even if the guest has no vx. With
@@@ -2344,7 -2343,6 +2348,7 @@@ static void kvm_s390_vcpu_initial_reset
        current->thread.fpu.fpc = 0;
        vcpu->arch.sie_block->gbea = 1;
        vcpu->arch.sie_block->pp = 0;
 +      vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
        vcpu->arch.pfault_token = KVM_S390_PFAULT_TOKEN_INVALID;
        kvm_clear_async_pf_completion_queue(vcpu);
        if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm))
@@@ -3304,11 -3302,6 +3308,11 @@@ static void sync_regs(struct kvm_vcpu *
                vcpu->arch.sie_block->ecd |= ECD_HOSTREGMGMT;
                vcpu->arch.gs_enabled = 1;
        }
 +      if ((kvm_run->kvm_dirty_regs & KVM_SYNC_BPBC) &&
 +          test_kvm_facility(vcpu->kvm, 82)) {
 +              vcpu->arch.sie_block->fpf &= ~FPF_BPBC;
 +              vcpu->arch.sie_block->fpf |= kvm_run->s.regs.bpbc ? FPF_BPBC : 0;
 +      }
        save_access_regs(vcpu->arch.host_acrs);
        restore_access_regs(vcpu->run->s.regs.acrs);
        /* save host (userspace) fprs/vrs */
@@@ -3355,7 -3348,6 +3359,7 @@@ static void store_regs(struct kvm_vcpu 
        kvm_run->s.regs.pft = vcpu->arch.pfault_token;
        kvm_run->s.regs.pfs = vcpu->arch.pfault_select;
        kvm_run->s.regs.pfc = vcpu->arch.pfault_compare;
 +      kvm_run->s.regs.bpbc = (vcpu->arch.sie_block->fpf & FPF_BPBC) == FPF_BPBC;
        save_access_regs(vcpu->run->s.regs.acrs);
        restore_access_regs(vcpu->arch.host_acrs);
        /* Save guest register state */
  int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
  {
        int rc;
 -      sigset_t sigsaved;
  
        if (kvm_run->immediate_exit)
                return -EINTR;
                return 0;
        }
  
 -      if (vcpu->sigset_active)
 -              sigprocmask(SIG_SETMASK, &vcpu->sigset, &sigsaved);
 +      kvm_sigset_activate(vcpu);
  
        if (!kvm_s390_user_cpu_state_ctrl(vcpu->kvm)) {
                kvm_s390_vcpu_start(vcpu);
        disable_cpu_timer_accounting(vcpu);
        store_regs(vcpu, kvm_run);
  
 -      if (vcpu->sigset_active)
 -              sigprocmask(SIG_SETMASK, &sigsaved, NULL);
 +      kvm_sigset_deactivate(vcpu);
  
        vcpu->stat.exit_userspace++;
        return rc;
This page took 0.067614 seconds and 4 git commands to generate.