From nobody Fri Oct 2 01:10:34 2026 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9DB533B5E19 for ; Thu, 6 Aug 2026 14:51:21 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786027883; cv=none; b=LtZRGTYpWKwX0JdlgOuQYLBTc8jG7VL98tLUy9GstxT0AyvbdyKb+2wDPr3aFYTZOV+PNbtkukOnQ9qxUQX3y7sRRE/FajnVgAMPFrkKFGmtL2PutkYU67YZxe4dhasF6AwcXlYpnCDEWJBZmoaWg1xmQUr2HxnkONeIiP2/RX0= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1786027883; c=relaxed/simple; bh=JTn9s6gM2szvKxoPm3/ZyZ77FIqrcsDh6La/UymsTEY=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version; b=jpZYsjpmE2XdwnePGrHlVfqOqp2DwYj1yHBizEC6eQ2IGNDgqSQ4xCY1DUlfZ2lYa0YZ770moqR0Vgxe3ExtJsxM/WxhU7g8mz1dG6cVuXRF/6/qNJiK8rcObRG7V9pzZOa+pag6156GyBKHjELYDpYnu/vcITiSlu4D3cgv/2w= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=i9jVNOxj; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b=qoAviZB6; arc=none smtp.client-ip=170.10.133.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="i9jVNOxj"; dkim=pass (2048-bit key) header.d=redhat.com header.i=@redhat.com header.b="qoAviZB6" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1786027880; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding; bh=9UBsUkDYuwCc8pkolF5HK4/LrXTfhHoQ32/qQ5yuXRI=; b=i9jVNOxjJDZQ+UuRoAtOHo3WZESVVVmupSDrIKwKmcYe4qLcvjN8wO4ColH7XHiBL+0BGL cFhoXNknEa699a3JxExb6SnyrvHGw2a3jS8H6jIwsM0vvAYAVFhgjYqWsodBLnBJ1HYorz rsFs0bmjLEH19nkia7rN4HyilmZG4E8= Received: from mail-wr1-f72.google.com (mail-wr1-f72.google.com [209.85.221.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-646-Xl6Ps0JRMkOq885nSgTI3g-1; Thu, 06 Aug 2026 10:51:19 -0400 X-MC-Unique: Xl6Ps0JRMkOq885nSgTI3g-1 X-Mimecast-MFC-AGG-ID: Xl6Ps0JRMkOq885nSgTI3g_1786027878 Received: by mail-wr1-f72.google.com with SMTP id ffacd0b85a97d-473ac08a6a4so1600712f8f.0 for ; Thu, 06 Aug 2026 07:51:19 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=google; t=1786027878; x=1786632678; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:from:to:cc:subject:date:message-id:reply-to:content-type; bh=9UBsUkDYuwCc8pkolF5HK4/LrXTfhHoQ32/qQ5yuXRI=; b=qoAviZB63SiKNh32AsTrBK30RProA97/S5XuhvPGgWwsvADzdadOQBPln79l7tBCKt Uk8CThE3iRWIxsGVYuoL3m8j5WOtwjspgTfITb4oUM8Z0IqCjvW1NOcFvo/QU1/tVWrG vjik7pEB7nvvqJw6BchaxLRxCwd41trWGXPRhXoIe7XsVXG35lB+f68JU6JRAx4I8tuj 559MhpasJvpa/AbKLgtZjEXY8gbezHh/x1jkHKiBSOG2BXx3yJv4HrqiKaLKn8w2/14F 6qwOelGv8gwwztEX2L9gPNSxQh3ftj0QOokOg4SMuZd71k+2G/GEKeLTV+lOn9vfaHiV vgWg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1786027878; x=1786632678; h=content-transfer-encoding:mime-version:message-id:date:subject:cc :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to:content-type; bh=9UBsUkDYuwCc8pkolF5HK4/LrXTfhHoQ32/qQ5yuXRI=; b=M1zpR65yXFz5k6R/7HOJ/bCikP6010EdLux2bLEMU1noigM/rGXWXJx4GdNQty6k8K nRYqiQvnmVI5aSkPdbNMfjlS6iJf4FCiW7m3+Pn5MHrj7i1sW0RQURwNIAYY4mAEBJpP ytheyMXTkRXxb/D3FSsXXXClUCBD9F9UnLPdJanclGnj0aGXhU3y/+WH2drduIZR2+Dh oFYzdQoYds5RDtty+eUQ9mMIBhDC6ZWGhKfosUa7dZo2akLuxhdCZ91pRjBf2D9Ooofs 1/NOlPS25L1p6YCO9AUDFZUME8K0HQA4nVBWnCnB/6SyQ4zpj/TdQP7XK0siLQKucVto v6hQ== X-Gm-Message-State: AOJu0YzOjT7B4a/hAB3N3bwAKfaEL3tTkoUhyBS2Mq0oMFY5IN7ga1QE 6/42DuuSACRhQAFTr/qVijyah7mn4oyhNDPFiSjnt7OOp5E0se4My8fpQ5fRxBeoD6LeSDFHv1V l58rgqsqjEh+x0sBsJ2YGLEML/sF0gvXglPr4iMJBRsnKFoEK2fLYataBb5pDv5cSmh4AOhZvwd Z8ElwHnONDjSEjD0xskTK54B0yY0Z5wF3ScbmZ5KiNzBOMD/Z0yQ== X-Gm-Gg: AR+sD13eKXho21zzlKMc3Qxrg6T7b3x/Xse2PxbKJ/QyT8YnoLixBfRjFflD/RSovXD a5t5Nyf097arD3aPeutNM7pwFPo+5UeCnLfsCXRPj6QjshjDPmtzRBSiDNch466MjieFsi+jIHW 35SfDSwZAKlDFmVKs7j/v5AdDuo8RTanECKM0yzCfjuucOL9+SchVtAxIUIVv1VdCQVE2Gzd/bt 7whvqNlxaWGcoZpDZzRbXozuFtknjmjpK38V6axpW9mbLppRQgLoXv/ckH4x/zholvMGhWnQC4g P/bqS9UN1oJe4y8X41mGTT6NIRiD49QPRSsqYB8CVDqKoxGlLQAv/ruIYb7OhS4VzE4obCDh8AQ +mEZ015SYdNDwThQzVrkAOsJp0TT2T7shUgogiCe0BAPYcKUfg21Q5axdML6Mlv3NcupOEXF1LF 2XZsQ= X-Received: by 2002:a05:6000:60f:b0:47f:80d1:be0a with SMTP id ffacd0b85a97d-47fec634bbcmr24302561f8f.14.1786027878128; Thu, 06 Aug 2026 07:51:18 -0700 (PDT) X-Received: by 2002:a05:6000:60f:b0:47f:80d1:be0a with SMTP id ffacd0b85a97d-47fec634bbcmr24302435f8f.14.1786027877611; Thu, 06 Aug 2026 07:51:17 -0700 (PDT) Received: from [192.168.10.48] ([151.95.34.92]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-47ff7b28729sm7648431f8f.32.2026.08.06.07.51.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 06 Aug 2026 07:51:17 -0700 (PDT) From: Paolo Bonzini To: linux-kernel@vger.kernel.org, kvm@vger.kernel.org Cc: seanjc@google.com, pgonda@google.com, thomas.lendacky@amd.com, stable@vger.kernel.org, Shen Yongchao Subject: [PATCH] KVM: SVM: Serialize accesses to the owner and mirror list with separate lock Date: Thu, 6 Aug 2026 16:51:15 +0200 Message-ID: <20260806145115.2441519-1-pbonzini@redhat.com> X-Mailer: git-send-email 2.55.0 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Interaction between KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM and KVM_CAP_VM_COPY_ENC_CONTEXT_FROM can cause two separate issues: - 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 unlike other writers of the owner's mirror list (sev_vm_copy_enc_context_from(), sev_vm_destroy()). A concurrent COPY or destroy can race with sev_migrate_from() and corrupt the list. - In sev_vm_destroy(), the *owner* is still active and could receive concurrently a KVM_CAP_VM_MOVE_ENC_CONTEXT_FROM that causes sev->enc_context_owner to change. In this case the incorrect VM receives kvm_put_kvm(). The second issue needs particular care because the owner could disappear altogether (even though the race window is impossibly small) between reading it and locking it. There is thus no way to perform the checks under the owner lock without putting struct kvm under SLAB_TYPESAFE_BY_RCU (which would allow kvm_get_kvm_safe() under RCU critical section). It is much simpler to just use a global lock, since the critical sections are so small and the new lock is always a leaf lock. Fixes: b2125513dfc0 ("KVM: SEV: Allow SEV intra-host migration of VM with m= irrors") Cc: stable@vger.kernel.org Reported-by: Shen Yongchao Link: https://lore.kernel.org/kvm/tencent_625C0F42824E542C72B34733392AF2C49= 709@qq.com/ Link: https://lore.kernel.org/kvm/tencent_DDC4E4352EC91CAC05A9A8F4E55E8C967= 30A@qq.com/ Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/sev.c | 34 +++++++++++++++++++++++++--------- arch/x86/kvm/svm/svm.h | 1 + 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/arch/x86/kvm/svm/sev.c b/arch/x86/kvm/svm/sev.c index 944aaea6501f..0f0ea7896af5 100644 --- a/arch/x86/kvm/svm/sev.c +++ b/arch/x86/kvm/svm/sev.c @@ -97,6 +97,8 @@ static u64 sev_supported_vmsa_features __ro_after_init; static u8 sev_enc_bit; static DECLARE_RWSEM(sev_deactivate_lock); static DEFINE_MUTEX(sev_bitmap_lock); +/* Protects kvm_sev_info's enc_context_owner, mirror_vms and mirror_entry.= */ +static DEFINE_MUTEX(sev_mirror_lock); unsigned int max_sev_asid; static unsigned int min_sev_asid; static unsigned int max_sev_es_asid; @@ -2018,7 +2020,6 @@ static void sev_migrate_from(struct kvm *dst_kvm, str= uct kvm *src_kvm) dst->asid =3D src->asid; dst->handle =3D src->handle; dst->pages_locked =3D src->pages_locked; - dst->enc_context_owner =3D src->enc_context_owner; dst->es_active =3D src->es_active; dst->vmsa_features =3D src->vmsa_features; =20 @@ -2026,11 +2027,12 @@ static void sev_migrate_from(struct kvm *dst_kvm, s= truct kvm *src_kvm) src->active =3D false; src->handle =3D 0; src->pages_locked =3D 0; - src->enc_context_owner =3D NULL; src->es_active =3D false; =20 list_cut_before(&dst->regions_list, &src->regions_list, &src->regions_lis= t); =20 + mutex_lock(&sev_mirror_lock); + /* * If this VM has mirrors, "transfer" each mirror's refcount of the * source to the destination (this KVM). The caller holds a reference @@ -2047,12 +2049,15 @@ static void sev_migrate_from(struct kvm *dst_kvm, s= truct kvm *src_kvm) * If this VM is a mirror, remove the old mirror from the owners list * and add the new mirror to the list. */ - if (is_mirroring_enc_context(dst_kvm)) { - struct kvm_sev_info *owner_sev_info =3D to_kvm_sev_info(dst->enc_context= _owner); + if (is_mirroring_enc_context(src_kvm)) { + struct kvm_sev_info *owner_sev_info =3D to_kvm_sev_info(src->enc_context= _owner); =20 + dst->enc_context_owner =3D src->enc_context_owner; + src->enc_context_owner =3D NULL; list_del(&src->mirror_entry); list_add_tail(&dst->mirror_entry, &owner_sev_info->mirror_vms); } + mutex_unlock(&sev_mirror_lock); =20 kvm_for_each_vcpu(i, dst_vcpu, dst_kvm) { dst_svm =3D to_svm(dst_vcpu); @@ -2871,11 +2876,14 @@ int sev_vm_copy_enc_context_from(struct kvm *kvm, u= nsigned int source_fd) * disappear until we're done with it */ source_sev =3D to_kvm_sev_info(source_kvm); - kvm_get_kvm(source_kvm); - list_add_tail(&mirror_sev->mirror_entry, &source_sev->mirror_vms); =20 /* Set enc_context_owner and copy its encryption context over */ + mutex_lock(&sev_mirror_lock); + kvm_get_kvm(source_kvm); + list_add_tail(&mirror_sev->mirror_entry, &source_sev->mirror_vms); mirror_sev->enc_context_owner =3D source_kvm; + mutex_unlock(&sev_mirror_lock); + mirror_sev->active =3D true; mirror_sev->asid =3D source_sev->asid; mirror_sev->fd =3D source_sev->fd; @@ -2963,11 +2971,19 @@ void sev_vm_destroy(struct kvm *kvm) * Note, mirror VMs don't support registering encrypted regions. */ if (is_mirroring_enc_context(kvm)) { - struct kvm *owner_kvm =3D sev->enc_context_owner; + struct kvm *owner_kvm; =20 - mutex_lock(&owner_kvm->lock); + mutex_lock(&sev_mirror_lock); + owner_kvm =3D sev->enc_context_owner; list_del(&sev->mirror_entry); - mutex_unlock(&owner_kvm->lock); + sev->enc_context_owner =3D NULL; + + /* + * The reference to owner_kvm cannot move after sev_mirror_lock is + * released. Release it before kvm_put_kvm() so that owner_kvm is + * never destroyed inside sev_mirror_lock. + */ + mutex_unlock(&sev_mirror_lock); kvm_put_kvm(owner_kvm); return; } diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 716be21fba33..d63e5878988a 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -109,6 +109,7 @@ struct kvm_sev_info { u64 ap_jump_table; /* SEV-ES AP Jump Table address */ u64 vmsa_features; u16 ghcb_version; /* Highest guest GHCB protocol version allowed */ + /* The three fields below are protected by sev_mirror_lock */ struct kvm *enc_context_owner; /* Owner of copied encryption context */ struct list_head mirror_vms; /* List of VMs mirroring */ struct list_head mirror_entry; /* Use as a list entry of mirrors */ --=20 2.55.0