Message ID | 20210604172611.281819-1-jmattson@google.com (mailing list archive) |
---|---|
Headers | show |
Series | KVM: nVMX: Fix vmcs02 PID use-after-free issue | expand |
On 04/06/21 19:25, Jim Mattson wrote: > When the VMCS12 posted interrupt descriptor isn't backed by an L1 > memslot, kvm will launch vmcs02 with a stale posted interrupt > descriptor. Before commit 6beb7bd52e48 ("kvm: nVMX: Refactor > nested_get_vmcs12_pages()"), kvm would have silently disabled the > VMCS02 "process posted interrupts" VM-execution control. Both > behaviors are wrong, though the use-after-free is more egregious. > > Empirical tests on actual hardware reveal that a posted interrupt > descriptor without any backing memory/device has PCI bus error > semantics (reads return all 1's and writes are discarded). However, > kvm can't tell an unbacked address from an MMIO address. Normally, kvm > would ask userspace for an MMIO completion, but that's complicated for > a posted interrupt descriptor access. There are already a number of > cases where kvm bails out to userspace with KVM_INTERNAL_ERROR via > kvm_handle_memory_failure, so that seems like the best route to take. > > It would be relatively easy to invoke kvm_handle_memory_failure at > emulated VM-entry, but that approach would break existing > kvm-unit-tests. Moreover, the issue doesn't really come up until the > vCPU--in virtualized VMX non-root operation--received the posted > interrupt notification vector indicated in its VMCS12. > > Sadly, it's really hard to arrange for an exit to userspace from > vmx_complete_nested_posted_interrupt, which is where kvm actually > needs to access the unbacked PID. Initially, I added a new kvm request > for a userspace exit on the next guest entry, but Sean hated that > approach. Based on his suggestion, I added the plumbing to get back > out to userspace in the event of an error in > vmx_complete_nested_posted_interrupt. This works in the case of an > unbacked PID, but it doesn't work quite as well in the case of an > unbacked virtual APIC page (another case where kvm was happy to just > silently ignore the problem and attempt to muddle its way through.) In > that case, this series is an incremental improvement, but it's not a > complete fix. > > v1 -> v2: > 05/12: Modified kvm_arch_vcpu_ioctl_get_mpstate() so that it > returns the error code from kvm_apic_accept_events() if > said error code is less than 0. > 07/12: Changed a comment based on Sean's feedback. > > Jim Mattson (12): > KVM: x86: Remove guest mode check from kvm_check_nested_events > KVM: x86: Wake up a vCPU when kvm_check_nested_events fails > KVM: nVMX: Add a return code to vmx_complete_nested_posted_interrupt > KVM: x86: Add a return code to inject_pending_event > KVM: x86: Add a return code to kvm_apic_accept_events > KVM: nVMX: Fail on MMIO completion for nested posted interrupts > KVM: nVMX: Disable vmcs02 posted interrupts if vmcs12 PID isn't > mappable > KVM: selftests: Move APIC definitions into a separate file > KVM: selftests: Hoist APIC functions out of individual tests > KVM: selftests: Introduce x2APIC register manipulation functions > KVM: selftests: Introduce prepare_tpr_shadow > KVM: selftests: Add a test of an unbacked nested PI descriptor > > arch/x86/kvm/lapic.c | 11 +- > arch/x86/kvm/lapic.h | 2 +- > arch/x86/kvm/vmx/nested.c | 31 ++- > arch/x86/kvm/x86.c | 59 ++-- > tools/testing/selftests/kvm/.gitignore | 1 + > tools/testing/selftests/kvm/Makefile | 3 +- > .../selftests/kvm/include/x86_64/apic.h | 91 +++++++ > .../selftests/kvm/include/x86_64/processor.h | 49 +--- > .../selftests/kvm/include/x86_64/vmx.h | 6 + > tools/testing/selftests/kvm/lib/x86_64/apic.c | 45 ++++ > tools/testing/selftests/kvm/lib/x86_64/vmx.c | 8 + > .../testing/selftests/kvm/x86_64/evmcs_test.c | 11 +- > .../selftests/kvm/x86_64/set_boot_cpu_id.c | 6 +- > tools/testing/selftests/kvm/x86_64/smm_test.c | 4 +- > .../selftests/kvm/x86_64/vmx_pi_mmio_test.c | 252 ++++++++++++++++++ > .../selftests/kvm/x86_64/xapic_ipi_test.c | 59 +--- > 16 files changed, 490 insertions(+), 148 deletions(-) > create mode 100644 tools/testing/selftests/kvm/include/x86_64/apic.h > create mode 100644 tools/testing/selftests/kvm/lib/x86_64/apic.c > create mode 100644 tools/testing/selftests/kvm/x86_64/vmx_pi_mmio_test.c > Queued, thanks. I'll leave out temporarily 2/10/12 until I figure out what's going on. Paolo