[kernel/f16] Fix CVE-2012-0045 (rhbz 773392) and update to Linux 3.1.9

Josh Boyer jwboyer at fedoraproject.org
Fri Jan 13 16:13:22 UTC 2012


commit 8c9ba0738b2060076146a7a3022356dca27111df
Author: Josh Boyer <jwboyer at redhat.com>
Date:   Fri Jan 13 11:09:52 2012 -0500

    Fix CVE-2012-0045 (rhbz 773392) and update to Linux 3.1.9

 ...end-struct-x86_emulate_ops-with-get_cpuid.patch |   78 +++++++++++
 ...6-fix-missing-checks-in-syscall-emulation.patch |  144 ++++++++++++++++++++
 kernel.spec                                        |   17 ++-
 sources                                            |    2 +-
 4 files changed, 238 insertions(+), 3 deletions(-)
---
diff --git a/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
new file mode 100644
index 0000000..f9dbaa0
--- /dev/null
+++ b/KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
@@ -0,0 +1,78 @@
+From 0769c5de24621141c953fbe1f943582d37cb4244 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= <stephan.baerwolf at tu-ilmenau.de>
+Date: Thu, 12 Jan 2012 16:43:03 +0100
+Subject: [PATCH 1/2] KVM: x86: extend "struct x86_emulate_ops" with
+ "get_cpuid"
+
+In order to be able to proceed checks on CPU-specific properties
+within the emulator, function "get_cpuid" is introduced.
+With "get_cpuid" it is possible to virtually call the guests
+"cpuid"-opcode without changing the VM's context.
+
+[mtosatti: cleanup/beautify code]
+
+Signed-off-by: Stephan Baerwolf <stephan.baerwolf at tu-ilmenau.de>
+Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
+---
+ arch/x86/include/asm/kvm_emulate.h |    3 +++
+ arch/x86/kvm/x86.c                 |   23 +++++++++++++++++++++++
+ 2 files changed, 26 insertions(+), 0 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
+index ab4092e..c8b2868 100644
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -190,6 +190,9 @@ struct x86_emulate_ops {
+ 	int (*intercept)(struct x86_emulate_ctxt *ctxt,
+ 			 struct x86_instruction_info *info,
+ 			 enum x86_intercept_stage stage);
++
++	bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
++			 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
+ };
+ 
+ typedef u32 __attribute__((vector_size(16))) sse128_t;
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index f0fa3fb..c95ca2d 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -4205,6 +4205,28 @@ static int emulator_intercept(struct x86_emulate_ctxt *ctxt,
+ 	return kvm_x86_ops->check_intercept(emul_to_vcpu(ctxt), info, stage);
+ }
+ 
++static bool emulator_get_cpuid(struct x86_emulate_ctxt *ctxt,
++			       u32 *eax, u32 *ebx, u32 *ecx, u32 *edx)
++{
++	struct kvm_cpuid_entry2 *cpuid = NULL;
++
++	if (eax && ecx)
++		cpuid = kvm_find_cpuid_entry(emul_to_vcpu(ctxt),
++					    *eax, *ecx);
++
++	if (cpuid) {
++		*eax = cpuid->eax;
++		*ecx = cpuid->ecx;
++		if (ebx)
++			*ebx = cpuid->ebx;
++		if (edx)
++			*edx = cpuid->edx;
++		return true;
++	}
++
++	return false;
++}
++
+ static struct x86_emulate_ops emulate_ops = {
+ 	.read_std            = kvm_read_guest_virt_system,
+ 	.write_std           = kvm_write_guest_virt_system,
+@@ -4236,6 +4258,7 @@ static struct x86_emulate_ops emulate_ops = {
+ 	.get_fpu             = emulator_get_fpu,
+ 	.put_fpu             = emulator_put_fpu,
+ 	.intercept           = emulator_intercept,
++	.get_cpuid           = emulator_get_cpuid,
+ };
+ 
+ static void cache_all_regs(struct kvm_vcpu *vcpu)
+-- 
+1.7.7.5
+
diff --git a/KVM-x86-fix-missing-checks-in-syscall-emulation.patch b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch
new file mode 100644
index 0000000..933a134
--- /dev/null
+++ b/KVM-x86-fix-missing-checks-in-syscall-emulation.patch
@@ -0,0 +1,144 @@
+From e28ba7bb020f07193bc000453c8775e9d2c0dda7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Stephan=20B=C3=A4rwolf?= <stephan.baerwolf at tu-ilmenau.de>
+Date: Thu, 12 Jan 2012 16:43:04 +0100
+Subject: [PATCH 2/2] KVM: x86: fix missing checks in syscall emulation
+
+On hosts without this patch, 32bit guests will crash (and 64bit guests
+may behave in a wrong way) for example by simply executing following
+nasm-demo-application:
+
+    [bits 32]
+    global _start
+    SECTION .text
+    _start: syscall
+
+(I tested it with winxp and linux - both always crashed)
+
+    Disassembly of section .text:
+
+    00000000 <_start>:
+       0:   0f 05                   syscall
+
+The reason seems a missing "invalid opcode"-trap (int6) for the
+syscall opcode "0f05", which is not available on Intel CPUs
+within non-longmodes, as also on some AMD CPUs within legacy-mode.
+(depending on CPU vendor, MSR_EFER and cpuid)
+
+Because previous mentioned OSs may not engage corresponding
+syscall target-registers (STAR, LSTAR, CSTAR), they remain
+NULL and (non trapping) syscalls are leading to multiple
+faults and finally crashs.
+
+Depending on the architecture (AMD or Intel) pretended by
+guests, various checks according to vendor's documentation
+are implemented to overcome the current issue and behave
+like the CPUs physical counterparts.
+
+[mtosatti: cleanup/beautify code]
+
+Signed-off-by: Stephan Baerwolf <stephan.baerwolf at tu-ilmenau.de>
+Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
+---
+ arch/x86/include/asm/kvm_emulate.h |   13 +++++++++
+ arch/x86/kvm/emulate.c             |   51 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 64 insertions(+), 0 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
+index c8b2868..7b9cfc4 100644
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -301,6 +301,19 @@ struct x86_emulate_ctxt {
+ #define X86EMUL_MODE_PROT     (X86EMUL_MODE_PROT16|X86EMUL_MODE_PROT32| \
+ 			       X86EMUL_MODE_PROT64)
+ 
++/* CPUID vendors */
++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx 0x68747541
++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx 0x444d4163
++#define X86EMUL_CPUID_VENDOR_AuthenticAMD_edx 0x69746e65
++
++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx 0x69444d41
++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx 0x21726574
++#define X86EMUL_CPUID_VENDOR_AMDisbetterI_edx 0x74656273
++
++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ebx 0x756e6547
++#define X86EMUL_CPUID_VENDOR_GenuineIntel_ecx 0x6c65746e
++#define X86EMUL_CPUID_VENDOR_GenuineIntel_edx 0x49656e69
++
+ enum x86_intercept_stage {
+ 	X86_ICTP_NONE = 0,   /* Allow zero-init to not match anything */
+ 	X86_ICPT_PRE_EXCEPT,
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index 05a562b..0982507 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1891,6 +1891,51 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
+ 	ss->p = 1;
+ }
+ 
++static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt)
++{
++	struct x86_emulate_ops *ops = ctxt->ops;
++	u32 eax, ebx, ecx, edx;
++
++	/*
++	 * syscall should always be enabled in longmode - so only become
++	 * vendor specific (cpuid) if other modes are active...
++	 */
++	if (ctxt->mode == X86EMUL_MODE_PROT64)
++		return true;
++
++	eax = 0x00000000;
++	ecx = 0x00000000;
++	if (ops->get_cpuid(ctxt, &eax, &ebx, &ecx, &edx)) {
++		/*
++		 * Intel ("GenuineIntel")
++		 * remark: Intel CPUs only support "syscall" in 64bit
++		 * longmode. Also an 64bit guest with a
++		 * 32bit compat-app running will #UD !! While this
++		 * behaviour can be fixed (by emulating) into AMD
++		 * response - CPUs of AMD can't behave like Intel.
++		 */
++		if (ebx == X86EMUL_CPUID_VENDOR_GenuineIntel_ebx &&
++		    ecx == X86EMUL_CPUID_VENDOR_GenuineIntel_ecx &&
++		    edx == X86EMUL_CPUID_VENDOR_GenuineIntel_edx)
++			return false;
++
++		/* AMD ("AuthenticAMD") */
++		if (ebx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ebx &&
++		    ecx == X86EMUL_CPUID_VENDOR_AuthenticAMD_ecx &&
++		    edx == X86EMUL_CPUID_VENDOR_AuthenticAMD_edx)
++			return true;
++
++		/* AMD ("AMDisbetter!") */
++		if (ebx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ebx &&
++		    ecx == X86EMUL_CPUID_VENDOR_AMDisbetterI_ecx &&
++		    edx == X86EMUL_CPUID_VENDOR_AMDisbetterI_edx)
++			return true;
++	}
++
++	/* default: (not Intel, not AMD), apply Intel's stricter rules... */
++	return false;
++}
++
+ static int em_syscall(struct x86_emulate_ctxt *ctxt)
+ {
+ 	struct x86_emulate_ops *ops = ctxt->ops;
+@@ -1904,9 +1949,15 @@ static int em_syscall(struct x86_emulate_ctxt *ctxt)
+ 	    ctxt->mode == X86EMUL_MODE_VM86)
+ 		return emulate_ud(ctxt);
+ 
++	if (!(em_syscall_is_enabled(ctxt)))
++		return emulate_ud(ctxt);
++
+ 	ops->get_msr(ctxt, MSR_EFER, &efer);
+ 	setup_syscalls_segments(ctxt, &cs, &ss);
+ 
++	if (!(efer & EFER_SCE))
++		return emulate_ud(ctxt);
++
+ 	ops->get_msr(ctxt, MSR_STAR, &msr_data);
+ 	msr_data >>= 32;
+ 	cs_sel = (u16)(msr_data & 0xfffc);
+-- 
+1.7.7.5
+
diff --git a/kernel.spec b/kernel.spec
index 5f46d6f..97deee0 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -54,7 +54,7 @@ Summary: The Linux kernel
 # For non-released -rc kernels, this will be appended after the rcX and
 # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
 #
-%global baserelease 4
+%global baserelease 1
 %global fedora_build %{baserelease}
 
 # base_sublevel is the kernel version we're starting with and patching
@@ -66,7 +66,7 @@ Summary: The Linux kernel
 %if 0%{?released_kernel}
 
 # Do we have a -stable update to apply?
-%define stable_update 8
+%define stable_update 9
 # Is it a -stable RC?
 %define stable_rc 0
 # Set rpm version accordingly
@@ -861,6 +861,11 @@ Patch21071: ext4-Fix-error-handling-on-inode-bitmap-corruption.patch
 #rhbz 769766
 Patch21072: mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch
 
+#rhbz 773392
+Patch21073: KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
+Patch21074: KVM-x86-fix-missing-checks-in-syscall-emulation.patch
+
+
 # compat-wireless patches
 Patch50000: compat-wireless-config-fixups.patch
 Patch50001: compat-wireless-change-CONFIG_IWLAGN-CONFIG_IWLWIFI.patch
@@ -1603,6 +1608,10 @@ ApplyPatch ext4-Fix-error-handling-on-inode-bitmap-corruption.patch
 
 ApplyPatch mac80211-fix-rx-key-NULL-ptr-deref-in-promiscuous-mode.patch
 
+#rhbz 773392
+ApplyPatch KVM-x86-extend-struct-x86_emulate_ops-with-get_cpuid.patch
+ApplyPatch KVM-x86-fix-missing-checks-in-syscall-emulation.patch
+
 # END OF PATCH APPLICATIONS
 
 %endif
@@ -2372,6 +2381,10 @@ fi
 # and build.
 
 %changelog
+* Fri Jan 13 2012 Josh Boyer <jwboyer at redhat.com> 3.1.9-1
+- Linux 3.1.9
+- CVE-2012-0045 kvm: syscall instruction induced guest panic (rhbz 773392)
+
 * Wed Jan 11 2012 Josh Boyer <jwboyer at redhat.com>
 - Patch from Stanislaw Gruszka to fix NULL ptr deref in mac80211 (rhbz 769766)
 
diff --git a/sources b/sources
index 41792bf..af7cbe4 100644
--- a/sources
+++ b/sources
@@ -1,3 +1,3 @@
 8d43453f8159b2332ad410b19d86a931  linux-3.1.tar.bz2
-54fac8e4b0b55201e012ef0337a6cc87  patch-3.1.8.bz2
 204381bc537b689edcb15df0efed6467  compat-wireless-3.2-1.tar.bz2
+fae6176f187628bcc5b330cdadc60f9e  patch-3.1.9.bz2


More information about the scm-commits mailing list