Relax the protection against interacting with a buggy KVM to only reject ioctls if the VM is bugged, i.e. allow userspace to invoke ioctls if KVM deliberately terminated the VM. Drop kvm.vm_dead as there are no longer any readers, and KVM shouldn't rely on vm_dead for functional correctness. The only functional guarantees provided by kvm_vm_dead() come by way of KVM_REQ_VM_DEAD, which ensures that vCPU won't re-enter the guest. Practically speaking, this only affects x86, which uses kvm_vm_dead() to prevent running a VM whose resources have been partially freed or has run one or more of its vCPUs into an architecturally defined state. In these cases, there is no (known) danger to KVM, the goal is purely to prevent entering the guest. As evidenced by commit ecf371f8b02d ("KVM: SVM: Reject SEV{-ES} intra host migration if vCPU creation is in-flight"), the restriction on invoking ioctls only blocks _new_ ioctls. I.e. KVM mustn't rely on blocking ioctls for functional safety (whereas KVM_REQ_VM_DEAD is guaranteed to prevent vCPUs from entering the guest). Signed-off-by: Sean Christopherson --- arch/arm64/kvm/vgic/vgic-init.c | 2 +- include/linux/kvm_host.h | 2 -- tools/testing/selftests/kvm/x86/sev_migrate_tests.c | 5 +---- virt/kvm/kvm_main.c | 10 +++++----- 4 files changed, 7 insertions(+), 12 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c index eb1205654ac8..c2033bae73b2 100644 --- a/arch/arm64/kvm/vgic/vgic-init.c +++ b/arch/arm64/kvm/vgic/vgic-init.c @@ -612,7 +612,7 @@ int kvm_vgic_map_resources(struct kvm *kvm) mutex_unlock(&kvm->arch.config_lock); out_slots: if (ret) - kvm_vm_dead(kvm); + kvm_vm_bugged(kvm); mutex_unlock(&kvm->slots_lock); diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h index 627054d27222..fa97d71577b5 100644 --- a/include/linux/kvm_host.h +++ b/include/linux/kvm_host.h @@ -854,7 +854,6 @@ struct kvm { u32 dirty_ring_size; bool dirty_ring_with_bitmap; bool vm_bugged; - bool vm_dead; #ifdef CONFIG_HAVE_KVM_PM_NOTIFIER struct notifier_block pm_notifier; @@ -894,7 +893,6 @@ struct kvm { static inline void kvm_vm_dead(struct kvm *kvm) { - kvm->vm_dead = true; kvm_make_all_cpus_request(kvm, KVM_REQ_VM_DEAD); } diff --git a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c index 0a6dfba3905b..0580bee5888e 100644 --- a/tools/testing/selftests/kvm/x86/sev_migrate_tests.c +++ b/tools/testing/selftests/kvm/x86/sev_migrate_tests.c @@ -87,10 +87,7 @@ static void test_sev_migrate_from(bool es) sev_migrate_from(dst_vms[i], dst_vms[i - 1]); /* Migrate the guest back to the original VM. */ - ret = __sev_migrate_from(src_vm, dst_vms[NR_MIGRATE_TEST_VMS - 1]); - TEST_ASSERT(ret == -1 && errno == EIO, - "VM that was migrated from should be dead. ret %d, errno: %d", ret, - errno); + sev_migrate_from(src_vm, dst_vms[NR_MIGRATE_TEST_VMS - 1]); kvm_vm_free(src_vm); for (i = 0; i < NR_MIGRATE_TEST_VMS; ++i) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 6c07dd423458..f1f69e10a371 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -4408,7 +4408,7 @@ static long kvm_vcpu_ioctl(struct file *filp, struct kvm_fpu *fpu = NULL; struct kvm_sregs *kvm_sregs = NULL; - if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_dead) + if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_bugged) return -EIO; if (unlikely(_IOC_TYPE(ioctl) != KVMIO)) @@ -4651,7 +4651,7 @@ static long kvm_vcpu_compat_ioctl(struct file *filp, void __user *argp = compat_ptr(arg); int r; - if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_dead) + if (vcpu->kvm->mm != current->mm || vcpu->kvm->vm_bugged) return -EIO; switch (ioctl) { @@ -4717,7 +4717,7 @@ static long kvm_device_ioctl(struct file *filp, unsigned int ioctl, { struct kvm_device *dev = filp->private_data; - if (dev->kvm->mm != current->mm || dev->kvm->vm_dead) + if (dev->kvm->mm != current->mm || dev->kvm->vm_bugged) return -EIO; switch (ioctl) { @@ -5139,7 +5139,7 @@ static long kvm_vm_ioctl(struct file *filp, void __user *argp = (void __user *)arg; int r; - if (kvm->mm != current->mm || kvm->vm_dead) + if (kvm->mm != current->mm || kvm->vm_bugged) return -EIO; switch (ioctl) { case KVM_CREATE_VCPU: @@ -5403,7 +5403,7 @@ static long kvm_vm_compat_ioctl(struct file *filp, struct kvm *kvm = filp->private_data; int r; - if (kvm->mm != current->mm || kvm->vm_dead) + if (kvm->mm != current->mm || kvm->vm_bugged) return -EIO; r = kvm_arch_vm_compat_ioctl(filp, ioctl, arg); -- 2.50.1.552.g942d659e1b-goog