Re: [PATCH 2/2] KVM: SVM: Re-check enc_context_owner under the owner's lock in sev_vm_destroy()
Paolo Bonzini <[email protected]>
| Newsgroups | org.kernel.vger.kvm |
|---|---|
| Message-ID | <[email protected]> |
On 8/4/26 17:00, Shen Yongchao wrote:
> sev_vm_destroy() reads the mirror KVM's enc_context_owner without any
> synchronization and then locks the returned KVM. A concurrent
> KVM_SEV_MIGRATE_VM (sev_migrate_from()) transfers this mirror's
> reference to a new owner under the current owner's lock, so the
> previous owner can be freed between the unlocked read and
> mutex_lock(): the mirror's final reference can be dropped while
> sev_vm_destroy() is about to dereference the owner, dropping the
> owner's reference count below its true value so that kvm_destroy_vm()
> runs while the owner's fd is still open.
>
> All kernels with SEV mirroring and intra-host migration support
> (KVM_SEV_MIRROR_CREATE / KVM_SEV_MIGRATE_VM) are affected. The mirror
> list mechanism was introduced by commit b2125513dfc0 ("KVM: SEV: Allow
> SEV intra-host migration of VM with mirrors", v5.18, 2022-02-18);
> upstream mainline is unfixed as of 2026-08-04. Triggering requires an
> AMD SEV-capable host with CONFIG_KVM_AMD_SEV and a local user able to
> create an SEV VM plus an SEV mirror VM, racing close() of the mirror
> against KVM_SEV_MIGRATE_VM on the owner (function-level window,
> deterministically reachable with a close(fd) primitive).
>
> Take the owner's lock and re-check enc_context_owner: if it changed,
> the migration already moved the mirror entry and the reference to the
> new owner, so retry with the new owner. The owner cannot be freed
> while the mirror holds a reference to it, or while a migration that
> takes the reference over holds the owner's file reference.
The problem is that the *old* owner can be freed between READ_ONCE() and
mutex_lock().
The patch narrows the window, but the cleanest fix for both issues is to
stop protecting enc_context_owner/mirror_vms with the owner's kvm->lock,
and use a global lock instead. This also fixes the other issue, so I'll
send a patch.
Paolo