]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - arch/x86/kvm/vmx.c
kvm: nVMX: Fix nested_vmx_check_msr_bitmap_controls
[mirror_ubuntu-artful-kernel.git] / arch / x86 / kvm / vmx.c
index f76efad248aba0dc02bce77a4cd984343d181d79..e02c7004b64b5c9a00d5ecb94415a75c20d11aca 100644 (file)
@@ -4634,6 +4634,11 @@ static bool guest_state_valid(struct kvm_vcpu *vcpu)
        return true;
 }
 
+static bool page_address_valid(struct kvm_vcpu *vcpu, gpa_t gpa)
+{
+       return PAGE_ALIGNED(gpa) && !(gpa >> cpuid_maxphyaddr(vcpu));
+}
+
 static int init_rmode_tss(struct kvm *kvm)
 {
        gfn_t fn;
@@ -8418,9 +8423,15 @@ static int vmx_handle_exit(struct kvm_vcpu *vcpu)
                        exit_reason != EXIT_REASON_TASK_SWITCH)) {
                vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR;
                vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV;
-               vcpu->run->internal.ndata = 2;
+               vcpu->run->internal.ndata = 3;
                vcpu->run->internal.data[0] = vectoring_info;
                vcpu->run->internal.data[1] = exit_reason;
+               vcpu->run->internal.data[2] = vcpu->arch.exit_qualification;
+               if (exit_reason == EXIT_REASON_EPT_MISCONFIG) {
+                       vcpu->run->internal.ndata++;
+                       vcpu->run->internal.data[3] =
+                               vmcs_read64(GUEST_PHYSICAL_ADDRESS);
+               }
                return 0;
        }
 
@@ -9589,23 +9600,26 @@ static void vmx_start_preemption_timer(struct kvm_vcpu *vcpu)
                      ns_to_ktime(preemption_timeout), HRTIMER_MODE_REL);
 }
 
+static int nested_vmx_check_io_bitmap_controls(struct kvm_vcpu *vcpu,
+                                              struct vmcs12 *vmcs12)
+{
+       if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
+               return 0;
+
+       if (!page_address_valid(vcpu, vmcs12->io_bitmap_a) ||
+           !page_address_valid(vcpu, vmcs12->io_bitmap_b))
+               return -EINVAL;
+
+       return 0;
+}
+
 static int nested_vmx_check_msr_bitmap_controls(struct kvm_vcpu *vcpu,
                                                struct vmcs12 *vmcs12)
 {
-       int maxphyaddr;
-       u64 addr;
-
        if (!nested_cpu_has(vmcs12, CPU_BASED_USE_MSR_BITMAPS))
                return 0;
 
-       if (vmcs12_read_any(vcpu, MSR_BITMAP, &addr)) {
-               WARN_ON(1);
-               return -EINVAL;
-       }
-       maxphyaddr = cpuid_maxphyaddr(vcpu);
-
-       if (!PAGE_ALIGNED(vmcs12->msr_bitmap) ||
-          ((addr + PAGE_SIZE) >> maxphyaddr))
+       if (!page_address_valid(vcpu, vmcs12->msr_bitmap))
                return -EINVAL;
 
        return 0;
@@ -10293,6 +10307,9 @@ static int check_vmentry_prereqs(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12)
            vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT)
                return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
 
+       if (nested_vmx_check_io_bitmap_controls(vcpu, vmcs12))
+               return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
+
        if (nested_vmx_check_msr_bitmap_controls(vcpu, vmcs12))
                return VMXERR_ENTRY_INVALID_CONTROL_FIELD;
 
@@ -10429,8 +10446,6 @@ static int enter_vmx_non_root_mode(struct kvm_vcpu *vcpu, bool from_vmentry)
                return 1;
        }
 
-       vmcs12->launch_state = 1;
-
        /*
         * Note no nested_vmx_succeed or nested_vmx_fail here. At this point
         * we are no longer running L1, and VMLAUNCH/VMRESUME has not yet
@@ -10804,6 +10819,8 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
        vmcs12->vmx_instruction_info = vmcs_read32(VMX_INSTRUCTION_INFO);
 
        if (!(vmcs12->vm_exit_reason & VMX_EXIT_REASONS_FAILED_VMENTRY)) {
+               vmcs12->launch_state = 1;
+
                /* vm_entry_intr_info_field is cleared on exit. Emulate this
                 * instead of reading the real value. */
                vmcs12->vm_entry_intr_info_field &= ~INTR_INFO_VALID_MASK;