CVE-2014-3690 kvm: invalid host cr4 handling (rhbz 1153322 1155372)

This commit is contained in:
Josh Boyer 2014-10-22 12:45:05 -04:00
parent 60b4d8c05f
commit f3bcd32f97
2 changed files with 95 additions and 1 deletions

View File

@ -759,6 +759,9 @@ Patch26032: mnt-Prevent-pivot_root-from-creating-a-loop-in-the-m.patch
#CVE-2014-7975 rhbz 1151108 1152025
Patch26042: fs-Add-a-missing-permission-check-to-do_umount.patch
# CVE-2014-3690 rhbz 1153322 1155372
Patch26060: x86-kvm-vmx-Preserve-CR4-across-VM-entry.patch
# END OF PATCH DEFINITIONS
%endif
@ -1460,6 +1463,9 @@ ApplyPatch mnt-Prevent-pivot_root-from-creating-a-loop-in-the-m.patch
#CVE-2014-7975 rhbz 1151108 1152025
ApplyPatch fs-Add-a-missing-permission-check-to-do_umount.patch
# CVE-2014-3690 rhbz 1153322 1155372
ApplyPatch x86-kvm-vmx-Preserve-CR4-across-VM-entry.patch
# END OF PATCH APPLICATIONS
%endif
@ -2272,6 +2278,9 @@ fi
# and build.
%changelog
* Wed Oct 22 2014 Josh Boyer <jwboyer@fedoraproject.org>
- CVE-2014-3690 kvm: invalid host cr4 handling (rhbz 1153322 1155372)
* Wed Oct 15 2014 Justin M. Forbes <jforbes@fedoraproject.org> - 3.14.22-100
- Linux v3.14.22
@ -2287,7 +2296,7 @@ fi
* Mon Oct 06 2014 Justin M. Forbes <jforbes@fedoraproject.org> - 3.14.20-100
- Linux v3.14.20
* Thu Sep 17 2014 Justin M. Forbes <jforbes@fedoraproject.org> - 3.14.19-100
* Thu Sep 18 2014 Justin M. Forbes <jforbes@fedoraproject.org> - 3.14.19-100
- Linux v3.14.19
* Mon Sep 15 2014 Josh Boyer <jwboyer@fedoraproject.org>

View File

@ -0,0 +1,85 @@
From 2401bcf9fb70d5577699835058e740ad18da6e24 Mon Sep 17 00:00:00 2001
From: Andy Lutomirski <luto@amacapital.net>
Date: Wed, 8 Oct 2014 09:02:13 -0700
Subject: [PATCH] x86,kvm,vmx: Preserve CR4 across VM entry
CR4 isn't constant; at least the TSD and PCE bits can vary.
TBH, treating CR0 and CR3 as constant scares me a bit, too, but it looks
like it's correct.
This adds a branch and a read from cr4 to each vm entry. Because it is
extremely likely that consecutive entries into the same vcpu will have
the same host cr4 value, this fixes up the vmcs instead of restoring cr4
after the fact. A subsequent patch will add a kernel-wide cr4 shadow,
reducing the overhead in the common case to just two memory reads and a
branch.
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
Cc: stable@vger.kernel.org
Cc: Petr Matousek <pmatouse@redhat.com>
Cc: Gleb Natapov <gleb@kernel.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Conflicts:
arch/x86/kvm/vmx.c
---
arch/x86/kvm/vmx.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 392752834751..21ccec8eb01b 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -441,6 +441,7 @@ struct vcpu_vmx {
#endif
int gs_ldt_reload_needed;
int fs_reload_needed;
+ unsigned long vmcs_host_cr4; /* May not match real cr4 */
} host_state;
struct {
int vm86_active;
@@ -4162,11 +4163,16 @@ static void vmx_set_constant_host_state(struct vcpu_vmx *vmx)
u32 low32, high32;
unsigned long tmpl;
struct desc_ptr dt;
+ unsigned long cr4;
vmcs_writel(HOST_CR0, read_cr0() & ~X86_CR0_TS); /* 22.2.3 */
- vmcs_writel(HOST_CR4, read_cr4()); /* 22.2.3, 22.2.5 */
vmcs_writel(HOST_CR3, read_cr3()); /* 22.2.3 FIXME: shadow tables */
+ /* Save the most likely value for this task's CR4 in the VMCS. */
+ cr4 = read_cr4();
+ vmcs_writel(HOST_CR4, cr4); /* 22.2.3, 22.2.5 */
+ vmx->host_state.vmcs_host_cr4 = cr4;
+
vmcs_write16(HOST_CS_SELECTOR, __KERNEL_CS); /* 22.2.4 */
#ifdef CONFIG_X86_64
/*
@@ -7186,7 +7192,7 @@ static void atomic_switch_perf_msrs(struct vcpu_vmx *vmx)
static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- unsigned long debugctlmsr;
+ unsigned long debugctlmsr, cr4;
/* Record the guest's net vcpu time for enforced NMI injections. */
if (unlikely(!cpu_has_virtual_nmis() && vmx->soft_vnmi_blocked))
@@ -7207,6 +7213,12 @@ static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
+ cr4 = read_cr4();
+ if (unlikely(cr4 != vmx->host_state.vmcs_host_cr4)) {
+ vmcs_writel(HOST_CR4, cr4);
+ vmx->host_state.vmcs_host_cr4 = cr4;
+ }
+
/* When single-stepping over STI and MOV SS, we must clear the
* corresponding interruptibility bits in the guest state. Otherwise
* vmentry fails as it then expects bit 14 (BS) in pending debug
--
1.9.3