Skip to content

Commit 64c947a

Browse files
committed
KVM: VMX: Reject KVM_RUN if userspace forces emulation during nested VM-Enter
Extend KVM's restrictions on userspace forcing "emulation required" at odd times to cover stuffing invalid guest state while a nested run is pending. Clobbering guest state while KVM is in the middle of emulating VM-Enter is nonsensical, as it puts the vCPU into an architecturally impossible state, and will trip KVM's sanity check that guards against KVM bugs, e.g. helps detect missed VMX consistency checks. WARNING: CPU: 3 PID: 6336 at arch/x86/kvm/vmx/vmx.c:6480 __vmx_handle_exit arch/x86/kvm/vmx/vmx.c:6480 [inline] WARNING: CPU: 3 PID: 6336 at arch/x86/kvm/vmx/vmx.c:6480 vmx_handle_exit+0x40f/0x1f70 arch/x86/kvm/vmx/vmx.c:6637 Modules linked in: CPU: 3 UID: 0 PID: 6336 Comm: syz.0.73 Not tainted 6.13.0-rc1-syzkaller-00316-gb5f217084ab3 #0 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014 RIP: 0010:__vmx_handle_exit arch/x86/kvm/vmx/vmx.c:6480 [inline] RIP: 0010:vmx_handle_exit+0x40f/0x1f70 arch/x86/kvm/vmx/vmx.c:6637 <TASK> vcpu_enter_guest arch/x86/kvm/x86.c:11081 [inline] vcpu_run+0x3047/0x4f50 arch/x86/kvm/x86.c:11242 kvm_arch_vcpu_ioctl_run+0x44a/0x1740 arch/x86/kvm/x86.c:11560 kvm_vcpu_ioctl+0x6ce/0x1520 virt/kvm/kvm_main.c:4340 vfs_ioctl fs/ioctl.c:51 [inline] __do_sys_ioctl fs/ioctl.c:906 [inline] __se_sys_ioctl fs/ioctl.c:892 [inline] __x64_sys_ioctl+0x190/0x200 fs/ioctl.c:892 do_syscall_x64 arch/x86/entry/common.c:52 [inline] do_syscall_64+0xcd/0x250 arch/x86/entry/common.c:83 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK> Reported-by: syzbot+ac0bc3a70282b4d586cc@syzkaller.appspotmail.com Closes: https://lore.kernel.org/all/67598fb9.050a0220.17f54a.003b.GAE@google.com Debugged-by: James Houghton <jthoughton@google.com> Tested-by: James Houghton <jthoughton@google.com> Link: https://lore.kernel.org/r/20250224171409.2348647-1-seanjc@google.com Signed-off-by: Sean Christopherson <seanjc@google.com>
1 parent 61146f6 commit 64c947a

File tree

1 file changed

+28
-4
lines changed

1 file changed

+28
-4
lines changed

arch/x86/kvm/vmx/vmx.c

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5876,11 +5876,35 @@ static int handle_nmi_window(struct kvm_vcpu *vcpu)
58765876
return 1;
58775877
}
58785878

5879-
static bool vmx_emulation_required_with_pending_exception(struct kvm_vcpu *vcpu)
5879+
/*
5880+
* Returns true if emulation is required (due to the vCPU having invalid state
5881+
* with unsrestricted guest mode disabled) and KVM can't faithfully emulate the
5882+
* current vCPU state.
5883+
*/
5884+
static bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu)
58805885
{
58815886
struct vcpu_vmx *vmx = to_vmx(vcpu);
58825887

5883-
return vmx->emulation_required && !vmx->rmode.vm86_active &&
5888+
if (!vmx->emulation_required)
5889+
return false;
5890+
5891+
/*
5892+
* It is architecturally impossible for emulation to be required when a
5893+
* nested VM-Enter is pending completion, as VM-Enter will VM-Fail if
5894+
* guest state is invalid and unrestricted guest is disabled, i.e. KVM
5895+
* should synthesize VM-Fail instead emulation L2 code. This path is
5896+
* only reachable if userspace modifies L2 guest state after KVM has
5897+
* performed the nested VM-Enter consistency checks.
5898+
*/
5899+
if (vmx->nested.nested_run_pending)
5900+
return true;
5901+
5902+
/*
5903+
* KVM only supports emulating exceptions if the vCPU is in Real Mode.
5904+
* If emulation is required, KVM can't perform a successful VM-Enter to
5905+
* inject the exception.
5906+
*/
5907+
return !vmx->rmode.vm86_active &&
58845908
(kvm_is_exception_pending(vcpu) || vcpu->arch.exception.injected);
58855909
}
58865910

@@ -5903,7 +5927,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
59035927
if (!kvm_emulate_instruction(vcpu, 0))
59045928
return 0;
59055929

5906-
if (vmx_emulation_required_with_pending_exception(vcpu)) {
5930+
if (vmx_unhandleable_emulation_required(vcpu)) {
59075931
kvm_prepare_emulation_failure_exit(vcpu);
59085932
return 0;
59095933
}
@@ -5927,7 +5951,7 @@ static int handle_invalid_guest_state(struct kvm_vcpu *vcpu)
59275951

59285952
int vmx_vcpu_pre_run(struct kvm_vcpu *vcpu)
59295953
{
5930-
if (vmx_emulation_required_with_pending_exception(vcpu)) {
5954+
if (vmx_unhandleable_emulation_required(vcpu)) {
59315955
kvm_prepare_emulation_failure_exit(vcpu);
59325956
return 0;
59335957
}

0 commit comments

Comments
 (0)