[kernel] r18848 - in dists/squeeze-security/linux-2.6/debian: . patches/bugfix/x86 patches/series

Dann Frazier dannf at alioth.debian.org
Thu Mar 15 07:19:36 UTC 2012


Author: dannf
Date: Thu Mar 15 07:19:34 2012
New Revision: 18848

Log:
* Fix CVE-2012-0045, with backport work from Ben Hutchings:
  - KVM: extend "struct x86_emulate_ops" with "get_cpuid"
  - KVM: syscall instruction induced guest panic

Added:
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/KVM-extend-struct-x86_emulate_ops-with-get_cpuid.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/KVM-fix-missing-checks-in-syscall-emulation.patch
Modified:
   dists/squeeze-security/linux-2.6/debian/changelog
   dists/squeeze-security/linux-2.6/debian/patches/series/41squeeze1

Modified: dists/squeeze-security/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/changelog	Thu Mar 15 07:10:12 2012	(r18847)
+++ dists/squeeze-security/linux-2.6/debian/changelog	Thu Mar 15 07:19:34 2012	(r18848)
@@ -6,6 +6,9 @@
     expect uid (CVE-2011-1833)
   * KVM: Remove ability to assign devices without IOMMU support
   * KVM: Check permissions before permitting device assignment (CVE-2011-4347)
+  * Fix CVE-2012-0045, with backport work from Ben Hutchings:
+    - KVM: extend "struct x86_emulate_ops" with "get_cpuid"
+    - KVM: syscall instruction induced guest panic
 
   [ Ben Hutchings ]
   * V4L/DVB: v4l2-ioctl: integer overflow in video_usercopy()

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/KVM-extend-struct-x86_emulate_ops-with-get_cpuid.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/KVM-extend-struct-x86_emulate_ops-with-get_cpuid.patch	Thu Mar 15 07:19:34 2012	(r18848)
@@ -0,0 +1,82 @@
+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"
+
+commit 0769c5de24621141c953fbe1f943582d37cb4244 upstream.
+
+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]
+
+[bwh: Backport to 2.6.32:
+ - Don't use emul_to_vcpu
+ - Adjust context]
+
+Signed-off-by: Stephan Baerwolf <stephan.baerwolf at tu-ilmenau.de>
+Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ arch/x86/include/asm/kvm_emulate.h |    2 ++
+ arch/x86/kvm/x86.c                 |   23 +++++++++++++++++++++++
+ 2 files changed, 25 insertions(+), 0 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
+index 5ed59ec..61bf2eb 100644
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -109,6 +109,8 @@ struct x86_emulate_ops {
+ 				unsigned int bytes,
+ 				struct kvm_vcpu *vcpu);
+ 
++	bool (*get_cpuid)(struct x86_emulate_ctxt *ctxt,
++			 u32 *eax, u32 *ebx, u32 *ecx, u32 *edx);
+ };
+ 
+ /* Type, address-of, and value of an instruction's operand. */
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 7cb2a58..5fab056 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2998,12 +2998,35 @@ void kvm_report_emulation_failure(struct kvm_vcpu *vcpu, const char *context)
+ }
+ EXPORT_SYMBOL_GPL(kvm_report_emulation_failure);
+ 
++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(ctxt->vcpu,
++					    *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,
+ 	.fetch               = kvm_fetch_guest_virt,
+ 	.read_emulated       = emulator_read_emulated,
+ 	.write_emulated      = emulator_write_emulated,
+ 	.cmpxchg_emulated    = emulator_cmpxchg_emulated,
++	.get_cpuid           = emulator_get_cpuid,
+ };
+ 
+ static void cache_all_regs(struct kvm_vcpu *vcpu)
+-- 
+1.7.9.1
+

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/KVM-fix-missing-checks-in-syscall-emulation.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/KVM-fix-missing-checks-in-syscall-emulation.patch	Thu Mar 15 07:19:34 2012	(r18848)
@@ -0,0 +1,166 @@
+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
+
+commit bdb42f5afebe208eae90406959383856ae2caf2b upstream.
+
+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]
+
+[bwh: Backport to 2.6.32:
+ - Add the prerequisite read of EFER
+ - Return -1 in the error cases rather than invoking emulate_ud()
+   directly
+ - Adjust context]
+[dannf: fix build by passing x86_emulate_ops through each call]
+
+Signed-off-by: Stephan Baerwolf <stephan.baerwolf at tu-ilmenau.de>
+Signed-off-by: Marcelo Tosatti <mtosatti at redhat.com>
+Signed-off-by: Ben Hutchings <ben at decadent.org.uk>
+---
+ arch/x86/include/asm/kvm_emulate.h |   13 +++++++++
+ arch/x86/kvm/emulate.c             |   53 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 66 insertions(+), 0 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm_emulate.h b/arch/x86/include/asm/kvm_emulate.h
+index 61bf2eb..cc44e3d 100644
+--- a/arch/x86/include/asm/kvm_emulate.h
++++ b/arch/x86/include/asm/kvm_emulate.h
+@@ -192,6 +192,19 @@ struct x86_emulate_ctxt {
+ #define X86EMUL_MODE_HOST X86EMUL_MODE_PROT64
+ #endif
+ 
++/* 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
++
+ int x86_decode_insn(struct x86_emulate_ctxt *ctxt,
+ 		    struct x86_emulate_ops *ops);
+ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt,
+diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
+index 1350e43..aa2d905 100644
+--- a/arch/x86/kvm/emulate.c
++++ b/arch/x86/kvm/emulate.c
+@@ -1495,20 +1495,73 @@ setup_syscalls_segments(struct x86_emulate_ctxt *ctxt,
+ 	ss->present = 1;
+ }
+ 
++static bool em_syscall_is_enabled(struct x86_emulate_ctxt *ctxt,
++				  struct x86_emulate_ops *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
+-emulate_syscall(struct x86_emulate_ctxt *ctxt)
++emulate_syscall(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
+ {
+ 	struct decode_cache *c = &ctxt->decode;
+ 	struct kvm_segment cs, ss;
+ 	u64 msr_data;
++	u64 efer = 0;
+ 
+ 	/* syscall is not available in real mode */
+ 	if (c->lock_prefix || ctxt->mode == X86EMUL_MODE_REAL
+ 	    || ctxt->mode == X86EMUL_MODE_VM86)
+ 		return -1;
+ 
++	if (!(em_syscall_is_enabled(ctxt, ops)))
++		return -1;
++
++	kvm_x86_ops->get_msr(ctxt->vcpu, MSR_EFER, &efer);
+ 	setup_syscalls_segments(ctxt, &cs, &ss);
+ 
++	if (!(efer & EFER_SCE))
++		return -1;
++
+ 	kvm_x86_ops->get_msr(ctxt->vcpu, MSR_STAR, &msr_data);
+ 	msr_data >>= 32;
+ 	cs.selector = (u16)(msr_data & 0xfffc);
+@@ -2342,7 +2395,7 @@ twobyte_insn:
+ 		}
+ 		break;
+ 	case 0x05: 		/* syscall */
+-		if (emulate_syscall(ctxt) == -1)
++		if (emulate_syscall(ctxt, ops) == -1)
+ 			goto cannot_emulate;
+ 		else
+ 			goto writeback;

Modified: dists/squeeze-security/linux-2.6/debian/patches/series/41squeeze1
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/patches/series/41squeeze1	Thu Mar 15 07:10:12 2012	(r18847)
+++ dists/squeeze-security/linux-2.6/debian/patches/series/41squeeze1	Thu Mar 15 07:19:34 2012	(r18848)
@@ -14,3 +14,5 @@
 + bugfix/all/cdrom-use-copy_to_user-without-the-underscores.patch
 + bugfix/all/KVM-Remove-ability-to-assign-a-device-without-iommu-support.patch
 + bugfix/all/KVM-Device-assignment-permission-checks.patch
++ bugfix/x86/KVM-extend-struct-x86_emulate_ops-with-get_cpuid.patch
++ bugfix/x86/KVM-fix-missing-checks-in-syscall-emulation.patch



More information about the Kernel-svn-changes mailing list