[PATCH 1/2] KVM: SVM: Serialize the owner's mirror list in sev_migrate_from()
Shen Yongchao <[email protected]> Tue, 4 Aug 2026 22:54:32 +0800
| Newsgroups | org.kernel.vger.kvm |
|---|---|
| Message-ID | <[email protected]> |
In sev_migrate_from(), when the destination KVM is a mirror, the mirror
entry is moved from the source's list to the owner's mirror_vms list
without holding the owner's lock. All other writers of the owner's
mirror list (KVM_SEV_MIRROR_CREATE, sev_vm_destroy()) serialize on the
owner's lock, so a concurrent COPY or destroy can race with
KVM_SEV_MIGRATE_VM and corrupt the list, e.g. leaving a dangling
mirror_entry that is later dereferenced.
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 SEV VMs and mirrors, racing KVM_SEV_MIGRATE_VM against
KVM_SEV_MIRROR_CREATE or mirror destroy (instruction-level window).
Take the owner's lock around the list operations. The lock is taken
after sev_lock_two_vms() and the migration_in_progress flags prevent
two migrations from interleaving. The owner is a third VM whose lock
is not held: the destination cannot already own an encryption context
(sev_vm_move_enc_context_from() rejects SEV guests as the destination,
gating on ->active), and a VM cannot be its own mirror owner. Hence
SINGLE_DEPTH_NESTING is sufficient and cannot deadlock.
This patch was drafted with AI assistance.
Fixes: b2125513dfc0 ("KVM: SEV: Allow SEV intra-host migration of VM with mirrors")
Cc: [email protected]
Assisted-by: Hermes:deepseek-v4-flash
Signed-off-by: Shen Yongchao <[email protected]>
---
Reproducer: static analysis only (no SEV-capable hardware available);
no reproducer has been run. The triggering sequence is described in
the commit message.
This issue was initially reported privately to security@; Sean
Christopherson OK'd handling it on-list.
Mitigations: none; SEV is an optional platform feature and the attack
requires a local user with SEV VM creation privileges.
arch/x86/kvm/svm/sev.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c
index 944aaea6501..4fa4e9bf408 100644
--- a/arch/x86/kvm/svm/sev.c
+++ b/arch/x86/kvm/svm/sev.c
@@ -2050,8 +2050,14 @@ static void sev_migrate_from(struct kvm *dst_kvm, struct kvm *src_kvm)
if (is_mirroring_enc_context(dst_kvm)) {
struct kvm_sev_info *owner_sev_info = to_kvm_sev_info(dst->enc_context_owner);
+ /*
+ * All other writers of the owner's mirror list (COPY,
+ * destroy) serialize on the owner's lock; do the same.
+ */
+ mutex_lock_nested(&dst->enc_context_owner->lock, SINGLE_DEPTH_NESTING);
list_del(&src->mirror_entry);
list_add_tail(&dst->mirror_entry, &owner_sev_info->mirror_vms);
+ mutex_unlock(&dst->enc_context_owner->lock);
}
kvm_for_each_vcpu(i, dst_vcpu, dst_kvm) {
--
2.43.0