From: Amirmohammad Eftekhar <amirmohammad.eftekhar@cispa.de>
To: <seanjc@google.com>, <pbonzini@redhat.com>
Cc: <kvm@vger.kernel.org>, <linux-kernel@vger.kernel.org>
Subject: [BUG] KVM: x86: __set_regs() silently drops a pending nested exception destined to VM-exit to L1
Date: Sat, 17 Oct 2026 01:52:21 +0200 [thread overview]
Message-ID: <20261016235221.33726-5-amirmohammad.eftekhar@cispa.de> (raw)
Hi,
__set_regs() (arch/x86/kvm/regs.c:102) unconditionally clears both pending
exception queues:
vcpu->arch.exception.pending = false; /* regs.c:129 */
vcpu->arch.exception_vmexit.pending = false; /* regs.c:130 */
Neither clear is gated by is_guest_mode(), and neither is visible to
KVM_GET/SET_VCPU_EVENTS. exception_vmexit is the queued exception KVM will turn
into a nested VM-exit to L1 (the vector L1 intercepts via the VMX
EXCEPTION_BITMAP / #PF error-code match, or SVM intercept_exceptions). When L2
is active and that reflection is pending, a KVM_SET_REGS the VMM issues for an
unrelated reason silently discards the reflection L1 configured, so L2 evades an
exception interception L1 relies on. __set_regs() is reached by
ioctl(KVM_SET_REGS) and by the KVM_SYNC_X86_REGS dirty-regs path
(kvm_run->s.regs, regs.c:728).
Class: a KVM ABI-level correctness bug (edge E3 -- L2 escapes an L1-intended
interception). It is NOT host corruption: the drop is clear-only, so it cannot
violate the requeue/injection WARNs (kvm_clear_exception_queue runs first in
*_complete_interrupts, so the drop cannot create dual-pending, set TRIPLE_FAULT,
or leave pending while !is_guest_mode), the SMM/#DF morph early-returns before
the #DF logic, and exception_vmexit is a software queue never written to
vmcs02/vmcb02 VM_ENTRY_INTR_INFO, so there is no stale hardware injection. All
PoC runs are dmesg-clean under KASAN. It is also not memory-safety and not a host
DoS.
Not reachable through stock QEMU: the apparent guest trigger (L2 IN 0x5658 ->
cpu_synchronize_state -> KVM_SET_REGS) does not drop anything, because QEMU's
put order is kvm_put_vcpu_events after KVM_SET_REGS in the same
kvm_arch_put_registers (it re-stuffs exception.pending, and the entry-morph
re-creates exception_vmexit), and QEMU x86 does not use KVM_SYNC_X86_REGS. So
this needs a custom/buggy VMM, or a direct /dev/kvm user issuing SET_REGS
without a paired events-put while in guest mode.
Secondary (H4): __set_regs() leaves exception_from_userspace and
exception.vector intact, so a pure-userspace KVM_SET_VCPU_EVENTS(pending=V) ->
KVM_SET_REGS with no KVM_RUN between makes the entry-morph fire a spurious
reflection of V that userspace believed it cleared. Real, self-cleaning,
VMM-userspace-only, and not QEMU-reachable (QEMU's put order is SET_REGS before
SET_VCPU_EVENTS).
Suggested direction (for your call): either do not clear exception_vmexit in
__set_regs() (leave the nested reflection to GET/SET_VCPU_EVENTS, which already
round-trips it correctly), or gate the clears appropriately and also clear
exception_from_userspace/vector so the H4 spurious-reflection path cannot fire.
I did not want to pick an ABI semantics here without your input.
Demonstrations (both dmesg-clean, deterministic, Intel 7.3-rc3): a standalone
KVM selftest that uses immediate_exit to hold exception_vmexit.pending across a
KVM_RUN return, then shows KVM_SET_REGS drops it while a GET/SET_VCPU_EVENTS
round-trip preserves it. It is small and I can post it alongside a patch once
the intended fix is agreed.
Thanks,
Amirmohammad
next reply other threads:[~2026-10-17 0:33 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-16 23:52 Amirmohammad Eftekhar [this message]
2026-10-17 0:50 ` 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=20261016235221.33726-5-amirmohammad.eftekhar@cispa.de \
--to=amirmohammad.eftekhar@cispa.de \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®