]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM nVMX: Check Host Segment Registers and Descriptor Tables on vmentry of nested...
authorKrish Sadhukhan <krish.sadhukhan@oracle.com>
Wed, 3 Jul 2019 23:54:35 +0000 (19:54 -0400)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 5 Jul 2019 12:01:51 +0000 (14:01 +0200)
According to section "Checks on Host Segment and Descriptor-Table
Registers" in Intel SDM vol 3C, the following checks are performed on
vmentry of nested guests:

   - In the selector field for each of CS, SS, DS, ES, FS, GS and TR, the
     RPL (bits 1:0) and the TI flag (bit 2) must be 0.
   - The selector fields for CS and TR cannot be 0000H.
   - The selector field for SS cannot be 0000H if the "host address-space
     size" VM-exit control is 0.
   - On processors that support Intel 64 architecture, the base-address
     fields for FS, GS and TR must contain canonical addresses.

Signed-off-by: Krish Sadhukhan <krish.sadhukhan@oracle.com>
Reviewed-by: Karl Heubaum <karl.heubaum@oracle.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/vmx/nested.c

index d125304ae2c999c286ad3a45aab04b589b8e9dea..6dd20e0ad2fad5ac00fdef9438254ae746ef3dbb 100644 (file)
@@ -2627,6 +2627,30 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
            !kvm_pat_valid(vmcs12->host_ia32_pat))
                return -EINVAL;
 
+       ia32e = (vmcs12->vm_exit_controls &
+                VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
+
+       if (vmcs12->host_cs_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_ss_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_ds_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_es_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_fs_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_gs_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_tr_selector & (SEGMENT_RPL_MASK | SEGMENT_TI_MASK) ||
+           vmcs12->host_cs_selector == 0 ||
+           vmcs12->host_tr_selector == 0 ||
+           (vmcs12->host_ss_selector == 0 && !ia32e))
+               return -EINVAL;
+
+#ifdef CONFIG_X86_64
+       if (is_noncanonical_address(vmcs12->host_fs_base, vcpu) ||
+           is_noncanonical_address(vmcs12->host_gs_base, vcpu) ||
+           is_noncanonical_address(vmcs12->host_gdtr_base, vcpu) ||
+           is_noncanonical_address(vmcs12->host_idtr_base, vcpu) ||
+           is_noncanonical_address(vmcs12->host_tr_base, vcpu))
+               return -EINVAL;
+#endif
+
        /*
         * If the load IA32_EFER VM-exit control is 1, bits reserved in the
         * IA32_EFER MSR must be 0 in the field for that register. In addition,
@@ -2634,8 +2658,6 @@ static int nested_vmx_check_host_state(struct kvm_vcpu *vcpu,
         * the host address-space size VM-exit control.
         */
        if (vmcs12->vm_exit_controls & VM_EXIT_LOAD_IA32_EFER) {
-               ia32e = (vmcs12->vm_exit_controls &
-                        VM_EXIT_HOST_ADDR_SPACE_SIZE) != 0;
                if (!kvm_valid_efer(vcpu, vmcs12->host_ia32_efer) ||
                    ia32e != !!(vmcs12->host_ia32_efer & EFER_LMA) ||
                    ia32e != !!(vmcs12->host_ia32_efer & EFER_LME))