[PATCH v3 00/15] KVM: Fix+harden against bad uaccess using dying VM

From: Sean Christopherson

Date: Tue Oct 27 2026 - 18:13:16 EST


Fix a class of bugs (limited to nested VMX, as far as we know) where KVM can
corrupt an unrelated process' memory if KVM (attempts to) write to guest memory
during VM destruction. Because current->mm usually isn't kvm->mm when a VM is
dying, e.g. because the associated kvm->mm process has already exited, writing
to what KVM thinks is guest memory will corrupt the current address space if
the associated userspace address happens to be writable in the victim.

Patch 1 is a blanket fix for the uaccess paths. AFAIK, x86's nVMX is the only
path in KVM that screws up, but auditing kvm_arch_destroy_vm() proved to be
infeasible for a human (I didn't throw AI at it, yet...), and I can't think of
any downsides to going straight to a broader fix.

Patch 2 fixes the underlyihng nVMX bug where KVM absuses the architectural
nested VM-Exit flow when tearing down a vCPU, which has a truly absurd number
of problems.

Patch 3 fixes what I assume is a blatant PPC bug. KVM PPC completely ignores
kvm_arch_flush_shadow_all(), i.e. AFAICT, doesn't tear down its page tables
when the owning process exits. I don't have much confidence in the "fix", in
part because it seems impossible that such a blatant bug could have gone
unnoticed, but also because I went with a very naive approach of invoking
kvm_arch_flush_shadow_memslot() for each memslot. The changelog is pretty
sparse, because I didn't know how to describe the issue byeond "this is
completely broken".

Patches 4-6 implement more agressive hardening to nuke the memslots before
calling kvm_arch_destroy_vm(), e.g. to guard against writing to guest memory
during kvm_arch_destroy_vm() without going through uaccess. Setting dummy
memslots feels a little hacky, but kvm_arch_flush_shadow_all() should have
purged everything that effectively caches memslots, so it seems like the right
approach?

Patches 7-9 add more hardening to detect KVM bugs (though the uaccess+memslot
changes earlier in the series should render any bugs benign).

The remaining patches double down on open coding nVMX's vCPU teardown by
tearing down the vCPU "as-is", instead of forcing a switch to L1 and then
doing teardown. The forced switch is quite heinous, as it requires KVM to
*load* the vCPU when it's dying due to architectural constraints for active
VMCSes. Not only is that gross, it was also papering over a bug (hopefully
just the one) where KVM was relying on the vCPU load for nested VMX to take
vCPUs off the posted interrupts wakeup list.

v3:
- Give up, and open code nVMX teardown. [Sashiko, syzbot, Chris]
- Drop the nVMX hacks that were trying to fudge around the mass of nVMX
teardown issues.
- Free the VMA only for the non-SMM internal memslot. [Sashiko]
- Use @len, not hardcoded PAGE_SIZE, in kvm_is_guest_access_ok(). [Sashiko]
- Rip out the awful vCPU load code from nested_vmx_free_vcpu().
- Collect James' reviews.

v2: https://lore.kernel.org/all/20261001202234.3794060-1-seanjc@xxxxxxxxxx

v1: https://lore.kernel.org/all/20260908132838.2116068-1-jmattson@xxxxxxxxxx

Sean Christopherson (15):
KVM: Reject user accesses to guest memory if current->mm != kvm->mm
KVM: nVMX: Don't force a full nested VM-Exit when destroying a vCPU
KVM: PPC: Flush/zap all memslots on kvm_arch_flush_shadow_all()
KVM: x86: Unmap VMAs for KVM-internal memslots when the memslot is
freed
KVM: Disallow setting memslots when the VM is being destroyed
KVM: Destroy memslots immediately after mmu_notifiers are unregistered
KVM: WARN if KVM attempts to do guest-related uaccess with "wrong"
process
KVM: WARN and reject guest-based uaccess if VM is dying
KVM: Pre-check uaccesses in KVM's APIs to read/write guest memory
KVM: VMX: Explicility free vmcs01, not the current VMCS, in vCPU free
paths
KVM: nVMX: Don't explicitly VMCLEAR+free() vmcs01's shadow VMCS when
freeing vCPU
KVM: nVMX: Cancel the nested VMX Preemption Timer's hrtimer in
free_nested()
KVM: VMX: Explicitly remove dying vCPUs from the PI wakeup list
KVM: nVMX: Don't switch to vmcs01 when freeing a vCPU
KVM: nVMX: Don't load+put the vCPU when freeing nested state for a
dying vCPU

arch/powerpc/include/asm/kvm_host.h | 1 -
arch/powerpc/kvm/powerpc.c | 11 ++++
arch/x86/kvm/vmx/nested.c | 69 ++++++++++++-----------
arch/x86/kvm/vmx/posted_intr.c | 68 +++++++++++++---------
arch/x86/kvm/vmx/posted_intr.h | 1 +
arch/x86/kvm/vmx/sgx.c | 2 +-
arch/x86/kvm/vmx/vmx.c | 19 ++++---
arch/x86/kvm/x86.c | 38 ++++++-------
include/linux/kvm_host.h | 26 ++++++++-
virt/kvm/kvm_main.c | 87 +++++++++++++++++++----------
10 files changed, 199 insertions(+), 123 deletions(-)


base-commit: 7e60162b16f9da0d2fa83da5c1723b6853a0ac1d
--
2.56.0.307.g5fe7bd680c-goog