From nobody Thu Apr 2 06:27:04 2026 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (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 3F594367F3C; Tue, 3 Mar 2026 00:34:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498080; cv=none; b=uEuarOU7VOPsc45h7D4lcUdSvl8lhaYoqPXul0pXcurd8zaNaAOn6i0yfTDT9EuPe6IIcJqXCy0rGz5uO1zmLKg7tjrVqK/qrJIMOCIlflzicloYkeALBZHGblvrHgh8BzwSdvUGGPUjV/3gs/V2rKdJeAgIVdp/Ssnv4w6JSdk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772498080; c=relaxed/simple; bh=t6T5p2jEtoStZk2ZCNurG/WhOCqTBgnABKrBRmfK3Vs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=W3G2Zbpttr934YBHrPMFstOJfWaUEAdZ8OasyNiVmsYcREFSJ7oXBZB05PJRHF3EWEjJZMgv5Cz1eatgx5oiGD+/vGtEIiZJZiXi44iq4oTzYCS3HR3oTRTzddm7E4d4tGSFZh2y4H2A5KG0Pe2CiuF59a0+6RN8SrCNQ+7TKSA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=WiveKnAA; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="WiveKnAA" Received: by smtp.kernel.org (Postfix) with ESMTPSA id D2C8EC19423; Tue, 3 Mar 2026 00:34:39 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1772498080; bh=t6T5p2jEtoStZk2ZCNurG/WhOCqTBgnABKrBRmfK3Vs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=WiveKnAAkAzfOFda66zzm2IoS1jhljqRP0atuS/SODnFiCj/IQBiNaftOtNrV5ocH Cx0T7IkDz+KcUSGib0XvdATUQd5A8a3uGtsGBgEVvONp69AVEMf8i7GQ6y5oZ13Vyo JpF+eN+FMKYJTZJiRiaAJq4qOzIp8FsmEcppn1S3NqUlX2d8nhIgPgAGCQT/qClBwW KHIuE/JQMweotwcF/wrrM6scu5IOAOxCkUsKU/aGBD8rLPLpflSPlyvQfhDs3QM0Zk NIAN2R1BYkmxLhvdDPnY+C5hdzV4VtGMTTOJ4lINxJdk5QIfwRugnUyFe9nz9LyYH6 uG9gDLLeEH7PQ== From: Yosry Ahmed To: Sean Christopherson Cc: Paolo Bonzini , kvm@vger.kernel.org, linux-kernel@vger.kernel.org, Yosry Ahmed Subject: [PATCH v7 21/26] KVM: nSVM: Restrict mapping vmcb12 on nested VMRUN Date: Tue, 3 Mar 2026 00:34:15 +0000 Message-ID: <20260303003421.2185681-22-yosry@kernel.org> X-Mailer: git-send-email 2.53.0.473.g4a7958ca14-goog In-Reply-To: <20260303003421.2185681-1-yosry@kernel.org> References: <20260303003421.2185681-1-yosry@kernel.org> 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" All accesses to the vmcb12 in the guest memory on nested VMRUN are limited to nested_svm_vmrun() copying vmcb12 fields and writing them on failed consistency checks. However, vmcb12 remains mapped throughout nested_svm_vmrun(). Mapping and unmapping around usages is possible, but it becomes easy-ish to introduce bugs where 'vmcb12' is used after being unmapped. Move reading the vmcb12, copying to cache, and consistency checks from nested_svm_vmrun() into a new helper, nested_svm_copy_vmcb12_to_cache() to limit the scope of the mapping. Signed-off-by: Yosry Ahmed --- arch/x86/kvm/svm/nested.c | 89 ++++++++++++++++++++++----------------- 1 file changed, 51 insertions(+), 38 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index f89040a467d4a..0151354b2ef01 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1054,12 +1054,39 @@ int enter_svm_guest_mode(struct kvm_vcpu *vcpu, u64= vmcb12_gpa, bool from_vmrun) return 0; } =20 -int nested_svm_vmrun(struct kvm_vcpu *vcpu) +static int nested_svm_copy_vmcb12_to_cache(struct kvm_vcpu *vcpu, u64 vmcb= 12_gpa) { struct vcpu_svm *svm =3D to_svm(vcpu); - int ret; - struct vmcb *vmcb12; struct kvm_host_map map; + struct vmcb *vmcb12; + int r =3D 0; + + if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) + return -EFAULT; + + vmcb12 =3D map.hva; + nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); + nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); + + if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || + !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) { + vmcb12->control.exit_code =3D SVM_EXIT_ERR; + vmcb12->control.exit_info_1 =3D 0; + vmcb12->control.exit_info_2 =3D 0; + vmcb12->control.event_inj =3D 0; + vmcb12->control.event_inj_err =3D 0; + svm_set_gif(svm, false); + r =3D -EINVAL; + } + + kvm_vcpu_unmap(vcpu, &map); + return r; +} + +int nested_svm_vmrun(struct kvm_vcpu *vcpu) +{ + struct vcpu_svm *svm =3D to_svm(vcpu); + int ret, err; u64 vmcb12_gpa; struct vmcb *vmcb01 =3D svm->vmcb01.ptr; =20 @@ -1080,32 +1107,23 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) return ret; } =20 + if (WARN_ON_ONCE(!svm->nested.initialized)) + return -EINVAL; + vmcb12_gpa =3D svm->vmcb->save.rax; - if (kvm_vcpu_map(vcpu, gpa_to_gfn(vmcb12_gpa), &map)) { + err =3D nested_svm_copy_vmcb12_to_cache(vcpu, vmcb12_gpa); + if (err =3D=3D -EFAULT) { kvm_inject_gp(vcpu, 0); return 1; } =20 + /* + * Advance RIP if #GP or #UD are not injected, but otherwise stop if + * copying and checking vmcb12 failed. + */ ret =3D kvm_skip_emulated_instruction(vcpu); - - vmcb12 =3D map.hva; - - if (WARN_ON_ONCE(!svm->nested.initialized)) - return -EINVAL; - - nested_copy_vmcb_control_to_cache(svm, &vmcb12->control); - nested_copy_vmcb_save_to_cache(svm, &vmcb12->save); - - if (!nested_vmcb_check_save(vcpu, &svm->nested.save) || - !nested_vmcb_check_controls(vcpu, &svm->nested.ctl)) { - vmcb12->control.exit_code =3D SVM_EXIT_ERR; - vmcb12->control.exit_info_1 =3D 0; - vmcb12->control.exit_info_2 =3D 0; - vmcb12->control.event_inj =3D 0; - vmcb12->control.event_inj_err =3D 0; - svm_set_gif(svm, false); - goto out; - } + if (err) + return ret; =20 /* * Since vmcb01 is not in use, we can use it to store some of the L1 @@ -1122,23 +1140,18 @@ int nested_svm_vmrun(struct kvm_vcpu *vcpu) =20 svm->nested.nested_run_pending =3D 1; =20 - if (enter_svm_guest_mode(vcpu, vmcb12_gpa, true)) - goto out_exit_err; - - if (nested_svm_merge_msrpm(vcpu)) - goto out; - -out_exit_err: - svm->nested.nested_run_pending =3D 0; - - svm->vmcb->control.exit_code =3D SVM_EXIT_ERR; - svm->vmcb->control.exit_info_1 =3D 0; - svm->vmcb->control.exit_info_2 =3D 0; + if (enter_svm_guest_mode(vcpu, vmcb12_gpa, true) || + !nested_svm_merge_msrpm(vcpu)) { + svm->nested.nested_run_pending =3D 0; + svm->nmi_l1_to_l2 =3D false; + svm->soft_int_injected =3D false; =20 - nested_svm_vmexit(svm); + svm->vmcb->control.exit_code =3D SVM_EXIT_ERR; + svm->vmcb->control.exit_info_1 =3D 0; + svm->vmcb->control.exit_info_2 =3D 0; =20 -out: - kvm_vcpu_unmap(vcpu, &map); + nested_svm_vmexit(svm); + } =20 return ret; } --=20 2.53.0.473.g4a7958ca14-goog