Kernel KVM virtualization development
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Jim Mattson" <jmattson@google.com>
Cc: kvm@vger.kernel.org
Subject: Re: [PATCH] KVM: nVMX: Don't flush shadow VMCS12 to guest memory during vCPU teardown
Date: Tue, 08 Sep 2026 13:57:36 +0000	[thread overview]
Message-ID: <20260908135736.D14C01F00A3A@smtp.kernel.org> (raw)
In-Reply-To: <20260908132838.2116068-1-jmattson@google.com>

Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:

Pre-existing issues:
- [Critical] Live migration during SMM with an active nested guest overwrites L2 state (e.g. RIP/RSP) with stale data from the hardware shadow VMCS.
- [High] Live migration during SMM with nested shadow VMCS enabled causes a Triple Fault on the destination.
- [High] During vCPU teardown, __nested_vmx_vmexit() unconditionally loads L1 host state, triggering a cross-process memory read via load_pdptrs() with a borrowed active_mm.
--

commit 15d3183acc0011b1c1063bab25d832a346f7a45c
Author: Jim Mattson <jmattson@google.com>

KVM: nVMX: Don't flush shadow VMCS12 to guest memory during vCPU teardown

When a vCPU is destroyed while L2 is active, KVM synthesizes a nested VM-Exit.
During this process exit, the vCPU destruction runs with a borrowed lazy TLB 
active_mm, so skipping the shadow VMCS12 flush prevents __copy_to_user() 
from corrupting an unrelated task's memory.

> diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
> index 151873407abd3..33dc8a07019f8 100644
> --- a/arch/x86/kvm/vmx/nested.c
> +++ b/arch/x86/kvm/vmx/nested.c
> @@ -5121,21 +5121,28 @@ void __nested_vmx_vmexit(struct kvm_vcpu *vcpu, u32 vm_exit_reason,
>  	if (likely(!vmx->fail)) {
>  		sync_vmcs02_to_vmcs12(vcpu, vmcs12);
>  
> -		if (vm_exit_reason != -1)
> +		if (vm_exit_reason != -1) {
>  			prepare_vmcs12(vcpu, vmcs12, vm_exit_reason,
>  				       exit_intr_info, exit_qualification,
>  				       exit_insn_len);
>  
> -		/*
> -		 * Must happen outside of sync_vmcs02_to_vmcs12() as it will
> -		 * also be used to capture vmcs12 cache as part of
> -		 * capturing nVMX state for snapshot (migration).
> -		 *
> -		 * Otherwise, this flush will dirty guest memory at a
> -		 * point it is already assumed by user-space to be
> -		 * immutable.
> -		 */
> -		nested_flush_cached_shadow_vmcs12(vcpu, vmcs12);
> +			/*
> +			 * Must happen outside of sync_vmcs02_to_vmcs12() as it will
> +			 * also be used to capture vmcs12 cache as part of
> +			 * capturing nVMX state for snapshot (migration).
> +			 *
> +			 * Otherwise, this flush will dirty guest memory at a
> +			 * point it is already assumed by user-space to be
> +			 * immutable.
> +			 *
> +			 * Do not flush when vm_exit_reason == -1 (e.g. forced exit
> +			 * on vCPU teardown or SMM entry). On teardown, KVM may run
> +			 * with current->mm == NULL on a borrowed lazy TLB mm,
> +			 * where writing guest memory would corrupt an unrelated
> +			 * task. Nothing can observe the flush in that case anyway.
> +			 */
> +			nested_flush_cached_shadow_vmcs12(vcpu, vmcs12);
> +		}
>  	} else {
>  		/*
>  		 * The only expected VM-instruction error is "VM entry with

[Severity: High]
This is a pre-existing issue, but since this patch handles vCPU teardown with
a borrowed active_mm, does the later call to load_vmcs12_host_state() in
__nested_vmx_vmexit() have a similar issue?

During vCPU teardown, __nested_vmx_vmexit() unconditionally loads L1 host
state:

arch/x86/kvm/vmx/nested.c:__nested_vmx_vmexit() {
    ...
    load_vmcs12_host_state(vcpu, vmcs12);
    ...
}

If the L1 host state uses PAE paging, nested_vmx_load_cr3() triggers the
PDPTR load:

arch/x86/kvm/vmx/nested.c:nested_vmx_load_cr3() {
    ...
    if (reload_pdptrs && !nested_ept && is_pae_paging(vcpu) &&
        CC(!load_pdptrs(vcpu, cr3))) {
    ...
}

This executes a memory read using copy_from_user() in the context of the
borrowed active_mm:

arch/x86/kvm/regs.c:load_pdptrs() {
    ...
    ret = kvm_vcpu_read_guest_page(vcpu, gpa_to_gfn(real_gpa), pdpte,
                                   cr3 & GENMASK(11, 5), sizeof(pdpte));
    ...
}

Could this cross-process memory read cause destructive side-effects if it hits
a memory-mapped I/O (MMIO) region in the unrelated task?


[Severity: Critical]
This is a pre-existing issue, but does skipping the shadow VMCS12 flush on
SMM entry (where vm_exit_reason == -1) cause data corruption during live
migration?

In __nested_vmx_vmexit(), need_vmcs12_to_shadow_sync is prevented from being
set on SMM entry because of the vm_exit_reason check:

arch/x86/kvm/vmx/nested.c:__nested_vmx_vmexit() {
    ...
    if ((vm_exit_reason != -1) &&
        (enable_shadow_vmcs || nested_vmx_is_evmptr12_valid(vmx)))
        vmx->nested.need_vmcs12_to_shadow_sync = true;
    ...
}

If live migration is initiated while in SMM, vmx_get_nested_state() treats
the hardware shadow VMCS as authoritative:

arch/x86/kvm/vmx/nested.c:vmx_get_nested_state() {
    ...
    else if (enable_shadow_vmcs)
        copy_shadow_to_vmcs12(vmx);
    ...
}

Since need_vmcs12_to_shadow_sync was not set, doesn't this overwrite the
correctly synced vmcs12 with stale data from the hardware shadow VMCS,
resulting in guest state rollback (e.g., RIP/RSP)?


[Severity: High]
This isn't a bug introduced by this patch, but is there a Triple Fault risk
during live migration in SMM with nested shadow VMCS enabled?

Because is_guest_mode is false in SMM, the shadow_vmcs12 is omitted from the
migration stream:

arch/x86/kvm/vmx/nested.c:vmx_get_nested_state() {
    ...
    if (is_guest_mode(vcpu) &&
        nested_cpu_has_shadow_vmcs(vmcs12) &&
        vmcs12->vmcs_link_pointer != INVALID_GPA)
        kvm_state.size += sizeof(user_vmx_nested_state->shadow_vmcs12);
    ...
}

On the destination, vmx_set_nested_state() skips restoring shadow_vmcs12 and
returns early:

arch/x86/kvm/vmx/nested.c:vmx_set_nested_state() {
    ...
    if (!(kvm_state->flags & KVM_STATE_NESTED_GUEST_MODE))
        return 0;
    ...
}

When the guest leaves SMM, vmx_leave_smm() checks the revision ID of the
zeroed shadow_vmcs12:

arch/x86/kvm/vmx/vmx.c:vmx_leave_smm() {
    ...
    /* Triple fault if the state is invalid.  */
    if (nested_vmx_check_restored_vmcs12(vcpu) < 0)
        return 1;
    ...
}

Could this zeroed buffer fail the revision ID check and induce a Triple Fault?

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260908132838.2116068-1-jmattson@google.com?part=1

  reply	other threads:[~2026-09-08 13:57 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-08 13:28 [PATCH] KVM: nVMX: Don't flush shadow VMCS12 to guest memory during vCPU teardown Jim Mattson
2026-09-08 13:57 ` sashiko-bot [this message]
2026-09-08 17:34 ` James Houghton
2026-09-08 19:12   ` Jim Mattson
2026-09-09 15:41     ` James Houghton
2026-09-09 19:00     ` Sean Christopherson
2026-09-10 18:58       ` James Houghton
2026-09-10 19:14         ` Sean Christopherson
2026-09-10 19:32           ` Sean Christopherson
2026-09-10 19:40           ` Sean Christopherson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260908135736.D14C01F00A3A@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=jmattson@google.com \
    --cc=kvm@vger.kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox