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

Ben Hutchings benh at moszumanska.debian.org
Wed Feb 18 02:42:23 UTC 2015


Author: benh
Date: Wed Feb 18 02:42:22 2015
New Revision: 22403

Log:
Add regression fixes for CVE-2014-8133 fix

Added:
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/x86-tls-interpret-an-all-zero-struct-user_desc-as-no.patch
   dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/x86-tls-ldt-stop-checking-lm-in-ldt_empty.patch
Modified:
   dists/squeeze-security/linux-2.6/debian/changelog
   dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze11

Modified: dists/squeeze-security/linux-2.6/debian/changelog
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/changelog	Wed Feb 18 02:06:22 2015	(r22402)
+++ dists/squeeze-security/linux-2.6/debian/changelog	Wed Feb 18 02:42:22 2015	(r22403)
@@ -2,6 +2,8 @@
 
   * [x86] cpu, amd: Add workaround for family 16h, erratum 793 (CVE-2013-6885)
   * [x86] tls: Validate TLS entries to protect espfix (CVE-2014-8133)
+  * [amd64] tls, ldt: Stop checking lm in LDT_empty
+  * [x86] tls: Interpret an all-zero struct user_desc as "no segment"
   * [x86] kvm: Clear paravirt_enabled on KVM guests for espfix32's benefit
     (CVE-2014-8134)
   * netfilter: conntrack: disable generic tracking for known protocols
@@ -15,7 +17,7 @@
     (CVE-2015-1421)
   * ASLR: fix stack randomization on 64-bit systems (CVE-2015-1593)
 
- -- Ben Hutchings <ben at decadent.org.uk>  Tue, 17 Feb 2015 23:15:29 +0000
+ -- Ben Hutchings <ben at decadent.org.uk>  Wed, 18 Feb 2015 02:41:42 +0000
 
 linux-2.6 (2.6.32-48squeeze10) squeeze-lts; urgency=medium
 

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/x86-tls-interpret-an-all-zero-struct-user_desc-as-no.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/x86-tls-interpret-an-all-zero-struct-user_desc-as-no.patch	Wed Feb 18 02:42:22 2015	(r22403)
@@ -0,0 +1,112 @@
+From: Andy Lutomirski <luto at amacapital.net>
+Date: Thu, 22 Jan 2015 11:27:59 -0800
+Subject: x86, tls: Interpret an all-zero struct user_desc as "no segment"
+Origin: https://git.kernel.org/linus/3669ef9fa7d35f573ec9c0e0341b29251c2734a7
+
+The Witcher 2 did something like this to allocate a TLS segment index:
+
+        struct user_desc u_info;
+        bzero(&u_info, sizeof(u_info));
+        u_info.entry_number = (uint32_t)-1;
+
+        syscall(SYS_set_thread_area, &u_info);
+
+Strictly speaking, this code was never correct.  It should have set
+read_exec_only and seg_not_present to 1 to indicate that it wanted
+to find a free slot without putting anything there, or it should
+have put something sensible in the TLS slot if it wanted to allocate
+a TLS entry for real.  The actual effect of this code was to
+allocate a bogus segment that could be used to exploit espfix.
+
+The set_thread_area hardening patches changed the behavior, causing
+set_thread_area to return -EINVAL and crashing the game.
+
+This changes set_thread_area to interpret this as a request to find
+a free slot and to leave it empty, which isn't *quite* what the game
+expects but should be close enough to keep it working.  In
+particular, using the code above to allocate two segments will
+allocate the same segment both times.
+
+According to FrostbittenKing on Github, this fixes The Witcher 2.
+
+If this somehow still causes problems, we could instead allocate
+a limit==0 32-bit data segment, but that seems rather ugly to me.
+
+Fixes: 41bdc78544b8 x86/tls: Validate TLS entries to protect espfix
+Signed-off-by: Andy Lutomirski <luto at amacapital.net>
+Cc: torvalds at linux-foundation.org
+Link: http://lkml.kernel.org/r/0cb251abe1ff0958b8e468a9a9a905b80ae3a746.1421954363.git.luto@amacapital.net
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ arch/x86/include/asm/desc.h | 13 +++++++++++++
+ arch/x86/kernel/tls.c       | 25 +++++++++++++++++++++++--
+ 2 files changed, 36 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
+index fc237fd..a94b82e 100644
+--- a/arch/x86/include/asm/desc.h
++++ b/arch/x86/include/asm/desc.h
+@@ -262,6 +262,19 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+ 	 (info)->seg_not_present	== 1	&&	\
+ 	 (info)->useable		== 0)
+ 
++/* Lots of programs expect an all-zero user_desc to mean "no segment at all". */
++static inline bool LDT_zero(const struct user_desc *info)
++{
++	return (info->base_addr		== 0 &&
++		info->limit		== 0 &&
++		info->contents		== 0 &&
++		info->read_exec_only	== 0 &&
++		info->seg_32bit		== 0 &&
++		info->limit_in_pages	== 0 &&
++		info->seg_not_present	== 0 &&
++		info->useable		== 0);
++}
++
+ static inline void clear_LDT(void)
+ {
+ 	set_ldt(NULL, 0);
+diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c
+index 4e942f3..7fc5e84 100644
+--- a/arch/x86/kernel/tls.c
++++ b/arch/x86/kernel/tls.c
+@@ -29,7 +29,28 @@ static int get_free_idx(void)
+ 
+ static bool tls_desc_okay(const struct user_desc *info)
+ {
+-	if (LDT_empty(info))
++	/*
++	 * For historical reasons (i.e. no one ever documented how any
++	 * of the segmentation APIs work), user programs can and do
++	 * assume that a struct user_desc that's all zeros except for
++	 * entry_number means "no segment at all".  This never actually
++	 * worked.  In fact, up to Linux 3.19, a struct user_desc like
++	 * this would create a 16-bit read-write segment with base and
++	 * limit both equal to zero.
++	 *
++	 * That was close enough to "no segment at all" until we
++	 * hardened this function to disallow 16-bit TLS segments.  Fix
++	 * it up by interpreting these zeroed segments the way that they
++	 * were almost certainly intended to be interpreted.
++	 *
++	 * The correct way to ask for "no segment at all" is to specify
++	 * a user_desc that satisfies LDT_empty.  To keep everything
++	 * working, we accept both.
++	 *
++	 * Note that there's a similar kludge in modify_ldt -- look at
++	 * the distinction between modes 1 and 0x11.
++	 */
++	if (LDT_empty(info) || LDT_zero(info))
+ 		return true;
+ 
+ 	/*
+@@ -71,7 +92,7 @@ static void set_tls_desc(struct task_struct *p, int idx,
+ 	cpu = get_cpu();
+ 
+ 	while (n-- > 0) {
+-		if (LDT_empty(info))
++		if (LDT_empty(info) || LDT_zero(info))
+ 			desc->a = desc->b = 0;
+ 		else
+ 			fill_ldt(desc, info);

Added: dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/x86-tls-ldt-stop-checking-lm-in-ldt_empty.patch
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ dists/squeeze-security/linux-2.6/debian/patches/bugfix/x86/x86-tls-ldt-stop-checking-lm-in-ldt_empty.patch	Wed Feb 18 02:42:22 2015	(r22403)
@@ -0,0 +1,49 @@
+From: Andy Lutomirski <luto at amacapital.net>
+Date: Thu, 22 Jan 2015 11:27:58 -0800
+Subject: x86, tls, ldt: Stop checking lm in LDT_empty
+Origin: https://git.kernel.org/linus/e30ab185c490e9a9381385529e0fd32f0a399495
+
+32-bit programs don't have an lm bit in their ABI, so they can't
+reliably cause LDT_empty to return true without resorting to memset.
+They shouldn't need to do this.
+
+This should fix a longstanding, if minor, issue in all 64-bit kernels
+as well as a potential regression in the TLS hardening code.
+
+Fixes: 41bdc78544b8 x86/tls: Validate TLS entries to protect espfix
+Signed-off-by: Andy Lutomirski <luto at amacapital.net>
+Cc: torvalds at linux-foundation.org
+Link: http://lkml.kernel.org/r/72a059de55e86ad5e2935c80aa91880ddf19d07c.1421954363.git.luto@amacapital.net
+Signed-off-by: Thomas Gleixner <tglx at linutronix.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh at linuxfoundation.org>
+---
+ arch/x86/include/asm/desc.h | 9 ++-------
+ 1 file changed, 2 insertions(+), 7 deletions(-)
+
+diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h
+index 50d033a..fc237fd 100644
+--- a/arch/x86/include/asm/desc.h
++++ b/arch/x86/include/asm/desc.h
+@@ -251,7 +251,8 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+ 		gdt[GDT_ENTRY_TLS_MIN + i] = t->tls_array[i];
+ }
+ 
+-#define _LDT_empty(info)				\
++/* This intentionally ignores lm, since 32-bit apps don't have that field. */
++#define LDT_empty(info)					\
+ 	((info)->base_addr		== 0	&&	\
+ 	 (info)->limit			== 0	&&	\
+ 	 (info)->contents		== 0	&&	\
+@@ -261,12 +262,6 @@ static inline void native_load_tls(struct thread_struct *t, unsigned int cpu)
+ 	 (info)->seg_not_present	== 1	&&	\
+ 	 (info)->useable		== 0)
+ 
+-#ifdef CONFIG_X86_64
+-#define LDT_empty(info) (_LDT_empty(info) && ((info)->lm == 0))
+-#else
+-#define LDT_empty(info) (_LDT_empty(info))
+-#endif
+-
+ static inline void clear_LDT(void)
+ {
+ 	set_ldt(NULL, 0);

Modified: dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze11
==============================================================================
--- dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze11	Wed Feb 18 02:06:22 2015	(r22402)
+++ dists/squeeze-security/linux-2.6/debian/patches/series/48squeeze11	Wed Feb 18 02:42:22 2015	(r22403)
@@ -1,5 +1,7 @@
 + bugfix/x86/x86-cpu-amd-add-workaround-for-family-16h-erratum-79.patch
 + bugfix/x86/x86-tls-validate-tls-entries-to-protect-espfix.patch
++ bugfix/x86/x86-tls-ldt-stop-checking-lm-in-ldt_empty.patch
++ bugfix/x86/x86-tls-interpret-an-all-zero-struct-user_desc-as-no.patch
 + bugfix/x86/x86-kvm-clear-paravirt_enabled-on-kvm-guests-for-espfix32-s-benefit.patch
 + bugfix/all/netfilter-conntrack-disable-generic-tracking-for-kno.patch
 + bugfix/all/isofs-fix-infinite-looping-over-ce-entries.patch



More information about the Kernel-svn-changes mailing list