From: Hao Zhang <hao_zhang_kdev@163.com>
To: Sean Christopherson <seanjc@google.com>
Cc: Hao Zhang <hao_zhang_kdev@163.com>,
Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org
Subject: Re: [PATCH v3] KVM: x86: Mark nested RSM-created VM-Enter as untrusted
Date: Wed, 22 Jul 2026 09:26:17 +0800 [thread overview]
Message-ID: <amAcObySFW2LOtXH@192.168.1.215> (raw)
In-Reply-To: <al-SKXoha-dqz047@google.com>
On Tue, Jul 21, 2026, Sean Christopherson wrote:
> On Tue, Jul 21, 2026, Hao Zhang wrote:
> > From: Hao Zhang <zhanghao1@kylinos.cn>
> >
> > RSM can restore state that indicates the vCPU was running L2 when SMI
> > arrived. KVM then re-enters nested guest mode and marks nested_run_pending
> > so that the next KVM_RUN completes the pending nested transition.
> >
> > Unlike a normal nested VMLAUNCH/VMRESUME, the state restored by RSM comes
> > from SMRAM. Userspace can modify SMRAM before RSM. The resulting L2 state
> > may require invalid-guest-state emulation. If KVM trusts that pending run,
> > VMX can synthesize EXIT_REASON_INVALID_STATE before hardware VM-Entry
> > completes the pending run and trip the nested_run_pending invariant.
> >
> > Do not treat an RSM-created pending nested run as KVM-trusted state. Mark
> > the run as KVM_NESTED_RUN_PENDING_UNTRUSTED for both VMX and SVM, matching
> > the existing userspace-modified-state handling in kvm_x86_vcpu_pre_run().
> >
> > Keep the VMX BUG check for trusted pending nested VM-Enters, but allow
> > untrusted pending state to reach the existing invalid-L2-state handling.
> > If that handling synthesizes a nested VM-Exit back to L1, retain the
> > pending state while synchronizing VMCS02 to VMCS12, and consume it before
> > restoring L1 state so that the flag does not leak into L1 and block event
> > injection.
> >
> > Fixes: 2bb8cafea80b ("KVM: vVMX: signal failure for nested VMEntry if emulation_required")
> > Suggested-by: Sean Christopherson <seanjc@google.com>
> > Signed-off-by: Hao Zhang <zhanghao1@kylinos.cn>
> > ---
> > diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> > index cc75feec05da..cf5c3f78ebfc 100644
> > --- a/arch/x86/kvm/vmx/vmx.c
> > +++ b/arch/x86/kvm/vmx/vmx.c
> > @@ -6715,12 +6715,14 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
> > return 0;
> >
> > /*
> > - * KVM should never reach this point with a pending nested VM-Enter.
> > - * More specifically, short-circuiting VM-Entry to emulate L2 due to
> > - * invalid guest state should never happen as that means KVM knowingly
> > - * allowed a nested VM-Enter with an invalid vmcs12. More below.
> > - */
> > - if (KVM_BUG_ON(vcpu->arch.nested_run_pending, vcpu->kvm))
> > + * KVM should never reach this point with a trusted pending nested
> > + * VM-Enter. Short-circuiting VM-Entry to emulate L2 due to invalid
> > + * guest state after a normal nested VM-Enter would mean KVM knowingly
> > + * allowed an invalid vmcs12. Pending VM-Enters restored from untrusted
> > + * state are handled below.
> > + */
> > + if (KVM_BUG_ON(vcpu->arch.nested_run_pending == KVM_NESTED_RUN_PENDING,
> > + vcpu->kvm))
>
> Ugh, I missed that my suggestion would require adjusting this KVM_BUG_ON().
> That's not the end of the world, but it's not great either because it further
> degrades the sanity checks provided by nested_run_pending.
>
> And while Sashiko was hallucinating wildly with respect to a "mailicious L2
> modifying SMRAM", Sashiko did have a point about leaving nested_run_pending set
> beyond the emulated RSM. KVM really should check for the impossible state after
> loading vCPU state from SMRAM in emulator_leave_smm(), so that forcibly leaving
> nested mode to synthesize TRIPLE_FAULT into L1 naturally Just Works.
>
> The only reason I didn't suggest that is because I didn't want to add another
> SMM-specific kvm_x86_ops hook, but I think we can avoid that and (arguably)
> improve other paths at the same time.
>
> Rather than provide a generic .vcpu_pre_run() hook, which is somewhat confusing
> because SVM has it's own pre_svm_run(), what if we provide separate hooks for
> unhandleable_emulation_required() and vcpu_needs_initialization()? That bleeds
> some vendor specific details into common x86, but in many ways, that's a _good_
> thing in this case because I think it's helpful to highlight the need for
> additional initialization for CoCo vCPUs.
>
> Do you happen to have a reproducer I can test? Either way, I'll try to add a
> testcase to tools/testing/selftests/kvm/x86/vmx_invalid_nested_guest_state.c to
> cover the SMRAM => RSM path.
>
I don't have a standalone C reproducer, but I do have the syzkaller program
that hit the original WARNING. It uses syz_kvm_setup_cpu$x86 and includes the
RSM path; I used it via syz-repro against the original crash bucket.
The repro seed is below. It is not yet converted into a KVM selftest, but it
should be useful as a starting point for the SMRAM => RSM coverage in
vmx_invalid_nested_guest_state.c.
r0 = openat$kvm(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
r1 = ioctl$KVM_CREATE_VM(r0, 0xae01, 0x0)
r2 = ioctl$KVM_CREATE_VCPU(r1, 0xae41, 0x1)
syz_kvm_setup_cpu$x86(r1, r2, &(0x7f0000000000/0x18000)=nil, &(0x7f0000000080)=[@text64={0x40, 0x0}], 0x1, 0x54, 0x0, 0x0)
madvise(&(0x7f000010c000/0xe000)=nil, 0xe000, 0x66)
ioctl$KVM_RUN(r2, 0xae80, 0x0)
r3 = openat$kvm(0xffffffffffffff9c, &(0x7f0000000000), 0x2, 0x0)
r4 = ioctl$KVM_CREATE_VM(r3, 0xae01, 0x0)
r5 = ioctl$KVM_CREATE_VCPU(r4, 0xae41, 0x0)
syz_kvm_setup_cpu$x86(r4, r5, &(0x7f0000000000/0x18000)=nil, &(0x7f0000000080)=[@text32={0x20, &(0x7f0000000180)="6526f30f09660faade7e07b805000000b9ce8400000f01c1dd5d140f00d4ea000000008600440f20c03504000000440f22c0360f01d10f07", 0x38}], 0x1, 0x20, 0x0, 0x0)
syz_kvm_setup_cpu$x86(r1, r2, &(0x7f0000d9e000/0x18000)=nil, &(0x7f00000001c0)=[@text32={0x20, &(0x7f0000000240)="66ba4000edb8cd0000000f23d00f21f835100000020f23f8b99f0b00000f32dd1f66ba6100ec670f00d3b9800000c00f3235000100000f30c4e2e19274b900b9800000c00f3235008000000f3026650fc76c5589", 0x54}], 0x1, 0x8, &(0x7f0000000200)=[@cstype0={0x4, 0x8}], 0x1)
r6 = openat$kvm(0xffffffffffffff9c, &(0x7f0000000080), 0x0, 0x0)
r7 = ioctl$KVM_CREATE_VM(r6, 0xae01, 0x0)
r8 = ioctl$KVM_CREATE_VCPU(r7, 0xae41, 0x0)
syz_kvm_setup_cpu$x86(r7, r8, &(0x7f0000fe1000/0x18000)=nil, &(0x7f0000000040)=[@text64={0x40, &(0x7f00000000c0)="0f6f2848b802000000000000000f23d80f21f835c00000b00f23f8470f220240a6dae9643644a5410f01c80f0fb500800000aeb9cb020000b851320000ba000000000f300f006b00", 0x48}], 0x1, 0x51, 0x0, 0x0)
ioctl$KVM_RUN(r8, 0xae80, 0x0)
syz_kvm_setup_cpu$x86(r1, r2, &(0x7f0000fe5000/0x18000)=nil, &(0x7f00000002c0)=[@textreal={0x8, 0x0}], 0x1, 0x22, 0x0, 0x0)
ioctl$KVM_RUN(r2, 0xae80, 0x0)
--
Thanks,
Hao
prev parent reply other threads:[~2026-07-22 1:26 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-21 8:40 [PATCH v3] KVM: x86: Mark nested RSM-created VM-Enter as untrusted Hao Zhang
2026-07-21 15:37 ` Sean Christopherson
2026-07-22 1:26 ` Hao Zhang [this message]
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=amAcObySFW2LOtXH@192.168.1.215 \
--to=hao_zhang_kdev@163.com \
--cc=kvm@vger.kernel.org \
--cc=pbonzini@redhat.com \
--cc=seanjc@google.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.