Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit b6094c48 authored by Sean Christopherson's avatar Sean Christopherson Committed by Greg Kroah-Hartman
Browse files

KVM: VMX: Drop bits 31:16 when shoving exception error code into VMCS



commit eba9799b5a6efe2993cf92529608e4aa8163d73b upstream.

Deliberately truncate the exception error code when shoving it into the
VMCS (VM-Entry field for vmcs01 and vmcs02, VM-Exit field for vmcs12).
Intel CPUs are incapable of handling 32-bit error codes and will never
generate an error code with bits 31:16, but userspace can provide an
arbitrary error code via KVM_SET_VCPU_EVENTS.  Failure to drop the bits
on exception injection results in failed VM-Entry, as VMX disallows
setting bits 31:16.  Setting the bits on VM-Exit would at best confuse
L1, and at worse induce a nested VM-Entry failure, e.g. if L1 decided to
reinject the exception back into L2.

Cc: stable@vger.kernel.org
Signed-off-by: default avatarSean Christopherson <seanjc@google.com>
Reviewed-by: default avatarJim Mattson <jmattson@google.com>
Reviewed-by: default avatarMaxim Levitsky <mlevitsk@redhat.com>
Link: https://lore.kernel.org/r/20220830231614.3580124-3-seanjc@google.com


Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 76447864
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -3427,7 +3427,16 @@ static void nested_vmx_inject_exception_vmexit(struct kvm_vcpu *vcpu,
	u32 intr_info = nr | INTR_INFO_VALID_MASK;

	if (vcpu->arch.exception.has_error_code) {
		vmcs12->vm_exit_intr_error_code = vcpu->arch.exception.error_code;
		/*
		 * Intel CPUs do not generate error codes with bits 31:16 set,
		 * and more importantly VMX disallows setting bits 31:16 in the
		 * injected error code for VM-Entry.  Drop the bits to mimic
		 * hardware and avoid inducing failure on nested VM-Entry if L1
		 * chooses to inject the exception back to L2.  AMD CPUs _do_
		 * generate "full" 32-bit error codes, so KVM allows userspace
		 * to inject exception error codes with bits 31:16 set.
		 */
		vmcs12->vm_exit_intr_error_code = (u16)vcpu->arch.exception.error_code;
		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
	}

+11 −1
Original line number Diff line number Diff line
@@ -1676,7 +1676,17 @@ static void vmx_queue_exception(struct kvm_vcpu *vcpu)
	kvm_deliver_exception_payload(vcpu);

	if (has_error_code) {
		vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, error_code);
		/*
		 * Despite the error code being architecturally defined as 32
		 * bits, and the VMCS field being 32 bits, Intel CPUs and thus
		 * VMX don't actually supporting setting bits 31:16.  Hardware
		 * will (should) never provide a bogus error code, but AMD CPUs
		 * do generate error codes with bits 31:16 set, and so KVM's
		 * ABI lets userspace shove in arbitrary 32-bit values.  Drop
		 * the upper bits to avoid VM-Fail, losing information that
		 * does't really exist is preferable to killing the VM.
		 */
		vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, (u16)error_code);
		intr_info |= INTR_INFO_DELIVER_CODE_MASK;
	}