diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2021-11-22 19:50:36 -0500 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2021-11-30 03:54:15 -0500 |
commit | c9d61dcb0bc26a761dc84a87bd8a0d3b3c432f10 (patch) | |
tree | c58760947e78c0658a2222eefdeff70d7baab596 | |
parent | 10a37929efeb4c51a0069afdd537c4fa3831f6e5 (diff) |
KVM: SEV: accept signals in sev_lock_two_vms
Generally, kvm->lock is not taken for a long time, but
sev_lock_two_vms is different: it takes vCPU locks
inside, so userspace can hold it back just by calling
a vCPU ioctl. Play it safe and use mutex_lock_killable.
Message-Id: <20211123005036.2954379-13-pbonzini@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/svm/sev.c | 22 |
1 files changed, 16 insertions, 6 deletions
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index bbbf980c7e40..59727a966f90 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -1547,6 +1547,7 @@ static int sev_lock_two_vms(struct kvm *dst_kvm, struct kvm *src_kvm) { struct kvm_sev_info *dst_sev = &to_kvm_svm(dst_kvm)->sev_info; struct kvm_sev_info *src_sev = &to_kvm_svm(src_kvm)->sev_info; + int r = -EBUSY; if (dst_kvm == src_kvm) return -EINVAL; @@ -1558,14 +1559,23 @@ static int sev_lock_two_vms(struct kvm *dst_kvm, struct kvm *src_kvm) if (atomic_cmpxchg_acquire(&dst_sev->migration_in_progress, 0, 1)) return -EBUSY; - if (atomic_cmpxchg_acquire(&src_sev->migration_in_progress, 0, 1)) { - atomic_set_release(&dst_sev->migration_in_progress, 0); - return -EBUSY; - } + if (atomic_cmpxchg_acquire(&src_sev->migration_in_progress, 0, 1)) + goto release_dst; - mutex_lock(&dst_kvm->lock); - mutex_lock(&src_kvm->lock); + r = -EINTR; + if (mutex_lock_killable(&dst_kvm->lock)) + goto release_src; + if (mutex_lock_killable(&src_kvm->lock)) + goto unlock_dst; return 0; + +unlock_dst: + mutex_unlock(&dst_kvm->lock); +release_src: + atomic_set_release(&src_sev->migration_in_progress, 0); +release_dst: + atomic_set_release(&dst_sev->migration_in_progress, 0); + return r; } static void sev_unlock_two_vms(struct kvm *dst_kvm, struct kvm *src_kvm) |