kvm: x86: Disallow illegal IA32_APIC_BASE MSR values
authorJim Mattson <jmattson@google.com>
Thu, 10 Aug 2017 17:14:13 +0000 (10:14 -0700)
committerPaolo Bonzini <pbonzini@redhat.com>
Fri, 11 Aug 2017 16:59:30 +0000 (18:59 +0200)
Host-initiated writes to the IA32_APIC_BASE MSR do not have to follow
local APIC state transition constraints, but the value written must be
valid.

Signed-off-by: Jim Mattson <jmattson@google.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/x86/kvm/x86.c

index e40a779711a96b3f44dd8ca8ff07de72c4dee45a..e10eda86bc7b2b01a4e9695989905a162eccc8de 100644 (file)
@@ -313,10 +313,10 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        u64 reserved_bits = ((~0ULL) << cpuid_maxphyaddr(vcpu)) | 0x2ff |
                (guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
 
+       if ((msr_info->data & reserved_bits) || new_state == X2APIC_ENABLE)
+               return 1;
        if (!msr_info->host_initiated &&
-           ((msr_info->data & reserved_bits) != 0 ||
-            new_state == X2APIC_ENABLE ||
-            (new_state == MSR_IA32_APICBASE_ENABLE &&
+           ((new_state == MSR_IA32_APICBASE_ENABLE &&
              old_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE)) ||
             (new_state == (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE) &&
              old_state == 0)))
@@ -7424,6 +7424,11 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                        (sregs->cr4 & X86_CR4_OSXSAVE))
                return -EINVAL;
 
+       apic_base_msr.data = sregs->apic_base;
+       apic_base_msr.host_initiated = true;
+       if (kvm_set_apic_base(vcpu, &apic_base_msr))
+               return -EINVAL;
+
        dt.size = sregs->idt.limit;
        dt.address = sregs->idt.base;
        kvm_x86_ops->set_idt(vcpu, &dt);
@@ -7440,9 +7445,6 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
 
        mmu_reset_needed |= vcpu->arch.efer != sregs->efer;
        kvm_x86_ops->set_efer(vcpu, sregs->efer);
-       apic_base_msr.data = sregs->apic_base;
-       apic_base_msr.host_initiated = true;
-       kvm_set_apic_base(vcpu, &apic_base_msr);
 
        mmu_reset_needed |= kvm_read_cr0(vcpu) != sregs->cr0;
        kvm_x86_ops->set_cr0(vcpu, sregs->cr0);