Merge tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm

Pull kvm fixes from Paolo Bonzini:
 "Even more x86 fixes:

   - Avoid a false positive panic in the #PF handler, if the kernel
     triggers a page fault within the asynchronous page fault handler
     before the flags are reset.

     This can happen for example because of a perf NMI.

   - Always reset a vCPU's MMU pointer back to the root MMU when loading
     nested guest state fails during RSM or KVM_SET_NESTED_STATE.

     Otherwise KVM tries to run a non-nested guest with a nested MMU,
     which can result in a NULL pointer dereference attempting to get
     the nested MMU's pgd (EPTP or nested CR3)"

* tag 'for-linus' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
  KVM: nVMX: Reset MMU back to the root MMU if loading L2 state fails for !VM-Entry
  x86/kvm: Don't consume async #PF flags on a kernel #PF in NMI context
This commit is contained in:
Linus Torvalds committed 2026-10-15 08:12:47 -07:00
commit 9aa622dbaa
2 files changed
+32 -4

No files matched your search

+29 -3
View File
@@ -265,11 +265,39 @@ noinstr u32 kvm_read_and_reset_apf_flags(void)
}
EXPORT_SYMBOL_FOR_KVM(kvm_read_and_reset_apf_flags);
static __always_inline bool kvm_apf_reason_pending(void)
{
return __this_cpu_read(async_pf_enabled) &&
__this_cpu_read(apf_reason.flags);
}
noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token)
{
u32 flags = kvm_read_and_reset_apf_flags();
irqentry_state_t state;
u32 flags;
if (!kvm_apf_reason_pending())
return false;
/*
* The guest does not enable KVM_ASYNC_PF_SEND_ALWAYS, so the host
* delivers async #PF only to user mode (or as a #PF VM-exit, which KVM
* reads itself). A #PF from kernel mode can still arrive between that
* delivery and the read of the reason flags, inside an NMI that
* interrupted it, for instance perf reading user memory for a call
* chain. Such a fault is not async, so leave the async PF flags
* untouched for the outer handler. Outside NMI context, on the other
* hand, async PF flags on a kernel-mode fault mean the host is broken.
*/
if (!user_mode(regs)) {
if (likely(in_nmi()))
return false;
state = irqentry_enter(regs);
instrumentation_begin();
panic("Host injected async #PF in kernel mode\n");
}
flags = kvm_read_and_reset_apf_flags();
if (!flags)
return false;
@@ -285,8 +313,6 @@ noinstr bool __kvm_handle_async_pf(struct pt_regs *regs, u32 token)
panic("Host injected async #PF in interrupt disabled region\n");
if (flags & KVM_PV_REASON_PAGE_NOT_PRESENT) {
if (unlikely(!(user_mode(regs))))
panic("Host injected async #PF in kernel mode\n");
/* Page is swapped out by the host. */
kvm_async_pf_task_wait_schedule(token);
} else {
+3 -1
View File
@@ -3770,8 +3770,10 @@ vmentry_fail_vmexit_guest_mode:
vmentry_fail_vmexit:
vmx_switch_vmcs(vcpu, &vmx->vmcs01);
if (!from_vmentry)
if (!from_vmentry) {
nested_ept_uninit_mmu_context(vcpu);
return NVMX_VMENTRY_VMEXIT;
}
nested_put_vmcs12_pages(vcpu);