diff --git a/0001-KVM-x86-nVMX-close-leak-of-L0-s-x2APIC-MSRs-CVE-2019.patch b/0001-KVM-x86-nVMX-close-leak-of-L0-s-x2APIC-MSRs-CVE-2019.patch new file mode 100644 index 0000000..f8e81e7 --- /dev/null +++ b/0001-KVM-x86-nVMX-close-leak-of-L0-s-x2APIC-MSRs-CVE-2019.patch @@ -0,0 +1,134 @@ +From acff78477b9b4f26ecdf65733a4ed77fe837e9dc Mon Sep 17 00:00:00 2001 +From: Marc Orr +Date: Mon, 1 Apr 2019 23:55:59 -0700 +Subject: [PATCH] KVM: x86: nVMX: close leak of L0's x2APIC MSRs + (CVE-2019-3887) + +The nested_vmx_prepare_msr_bitmap() function doesn't directly guard the +x2APIC MSR intercepts with the "virtualize x2APIC mode" MSR. As a +result, we discovered the potential for a buggy or malicious L1 to get +access to L0's x2APIC MSRs, via an L2, as follows. + +1. L1 executes WRMSR(IA32_SPEC_CTRL, 1). This causes the spec_ctrl +variable, in nested_vmx_prepare_msr_bitmap() to become true. +2. L1 disables "virtualize x2APIC mode" in VMCS12. +3. L1 enables "APIC-register virtualization" in VMCS12. + +Now, KVM will set VMCS02's x2APIC MSR intercepts from VMCS12, and then +set "virtualize x2APIC mode" to 0 in VMCS02. Oops. + +This patch closes the leak by explicitly guarding VMCS02's x2APIC MSR +intercepts with VMCS12's "virtualize x2APIC mode" control. + +The scenario outlined above and fix prescribed here, were verified with +a related patch in kvm-unit-tests titled "Add leak scenario to +virt_x2apic_mode_test". + +Note, it looks like this issue may have been introduced inadvertently +during a merge---see 15303ba5d1cd. + +Signed-off-by: Marc Orr +Reviewed-by: Jim Mattson +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/vmx/nested.c | 72 ++++++++++++++++++++++++--------------- + 1 file changed, 44 insertions(+), 28 deletions(-) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index 153e539c29c9..897d70e3d291 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -500,6 +500,17 @@ static void nested_vmx_disable_intercept_for_msr(unsigned long *msr_bitmap_l1, + } + } + ++static inline void enable_x2apic_msr_intercepts(unsigned long *msr_bitmap) { ++ int msr; ++ ++ for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) { ++ unsigned word = msr / BITS_PER_LONG; ++ ++ msr_bitmap[word] = ~0; ++ msr_bitmap[word + (0x800 / sizeof(long))] = ~0; ++ } ++} ++ + /* + * Merge L0's and L1's MSR bitmap, return false to indicate that + * we do not use the hardware. +@@ -541,39 +552,44 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, + return false; + + msr_bitmap_l1 = (unsigned long *)kmap(page); +- if (nested_cpu_has_apic_reg_virt(vmcs12)) { +- /* +- * L0 need not intercept reads for MSRs between 0x800 and 0x8ff, it +- * just lets the processor take the value from the virtual-APIC page; +- * take those 256 bits directly from the L1 bitmap. +- */ +- for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) { +- unsigned word = msr / BITS_PER_LONG; +- msr_bitmap_l0[word] = msr_bitmap_l1[word]; +- msr_bitmap_l0[word + (0x800 / sizeof(long))] = ~0; +- } +- } else { +- for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) { +- unsigned word = msr / BITS_PER_LONG; +- msr_bitmap_l0[word] = ~0; +- msr_bitmap_l0[word + (0x800 / sizeof(long))] = ~0; +- } +- } + +- nested_vmx_disable_intercept_for_msr( +- msr_bitmap_l1, msr_bitmap_l0, +- X2APIC_MSR(APIC_TASKPRI), +- MSR_TYPE_W); ++ /* ++ * To keep the control flow simple, pay eight 8-byte writes (sixteen ++ * 4-byte writes on 32-bit systems) up front to enable intercepts for ++ * the x2APIC MSR range and selectively disable them below. ++ */ ++ enable_x2apic_msr_intercepts(msr_bitmap_l0); ++ ++ if (nested_cpu_has_virt_x2apic_mode(vmcs12)) { ++ if (nested_cpu_has_apic_reg_virt(vmcs12)) { ++ /* ++ * L0 need not intercept reads for MSRs between 0x800 ++ * and 0x8ff, it just lets the processor take the value ++ * from the virtual-APIC page; take those 256 bits ++ * directly from the L1 bitmap. ++ */ ++ for (msr = 0x800; msr <= 0x8ff; msr += BITS_PER_LONG) { ++ unsigned word = msr / BITS_PER_LONG; ++ ++ msr_bitmap_l0[word] = msr_bitmap_l1[word]; ++ } ++ } + +- if (nested_cpu_has_vid(vmcs12)) { +- nested_vmx_disable_intercept_for_msr( +- msr_bitmap_l1, msr_bitmap_l0, +- X2APIC_MSR(APIC_EOI), +- MSR_TYPE_W); + nested_vmx_disable_intercept_for_msr( + msr_bitmap_l1, msr_bitmap_l0, +- X2APIC_MSR(APIC_SELF_IPI), ++ X2APIC_MSR(APIC_TASKPRI), + MSR_TYPE_W); ++ ++ if (nested_cpu_has_vid(vmcs12)) { ++ nested_vmx_disable_intercept_for_msr( ++ msr_bitmap_l1, msr_bitmap_l0, ++ X2APIC_MSR(APIC_EOI), ++ MSR_TYPE_W); ++ nested_vmx_disable_intercept_for_msr( ++ msr_bitmap_l1, msr_bitmap_l0, ++ X2APIC_MSR(APIC_SELF_IPI), ++ MSR_TYPE_W); ++ } + } + + if (spec_ctrl) +-- +2.20.1 + diff --git a/0001-KVM-x86-nVMX-fix-x2APIC-VTPR-read-intercept.patch b/0001-KVM-x86-nVMX-fix-x2APIC-VTPR-read-intercept.patch new file mode 100644 index 0000000..f73a7f3 --- /dev/null +++ b/0001-KVM-x86-nVMX-fix-x2APIC-VTPR-read-intercept.patch @@ -0,0 +1,46 @@ +From c73f4c998e1fd4249b9edfa39e23f4fda2b9b041 Mon Sep 17 00:00:00 2001 +From: Marc Orr +Date: Mon, 1 Apr 2019 23:56:00 -0700 +Subject: [PATCH] KVM: x86: nVMX: fix x2APIC VTPR read intercept + +Referring to the "VIRTUALIZING MSR-BASED APIC ACCESSES" chapter of the +SDM, when "virtualize x2APIC mode" is 1 and "APIC-register +virtualization" is 0, a RDMSR of 808H should return the VTPR from the +virtual APIC page. + +However, for nested, KVM currently fails to disable the read intercept +for this MSR. This means that a RDMSR exit takes precedence over +"virtualize x2APIC mode", and KVM passes through L1's TPR to L2, +instead of sourcing the value from L2's virtual APIC page. + +This patch fixes the issue by disabling the read intercept, in VMCS02, +for the VTPR when "APIC-register virtualization" is 0. + +The issue described above and fix prescribed here, were verified with +a related patch in kvm-unit-tests titled "Test VMX's virtualize x2APIC +mode w/ nested". + +Signed-off-by: Marc Orr +Reviewed-by: Jim Mattson +Fixes: c992384bde84f ("KVM: vmx: speed up MSR bitmap merge") +Signed-off-by: Paolo Bonzini +--- + arch/x86/kvm/vmx/nested.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c +index 897d70e3d291..7ec9bb1dd723 100644 +--- a/arch/x86/kvm/vmx/nested.c ++++ b/arch/x86/kvm/vmx/nested.c +@@ -578,7 +578,7 @@ static inline bool nested_vmx_prepare_msr_bitmap(struct kvm_vcpu *vcpu, + nested_vmx_disable_intercept_for_msr( + msr_bitmap_l1, msr_bitmap_l0, + X2APIC_MSR(APIC_TASKPRI), +- MSR_TYPE_W); ++ MSR_TYPE_R | MSR_TYPE_W); + + if (nested_cpu_has_vid(vmcs12)) { + nested_vmx_disable_intercept_for_msr( +-- +2.20.1 + diff --git a/kernel.spec b/kernel.spec index bb508d9..fedb26a 100644 --- a/kernel.spec +++ b/kernel.spec @@ -617,6 +617,10 @@ Patch516: 0001-inotify-Fix-fsnotify_mark-refcount-leak-in-inotify_u.patch # CVE-2019-3882 rhbz 1689426 1695571 Patch517: vfio-type1-limit-dma-mappings-per-container.patch +# CVE-2019 rhbz 1695044 1697187 +Patch518: 0001-KVM-x86-nVMX-close-leak-of-L0-s-x2APIC-MSRs-CVE-2019.patch +Patch519: 0001-KVM-x86-nVMX-fix-x2APIC-VTPR-read-intercept.patch + # END OF PATCH DEFINITIONS %endif @@ -1890,6 +1894,9 @@ fi # # %changelog +* Mon Apr 08 2019 Justin M. Forbes +- Fix CVE-2019 (rhbz 1695044 1697187) + * Mon Apr 08 2019 Laura Abbott - 5.0.7-200 - Linux v5.0.7