From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794417546; b=egqV9EvQqF4kpz/va0QND3QVSgMvMeWvPf21fWL6WpjsHC5tE6x/PqRALQsLljixBX3v qv/pcnNqp23xXXNHORbG20xiOaZnx3YB56dYrppBWJ7y8sCySTpS5y3C+dsn2MuY9v20e gZPhmCzZYVrNhGKdADH5zZkCBpJ6z84/WmjDRF/Lz55RtCZxbqNO8l7aW2tSk2T9V5R5e cYCQ8TIND4/5Xjy7By0StHGsPUX0uvU9mry1i2tAYED7Usil1X3WMvAufmMrVzVmkPYR7 9cLuEZZLrcCC3Ayjv8vrGJrcNmpx3vV3LFyI+PgiHimLy6JIVaQlFJokItH9HRsWiIw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794417546; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:MIME-Version:Content-Transfer-Encoding; bh=x9r4He6dlOvFfDr10CZw0IrBEGWu4bAWP8F7SZlJEhA=; b=MLVHrilPefCGyJhpR4jLfQhpTdxfWPhos8BMZ67f2b2+1gbm59yMa1/G1jTKcJXWH+nn 7N29UAa4OLjYAa3ndmoS+e/goMnyNl8TfV+w0aRPWT/ZvwWE0Z/dtgvfVX3gt/9BGQwmQ iob6AVBeZic4R/uNSG0Za9iaNNSJSTimXZ6U3YljDvhrfgeZ+CUN2x7sx2wGP6wmopLJh R5Kuv/BKDVM+QKFniLmtFrlsi5+O2d5G9UGOoyooTl1akv/Q2Tpp2V07XBF5a6RxHyPFj sr9MLaywbHrA7qiwoY6hzyFhBFYvGK5DRKAdjGjNENa8H9jYgnRGkj7Zw0fnidTN9KQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=mMwIiLe8; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 346BB606A324 for ; Wed, 11 Nov 2026 17:19:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.a=rsa-sha256 header.s=k20260515 header.b=mMwIiLe8 Received: by smtp.kernel.org (Postfix) with ESMTPSA id 32C6F1F00A06; Wed, 11 Nov 2026 17:19:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=kernel.org; s=k20260515; t=1794417545; bh=x9r4He6dlOvFfDr10CZw0IrBEGWu4bAWP8F7SZlJEhA=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=mMwIiLe8M5fTEJph9gYnKmVJ7PFDntJgxnENMWunDsL0zHCdigmgqmY5m+0NiYGGw sCBJm21+9IAUMq146iAkIKlmHVpvcBHtixgCm100jy4uLH9SG6aNOxj3HlnS7FmkXv OPeUe4jsut6iUVetYdERiFwoZ5Vr4vfp6/3eA63PEC/i5yyow9XSNB8+BGqRUnv9ho V3h080Hrx45B5T6Z4DQMUlYj0NuTi/t8GNbkD1bqnXXsqp1/Exf6u+txGr7v6xhgAo fwfDrjqkzYFhbmT4ytLVu7qmlHpDuOUatNd3Iet709k313qGBk+s8taWWmJeh4EjyR ilYxhkyhxAy1g== From: Sasha Levin To: stable@vger.kernel.org Cc: Sean Christopherson , Bill Wendling , Stefan Teodorescu , Paolo Bonzini , Sasha Levin Subject: [PATCH 6.12.y] KVM: nSVM: Check validity of vmcs01 save area copied from SMRAM on RSM Date: Wed, 11 Nov 2026 12:19:04 -0500 Message-ID: <20261111171853.3548855-1-sashal@kernel.org> X-Mailer: git-send-email 2.53.0 In-Reply-To: <20261109200735-failed-6.12-053621535f01@kernel.org> References: <20261109200735-failed-6.12-053621535f01@kernel.org> X-Mailing-List: stable@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit From: Sean Christopherson [ Upstream commit 053621535f014085c935879582dd3b65964a0dce ] When doing RSM to L2, validate L1's state after copying it back into vmcb01 from SMRAM, as SMRAM is carved out of guest memory, i.e. is writable by the guest. Failure to validate L1's state is especially problematic for inputs to MMU context, as KVM can end up with impossible CR4 vs. EFER state. E.g. without the recent hardening FNAME(walk_addr_generic), a guest can trigger: ------------[ cut here ]------------ UBSAN: array-index-out-of-bounds in arch/x86/kvm/mmu/paging_tmpl.h:435:15 index 3 is out of range for type 'u32 [2]' CPU: 3 UID: 0 PID: 92 Comm: CPU 1/KVM Not tainted 7.3.0-rc1 #2 PREEMPT(lazy) Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014 Call Trace: dump_stack_lvl+0x5f/0x90 dump_stack+0x10/0x18 ubsan_epilogue+0x9/0x39 __ubsan_handle_out_of_bounds.cold+0x50/0x55 paging32_walk_addr_generic+0x889/0x970 paging32_page_fault+0x79/0xa60 kvm_mmu_do_page_fault+0x125/0x270 kvm_mmu_page_fault+0x88/0x7b0 npf_interception+0xc8/0x220 [kvm_amd] svm_invoke_exit_handler+0x16d/0x1d0 [kvm_amd] svm_handle_exit+0xb7/0x160 [kvm_amd] vcpu_enter_guest+0x428/0x16a0 kvm_arch_vcpu_ioctl_run+0x479/0x920 kvm_vcpu_ioctl+0x316/0xb00 __x64_sys_ioctl+0xa3/0x100 x64_sys_call+0x281/0x23d0 do_syscall_64+0xba/0x550 entry_SYSCALL_64_after_hwframe+0x76/0x7e RIP: 0033:0x79bb30deb04b ---[ end trace ]--- Fixes: 37be407b2ce8 ("KVM: nSVM: Fix L1 state corruption upon return from SMM") Cc: stable@vger.kernel.org Reported-by: Bill Wendling Reported-by: Stefan Teodorescu Tested-by: Stefan Teodorescu Signed-off-by: Sean Christopherson Message-ID: <20261022021046.295001-1-seanjc@google.com> Signed-off-by: Paolo Bonzini [ sashal: adapted validation to __nested_vmcb_check_save() with failures routed through the existing unmap_save cleanup ] Signed-off-by: Sasha Levin --- arch/x86/kvm/svm/nested.c | 23 ++++++++++++++++------- arch/x86/kvm/svm/svm.c | 2 ++ arch/x86/kvm/svm/svm.h | 2 ++ 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 3c9c20d7855fe..670a5d57f33da 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -1613,6 +1613,21 @@ static void nested_copy_vmcb_cache_to_control(struct vmcb_control_area *dst, /* 'clean' and 'hv_enlightenments' are not changed by KVM */ } +bool nested_svm_check_vmcb01_save(struct kvm_vcpu *vcpu, + struct vmcb_save_area *save) +{ + struct vmcb_save_area_cached save_cached; + + if (!(save->cr0 & X86_CR0_PG) || + !(save->cr0 & X86_CR0_PE) || + (save->rflags & X86_EFLAGS_VM) || + ((save->efer & EFER_LMA) && !(save->efer & EFER_LME))) + return false; + + __nested_copy_vmcb_save_to_cache(&save_cached, save); + return __nested_vmcb_check_save(vcpu, &save_cached); +} + static int svm_get_nested_state(struct kvm_vcpu *vcpu, struct kvm_nested_state __user *user_kvm_nested_state, u32 user_data_size) @@ -1689,7 +1704,6 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, &user_kvm_nested_state->data.svm[0]; struct vmcb_control_area *ctl; struct vmcb_save_area *save; - struct vmcb_save_area_cached save_cached; struct vmcb_ctrl_area_cached ctl_cached; unsigned long cr0; int ret; @@ -1759,12 +1773,7 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, * Validate host state saved from before VMRUN (see * nested_svm_check_permissions). */ - __nested_copy_vmcb_save_to_cache(&save_cached, save); - if (!(save->cr0 & X86_CR0_PG) || - !(save->cr0 & X86_CR0_PE) || - (save->rflags & X86_EFLAGS_VM) || - ((save->efer & EFER_LMA) && !(save->efer & EFER_LME)) || - !__nested_vmcb_check_save(vcpu, &save_cached)) + if (!nested_svm_check_vmcb01_save(vcpu, save)) goto out_free; diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c index df325d0864819..2796368f231d3 100644 --- a/arch/x86/kvm/svm/svm.c +++ b/arch/x86/kvm/svm/svm.c @@ -4960,6 +4960,8 @@ static int svm_leave_smm(struct kvm_vcpu *vcpu, const union kvm_smram *smram) */ svm_copy_vmrun_state(&svm->vmcb01.ptr->save, map_save.hva + 0x400); + if (!nested_svm_check_vmcb01_save(vcpu, &svm->vmcb01.ptr->save)) + goto unmap_save; /* * Enter the nested guest now diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h index 511fadfb055f6..a3724e867a4c9 100644 --- a/arch/x86/kvm/svm/svm.h +++ b/arch/x86/kvm/svm/svm.h @@ -689,6 +689,8 @@ void nested_copy_vmcb_save_to_cache(struct vcpu_svm *svm, struct vmcb_save_area *save); void nested_sync_control_from_vmcb02(struct vcpu_svm *svm); void nested_vmcb02_compute_g_pat(struct vcpu_svm *svm); +bool nested_svm_check_vmcb01_save(struct kvm_vcpu *vcpu, + struct vmcb_save_area *save); void svm_switch_vmcb(struct vcpu_svm *svm, struct kvm_vmcb_info *target_vmcb); extern struct kvm_x86_nested_ops svm_nested_ops; -- 2.53.0