linux-stable/arch/x86/kvm/vmx
Sean Christopherson 946c522b60 KVM: nVMX: Sign extend displacements of VMX instr's mem operands
The VMCS.EXIT_QUALIFCATION field reports the displacements of memory
operands for various instructions, including VMX instructions, as a
naturally sized unsigned value, but masks the value by the addr size,
e.g. given a ModRM encoded as -0x28(%ebp), the -0x28 displacement is
reported as 0xffffffd8 for a 32-bit address size.  Despite some weird
wording regarding sign extension, the SDM explicitly states that bits
beyond the instructions address size are undefined:

    In all cases, bits of this field beyond the instruction’s address
    size are undefined.

Failure to sign extend the displacement results in KVM incorrectly
treating a negative displacement as a large positive displacement when
the address size of the VMX instruction is smaller than KVM's native
size, e.g. a 32-bit address size on a 64-bit KVM.

The very original decoding, added by commit 064aea7747 ("KVM: nVMX:
Decoding memory operands of VMX instructions"), sort of modeled sign
extension by truncating the final virtual/linear address for a 32-bit
address size.  I.e. it messed up the effective address but made it work
by adjusting the final address.

When segmentation checks were added, the truncation logic was kept
as-is and no sign extension logic was introduced.  In other words, it
kept calculating the wrong effective address while mostly generating
the correct virtual/linear address.  As the effective address is what's
used in the segment limit checks, this results in KVM incorreclty
injecting #GP/#SS faults due to non-existent segment violations when
a nested VMM uses negative displacements with an address size smaller
than KVM's native address size.

Using the -0x28(%ebp) example, an EBP value of 0x1000 will result in
KVM using 0x100000fd8 as the effective address when checking for a
segment limit violation.  This causes a 100% failure rate when running
a 32-bit KVM build as L1 on top of a 64-bit KVM L0.

Fixes: f9eb4af67c ("KVM: nVMX: VMX instructions: add checks for #GP/#SS exceptions")
Cc: stable@vger.kernel.org
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
2019-02-20 22:48:22 +01:00
..
capabilities.h
evmcs.c x86/kvm/hyper-v: nested_enable_evmcs() sets vmcs_version incorrectly 2019-01-25 19:11:37 +01:00
evmcs.h
nested.c KVM: nVMX: Sign extend displacements of VMX instr's mem operands 2019-02-20 22:48:22 +01:00
nested.h
ops.h
pmu_intel.c
vmcs.h KVM: nVMX: Cache host_rsp on a per-VMCS basis 2019-02-12 13:12:22 +01:00
vmcs12.c
vmcs12.h
vmcs_shadow_fields.h
vmenter.S KVM: VMX: Reorder clearing of registers in the vCPU-run assembly flow 2019-02-20 22:48:18 +01:00
vmx.c KVM: VMX: Call vCPU-run asm sub-routine from C and remove clobbering 2019-02-20 22:48:18 +01:00
vmx.h KVM: VMX: Pass "launched" directly to the vCPU-run asm blob 2019-02-12 13:12:24 +01:00