linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/5] x86: oops on uaccess faults outside of user addresses
@ 2013-05-22 21:07 Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 1/5] x86: Split "utter crap" pnpbios fixup out of fixup_exception Andy Lutomirski
                   ` (6 more replies)
  0 siblings, 7 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-05-22 21:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, trinity, Andy Lutomirski

Currently, __get_user can't trigger an OOPS -- any exception will be
caught and return -EFAULT.  This means that, if an access_ok check is
missing somewhere, then an attacker can freely use it to probe for valid
kernel mappings.

This series annotates all of the exception fixups as "catch anything" or
"catch valid uaccess faults", and skips the fixup (and hence oopses) if
an instruction of the latter type faults for any reason other than a
page fault to a user address.

I know of only one bug of this type; it's fixed in patch 5.

Perhaps surprisingly, this seems to survive Trinity fairly well.

Andy Lutomirski (5):
  x86: Split "utter crap" pnpbios fixup out of fixup_exception
  x86: Clean up extable entry format (and free up a bit)
  x86: Annotate _ASM_EXTABLE users to distinguish uaccess from
    everything else
  x86: Don't fixup uaccess faults to kernel or non-canonical addresses
  net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg

 arch/x86/ia32/ia32entry.S             |   4 +-
 arch/x86/include/asm/asm.h            |  75 ++++++++----
 arch/x86/include/asm/fpu-internal.h   |   6 +-
 arch/x86/include/asm/futex.h          |   8 +-
 arch/x86/include/asm/kvm_host.h       |   2 +-
 arch/x86/include/asm/msr.h            |   4 +-
 arch/x86/include/asm/segment.h        |   2 +-
 arch/x86/include/asm/special_insns.h  |   2 +-
 arch/x86/include/asm/traps.h          |   6 +
 arch/x86/include/asm/uaccess.h        |  10 +-
 arch/x86/include/asm/word-at-a-time.h |   2 +-
 arch/x86/include/asm/xsave.h          |   6 +-
 arch/x86/kernel/entry_32.S            |  26 ++---
 arch/x86/kernel/entry_64.S            |   6 +-
 arch/x86/kernel/ftrace.c              |   4 +-
 arch/x86/kernel/kprobes/core.c        |   4 +-
 arch/x86/kernel/test_nx.c             |   2 +-
 arch/x86/kernel/test_rodata.c         |   2 +-
 arch/x86/kernel/traps.c               |  12 +-
 arch/x86/kvm/emulate.c                |   4 +-
 arch/x86/lib/checksum_32.S            |   4 +-
 arch/x86/lib/copy_user_64.S           |  50 ++++----
 arch/x86/lib/copy_user_nocache_64.S   |  44 +++----
 arch/x86/lib/csum-copy_64.S           |   6 +-
 arch/x86/lib/getuser.S                |  12 +-
 arch/x86/lib/mmx_32.c                 |  12 +-
 arch/x86/lib/msr-reg.S                |   4 +-
 arch/x86/lib/putuser.S                |  10 +-
 arch/x86/lib/usercopy_32.c            | 212 +++++++++++++++++-----------------
 arch/x86/lib/usercopy_64.c            |   4 +-
 arch/x86/mm/extable.c                 |  41 +++----
 arch/x86/mm/fault.c                   |  36 ++++--
 arch/x86/mm/init_32.c                 |   2 +-
 arch/x86/um/checksum_32.S             |   4 +-
 arch/x86/xen/xen-asm_32.S             |   2 +-
 net/socket.c                          |  33 +++++-
 36 files changed, 375 insertions(+), 288 deletions(-)

-- 
1.8.1.4


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH 1/5] x86: Split "utter crap" pnpbios fixup out of fixup_exception
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
@ 2013-05-22 21:07 ` Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 2/5] x86: Clean up extable entry format (and free up a bit) Andy Lutomirski
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-05-22 21:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, trinity, Andy Lutomirski

It has odd semantics, and it's only applicable (AFAICS) to #GP and #PF.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 arch/x86/include/asm/traps.h |  6 ++++++
 arch/x86/kernel/traps.c      |  2 ++
 arch/x86/mm/extable.c        | 14 --------------
 arch/x86/mm/fault.c          | 19 +++++++++++++++++++
 4 files changed, 27 insertions(+), 14 deletions(-)

diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
index 88eae2a..55521de 100644
--- a/arch/x86/include/asm/traps.h
+++ b/arch/x86/include/asm/traps.h
@@ -89,6 +89,12 @@ asmlinkage void smp_thermal_interrupt(void);
 asmlinkage void mce_threshold_interrupt(void);
 #endif
 
+#ifdef CONFIG_PNPBIOS
+extern void fixup_pnpbios_exception(struct pt_regs *regs);
+#else
+static inline void fixup_pnpbios_exception(struct pt_regs *regs) {}
+#endif
+
 /* Interrupts/Exceptions */
 enum {
 	X86_TRAP_DE = 0,	/*  0, Divide-by-zero */
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 68bda7a..8647670 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -275,6 +275,8 @@ do_general_protection(struct pt_regs *regs, long error_code)
 
 	tsk = current;
 	if (!user_mode(regs)) {
+		fixup_pnpbios_exception(regs);  /* Might not return */
+
 		if (fixup_exception(regs))
 			goto exit;
 
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 903ec1e..82e4ae8 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -19,20 +19,6 @@ int fixup_exception(struct pt_regs *regs)
 	const struct exception_table_entry *fixup;
 	unsigned long new_ip;
 
-#ifdef CONFIG_PNPBIOS
-	if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
-		extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
-		extern u32 pnp_bios_is_utter_crap;
-		pnp_bios_is_utter_crap = 1;
-		printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
-		__asm__ volatile(
-			"movl %0, %%esp\n\t"
-			"jmp *%1\n\t"
-			: : "g" (pnp_bios_fault_esp), "g" (pnp_bios_fault_eip));
-		panic("do_trap: can't hit this");
-	}
-#endif
-
 	fixup = search_exception_tables(regs->ip);
 	if (fixup) {
 		new_ip = ex_fixup_addr(fixup);
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 0e88336..58afb50 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -569,6 +569,23 @@ static int is_f00f_bug(struct pt_regs *regs, unsigned long address)
 	return 0;
 }
 
+#ifdef CONFIG_PNPBIOS
+void fixup_pnpbios_exception(struct pt_regs *regs)
+{
+	if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) {
+		extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp;
+		extern u32 pnp_bios_is_utter_crap;
+		pnp_bios_is_utter_crap = 1;
+		printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n");
+		__asm__ volatile(
+			"movl %0, %%esp\n\t"
+			"jmp *%1\n\t"
+			: : "g" (pnp_bios_fault_esp), "g" (pnp_bios_fault_eip));
+		panic("do_trap: can't hit this");
+	}
+}
+#endif
+
 static const char nx_warning[] = KERN_CRIT
 "kernel tried to execute NX-protected page - exploit attempt? (uid: %d)\n";
 
@@ -636,6 +653,8 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 	unsigned long flags;
 	int sig;
 
+	fixup_pnpbios_exception(regs);  /* Might not return */
+
 	/* Are we prepared to handle this kernel fault? */
 	if (fixup_exception(regs)) {
 		if (current_thread_info()->sig_on_uaccess_error && signal) {
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 2/5] x86: Clean up extable entry format (and free up a bit)
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 1/5] x86: Split "utter crap" pnpbios fixup out of fixup_exception Andy Lutomirski
@ 2013-05-22 21:07 ` Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 3/5] x86: Annotate _ASM_EXTABLE users to distinguish uaccess from everything else Andy Lutomirski
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-05-22 21:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, trinity, Andy Lutomirski

This adds two bits of fixup class information to a fixup entry,
generalizing the uaccess_err hack currently in place.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 arch/x86/include/asm/asm.h | 70 ++++++++++++++++++++++++++++++----------------
 arch/x86/mm/extable.c      | 22 +++++++++------
 2 files changed, 60 insertions(+), 32 deletions(-)

diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index 1c2d247..fa47fd4 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -39,34 +39,56 @@
 #define _ASM_DI		__ASM_REG(di)
 
 /* Exception table entry */
-#ifdef __ASSEMBLY__
-# define _ASM_EXTABLE(from,to)					\
-	.pushsection "__ex_table","a" ;				\
-	.balign 8 ;						\
-	.long (from) - . ;					\
-	.long (to) - . ;					\
-	.popsection
 
-# define _ASM_EXTABLE_EX(from,to)				\
-	.pushsection "__ex_table","a" ;				\
-	.balign 8 ;						\
-	.long (from) - . ;					\
-	.long (to) - . + 0x7ffffff0 ;				\
+/*
+ * An exception table entry is 64 bits.  The first 32 bits are the offset
+ * from that entry to the potentially faulting instruction.  sortextable
+ * relies on that exact encoding.  The second 32 bits encode the fault
+ * handler address.
+ *
+ * We want to stick two extra bits of handler class into the fault handler
+ * address.  All of these are generated by relocations, so we can only
+ * rely on addition.  We therefore emit:
+ *
+ * (target - here) + (class) + 0x20000000
+ *
+ * This has the property that the two high bits are the class and the
+ * rest is easy to decode.
+ */
+
+/* There are two bits of extable entry class, added to a signed offset. */
+#define _EXTABLE_CLASS_DEFAULT	0		/* standard uaccess fixup */
+#define _EXTABLE_CLASS_EX	0x80000000	/* uaccess + set uaccess_err */
+
+/*
+ * The biases are the class constants + 0x20000000, as signed integers.
+ * This can't use ordinary arithmetic -- the assembler isn't that smart.
+ */
+#define _EXTABLE_BIAS_DEFAULT	0x20000000
+#define _EXTABLE_BIAS_EX	0x20000000 - 0x80000000
+
+#ifdef __ASSEMBLY__
+# define _EXPAND_EXTABLE_BIAS(x) x
+# define _ASM_EXTABLE_CLASS(from,to,bias)				\
+	.pushsection "__ex_table","a" ;					\
+	.balign 8 ;							\
+	.long (from) - . ;						\
+	.long (to) - . + _EXPAND_EXTABLE_BIAS(bias) ;			\
 	.popsection
 #else
-# define _ASM_EXTABLE(from,to)					\
-	" .pushsection \"__ex_table\",\"a\"\n"			\
-	" .balign 8\n"						\
-	" .long (" #from ") - .\n"				\
-	" .long (" #to ") - .\n"				\
-	" .popsection\n"
-
-# define _ASM_EXTABLE_EX(from,to)				\
-	" .pushsection \"__ex_table\",\"a\"\n"			\
-	" .balign 8\n"						\
-	" .long (" #from ") - .\n"				\
-	" .long (" #to ") - . + 0x7ffffff0\n"			\
+# define _EXPAND_EXTABLE_BIAS(x) #x
+# define _ASM_EXTABLE_CLASS(from,to,bias)				\
+	" .pushsection \"__ex_table\",\"a\"\n"				\
+	" .balign 8\n"							\
+	" .long (" #from ") - .\n"					\
+	" .long (" #to ") - . + " _EXPAND_EXTABLE_BIAS(bias) "\n"	\
 	" .popsection\n"
 #endif
 
+#define _ASM_EXTABLE(from,to)						\
+	_ASM_EXTABLE_CLASS(from, to, _EXTABLE_BIAS_DEFAULT)
+
+#define _ASM_EXTABLE_EX(from,to)					\
+	_ASM_EXTABLE_CLASS(from, to, _EXTABLE_BIAS_EX)
+
 #endif /* _ASM_X86_ASM_H */
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 82e4ae8..85f45d4 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -8,25 +8,34 @@ ex_insn_addr(const struct exception_table_entry *x)
 {
 	return (unsigned long)&x->insn + x->insn;
 }
+
+static inline unsigned int
+ex_class(const struct exception_table_entry *x)
+{
+	return (unsigned int)x->fixup & 0xC0000000;
+}
+
 static inline unsigned long
 ex_fixup_addr(const struct exception_table_entry *x)
 {
-	return (unsigned long)&x->fixup + x->fixup;
+	long offset = (long)((u32)x->fixup & 0x3fffffff) - (long)0x20000000;
+	return (unsigned long)&x->fixup + offset;
 }
 
 int fixup_exception(struct pt_regs *regs)
 {
 	const struct exception_table_entry *fixup;
 	unsigned long new_ip;
+	unsigned int class;
 
 	fixup = search_exception_tables(regs->ip);
 	if (fixup) {
+		class = ex_class(fixup);
 		new_ip = ex_fixup_addr(fixup);
 
-		if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
+		if (class == _EXTABLE_CLASS_EX) {
 			/* Special hack for uaccess_err */
 			current_thread_info()->uaccess_err = 1;
-			new_ip -= 0x7ffffff0;
 		}
 		regs->ip = new_ip;
 		return 1;
@@ -39,18 +48,15 @@ int fixup_exception(struct pt_regs *regs)
 int __init early_fixup_exception(unsigned long *ip)
 {
 	const struct exception_table_entry *fixup;
-	unsigned long new_ip;
 
 	fixup = search_exception_tables(*ip);
 	if (fixup) {
-		new_ip = ex_fixup_addr(fixup);
-
-		if (fixup->fixup - fixup->insn >= 0x7ffffff0 - 4) {
+		if (ex_class(fixup) == _EXTABLE_CLASS_EX) {
 			/* uaccess handling not supported during early boot */
 			return 0;
 		}
 
-		*ip = new_ip;
+		*ip = ex_fixup_addr(fixup);
 		return 1;
 	}
 
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 3/5] x86: Annotate _ASM_EXTABLE users to distinguish uaccess from everything else
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 1/5] x86: Split "utter crap" pnpbios fixup out of fixup_exception Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 2/5] x86: Clean up extable entry format (and free up a bit) Andy Lutomirski
@ 2013-05-22 21:07 ` Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 4/5] x86: Don't fixup uaccess faults to kernel or non-canonical addresses Andy Lutomirski
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-05-22 21:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, trinity, Andy Lutomirski, kvm

The idea is that the kernel can be much more careful fixing up
uaccess exceptions -- page faults on user addresses are the only
legitimate reason for a uaccess instruction to fault.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

I'm not 100% sure what's happening in the KVM code.  Can someone familiar
with it take a look?

 arch/x86/ia32/ia32entry.S             |   4 +-
 arch/x86/include/asm/asm.h            |  13 ++-
 arch/x86/include/asm/fpu-internal.h   |   6 +-
 arch/x86/include/asm/futex.h          |   8 +-
 arch/x86/include/asm/kvm_host.h       |   2 +-
 arch/x86/include/asm/msr.h            |   4 +-
 arch/x86/include/asm/segment.h        |   2 +-
 arch/x86/include/asm/special_insns.h  |   2 +-
 arch/x86/include/asm/uaccess.h        |   8 +-
 arch/x86/include/asm/word-at-a-time.h |   2 +-
 arch/x86/include/asm/xsave.h          |   6 +-
 arch/x86/kernel/entry_32.S            |  26 ++---
 arch/x86/kernel/entry_64.S            |   6 +-
 arch/x86/kernel/ftrace.c              |   4 +-
 arch/x86/kernel/test_nx.c             |   2 +-
 arch/x86/kernel/test_rodata.c         |   2 +-
 arch/x86/kvm/emulate.c                |   4 +-
 arch/x86/lib/checksum_32.S            |   4 +-
 arch/x86/lib/copy_user_64.S           |  50 ++++----
 arch/x86/lib/copy_user_nocache_64.S   |  44 +++----
 arch/x86/lib/csum-copy_64.S           |   6 +-
 arch/x86/lib/getuser.S                |  12 +-
 arch/x86/lib/mmx_32.c                 |  12 +-
 arch/x86/lib/msr-reg.S                |   4 +-
 arch/x86/lib/putuser.S                |  10 +-
 arch/x86/lib/usercopy_32.c            | 212 +++++++++++++++++-----------------
 arch/x86/lib/usercopy_64.c            |   4 +-
 arch/x86/mm/init_32.c                 |   2 +-
 arch/x86/um/checksum_32.S             |   4 +-
 arch/x86/xen/xen-asm_32.S             |   2 +-
 30 files changed, 236 insertions(+), 231 deletions(-)

diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 474dc1b..8d3b5c2 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -149,7 +149,7 @@ ENTRY(ia32_sysenter_target)
  	   32bit zero extended */ 
 	ASM_STAC
 1:	movl	(%rbp),%ebp
-	_ASM_EXTABLE(1b,ia32_badarg)
+	_ASM_EXTABLE_UACCESS(1b,ia32_badarg)
 	ASM_CLAC
 	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
@@ -306,7 +306,7 @@ ENTRY(ia32_cstar_target)
 	/* hardware stack frame is complete now */	
 	ASM_STAC
 1:	movl	(%r8),%r9d
-	_ASM_EXTABLE(1b,ia32_badarg)
+	_ASM_EXTABLE_UACCESS(1b,ia32_badarg)
 	ASM_CLAC
 	orl     $TS_COMPAT,TI_status+THREAD_INFO(%rsp,RIP-ARGOFFSET)
 	testl   $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
diff --git a/arch/x86/include/asm/asm.h b/arch/x86/include/asm/asm.h
index fa47fd4..f48a850 100644
--- a/arch/x86/include/asm/asm.h
+++ b/arch/x86/include/asm/asm.h
@@ -57,14 +57,16 @@
  */
 
 /* There are two bits of extable entry class, added to a signed offset. */
-#define _EXTABLE_CLASS_DEFAULT	0		/* standard uaccess fixup */
+#define _EXTABLE_CLASS_UACCESS	0		/* standard uaccess fixup */
+#define _EXTABLE_CLASS_ANY	0x40000000	/* catch any exception */
 #define _EXTABLE_CLASS_EX	0x80000000	/* uaccess + set uaccess_err */
 
 /*
  * The biases are the class constants + 0x20000000, as signed integers.
  * This can't use ordinary arithmetic -- the assembler isn't that smart.
  */
-#define _EXTABLE_BIAS_DEFAULT	0x20000000
+#define _EXTABLE_BIAS_UACCESS	0x20000000
+#define _EXTABLE_BIAS_ANY	0x20000000 + 0x40000000
 #define _EXTABLE_BIAS_EX	0x20000000 - 0x80000000
 
 #ifdef __ASSEMBLY__
@@ -85,8 +87,11 @@
 	" .popsection\n"
 #endif
 
-#define _ASM_EXTABLE(from,to)						\
-	_ASM_EXTABLE_CLASS(from, to, _EXTABLE_BIAS_DEFAULT)
+#define _ASM_EXTABLE_UACCESS(from,to)					\
+	_ASM_EXTABLE_CLASS(from, to, _EXTABLE_BIAS_UACCESS)
+
+#define _ASM_EXTABLE_ANY(from,to)					\
+	_ASM_EXTABLE_CLASS(from, to, _EXTABLE_BIAS_ANY)
 
 #define _ASM_EXTABLE_EX(from,to)					\
 	_ASM_EXTABLE_CLASS(from, to, _EXTABLE_BIAS_EX)
diff --git a/arch/x86/include/asm/fpu-internal.h b/arch/x86/include/asm/fpu-internal.h
index e25cc33..7f86031 100644
--- a/arch/x86/include/asm/fpu-internal.h
+++ b/arch/x86/include/asm/fpu-internal.h
@@ -133,7 +133,7 @@ static inline void sanitize_i387_state(struct task_struct *tsk)
 		     "3:  movl $-1,%[err]\n"				\
 		     "    jmp  2b\n"					\
 		     ".previous\n"					\
-		     _ASM_EXTABLE(1b, 3b)				\
+		     _ASM_EXTABLE_UACCESS(1b, 3b)				\
 		     : [err] "=r" (err), output				\
 		     : "0"(0), input);					\
 	err;								\
@@ -148,7 +148,7 @@ static inline void sanitize_i387_state(struct task_struct *tsk)
 		     "3:  movl $-1,%[err]\n"				\
 		     "    jmp  2b\n"					\
 		     ".previous\n"					\
-		     _ASM_EXTABLE(1b, 3b)				\
+		     _ASM_EXTABLE_ANY(1b, 3b)				\
 		     : [err] "=r" (err), output				\
 		     : "0"(0), input);					\
 	err;								\
@@ -356,7 +356,7 @@ static inline void __drop_fpu(struct task_struct *tsk)
 		/* Ignore delayed exceptions from user space */
 		asm volatile("1: fwait\n"
 			     "2:\n"
-			     _ASM_EXTABLE(1b, 2b));
+			     _ASM_EXTABLE_ANY(1b, 2b));
 		__thread_fpu_end(tsk);
 	}
 }
diff --git a/arch/x86/include/asm/futex.h b/arch/x86/include/asm/futex.h
index be27ba1..606006c 100644
--- a/arch/x86/include/asm/futex.h
+++ b/arch/x86/include/asm/futex.h
@@ -19,7 +19,7 @@
 		     "3:\tmov\t%3, %1\n"			\
 		     "\tjmp\t2b\n"				\
 		     "\t.previous\n"				\
-		     _ASM_EXTABLE(1b, 3b)			\
+		     _ASM_EXTABLE_UACCESS(1b, 3b)		\
 		     : "=r" (oldval), "=r" (ret), "+m" (*uaddr)	\
 		     : "i" (-EFAULT), "0" (oparg), "1" (0))
 
@@ -35,8 +35,8 @@
 		     "4:\tmov\t%5, %1\n"			\
 		     "\tjmp\t3b\n"				\
 		     "\t.previous\n"				\
-		     _ASM_EXTABLE(1b, 4b)			\
-		     _ASM_EXTABLE(2b, 4b)			\
+		     _ASM_EXTABLE_UACCESS(1b, 4b)		\
+		     _ASM_EXTABLE_UACCESS(2b, 4b)		\
 		     : "=&a" (oldval), "=&r" (ret),		\
 		       "+m" (*uaddr), "=&r" (tem)		\
 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
@@ -122,7 +122,7 @@ static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
 		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
-		     _ASM_EXTABLE(1b, 3b)
+		     _ASM_EXTABLE_UACCESS(1b, 3b)
 		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
 		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 4979778..96c576f 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -986,7 +986,7 @@ extern bool kvm_rebooting;
 	__ASM_SIZE(push) " $666b \n\t"	      \
 	"call kvm_spurious_fault \n\t"	      \
 	".popsection \n\t" \
-	_ASM_EXTABLE(666b, 667b)
+	_ASM_EXTABLE_ANY(666b, 667b)
 
 #define __kvm_handle_fault_on_reboot(insn)		\
 	____kvm_handle_fault_on_reboot(insn, "")
diff --git a/arch/x86/include/asm/msr.h b/arch/x86/include/asm/msr.h
index 9264802..54e4bea 100644
--- a/arch/x86/include/asm/msr.h
+++ b/arch/x86/include/asm/msr.h
@@ -75,7 +75,7 @@ static inline unsigned long long native_read_msr_safe(unsigned int msr,
 		     ".section .fixup,\"ax\"\n\t"
 		     "3:  mov %[fault],%[err] ; jmp 1b\n\t"
 		     ".previous\n\t"
-		     _ASM_EXTABLE(2b, 3b)
+		     _ASM_EXTABLE_ANY(2b, 3b)
 		     : [err] "=r" (*err), EAX_EDX_RET(val, low, high)
 		     : "c" (msr), [fault] "i" (-EIO));
 	return EAX_EDX_VAL(val, low, high);
@@ -97,7 +97,7 @@ notrace static inline int native_write_msr_safe(unsigned int msr,
 		     ".section .fixup,\"ax\"\n\t"
 		     "3:  mov %[fault],%[err] ; jmp 1b\n\t"
 		     ".previous\n\t"
-		     _ASM_EXTABLE(2b, 3b)
+		     _ASM_EXTABLE_ANY(2b, 3b)
 		     : [err] "=a" (err)
 		     : "c" (msr), "0" (low), "d" (high),
 		       [fault] "i" (-EIO)
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h
index c48a950..89cac10 100644
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -231,7 +231,7 @@ do {									\
 		     "		jmp 1b				\n"	\
 		     ".previous					\n"	\
 									\
-		     _ASM_EXTABLE(1b, 2b)				\
+		     _ASM_EXTABLE_ANY(1b, 2b)				\
 									\
 		     : "+r" (__val) : : "memory");			\
 } while (0)
diff --git a/arch/x86/include/asm/special_insns.h b/arch/x86/include/asm/special_insns.h
index 41fc93a..30b6f01 100644
--- a/arch/x86/include/asm/special_insns.h
+++ b/arch/x86/include/asm/special_insns.h
@@ -69,7 +69,7 @@ static inline unsigned long native_read_cr4_safe(void)
 #ifdef CONFIG_X86_32
 	asm volatile("1: mov %%cr4, %0\n"
 		     "2:\n"
-		     _ASM_EXTABLE(1b, 2b)
+		     _ASM_EXTABLE_ANY(1b, 2b)
 		     : "=r" (val), "=m" (__force_order) : "0" (0));
 #else
 	val = native_read_cr4();
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 5ee2687..ed2d77a 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -188,8 +188,8 @@ __typeof__(__builtin_choose_expr(sizeof(x) > sizeof(0UL), 0ULL, 0UL))
 		     "4:	movl %3,%0\n"				\
 		     "	jmp 3b\n"					\
 		     ".previous\n"					\
-		     _ASM_EXTABLE(1b, 4b)				\
-		     _ASM_EXTABLE(2b, 4b)				\
+		     _ASM_EXTABLE_UACCESS(1b, 4b)			\
+		     _ASM_EXTABLE_UACCESS(2b, 4b)			\
 		     : "=r" (err)					\
 		     : "A" (x), "r" (addr), "i" (errret), "0" (err))
 
@@ -352,7 +352,7 @@ do {									\
 		     "	xor"itype" %"rtype"1,%"rtype"1\n"		\
 		     "	jmp 2b\n"					\
 		     ".previous\n"					\
-		     _ASM_EXTABLE(1b, 3b)				\
+		     _ASM_EXTABLE_UACCESS(1b, 3b)			\
 		     : "=r" (err), ltype(x)				\
 		     : "m" (__m(addr)), "i" (errret), "0" (err))
 
@@ -416,7 +416,7 @@ struct __large_struct { unsigned long buf[100]; };
 		     "3:	mov %3,%0\n"				\
 		     "	jmp 2b\n"					\
 		     ".previous\n"					\
-		     _ASM_EXTABLE(1b, 3b)				\
+		     _ASM_EXTABLE_UACCESS(1b, 3b)			\
 		     : "=r"(err)					\
 		     : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
 
diff --git a/arch/x86/include/asm/word-at-a-time.h b/arch/x86/include/asm/word-at-a-time.h
index 5b238981..aa80911 100644
--- a/arch/x86/include/asm/word-at-a-time.h
+++ b/arch/x86/include/asm/word-at-a-time.h
@@ -94,7 +94,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr)
 		"shr %%cl,%0\n\t"
 		"jmp 2b\n"
 		".previous\n"
-		_ASM_EXTABLE(1b, 3b)
+		_ASM_EXTABLE_ANY(1b, 3b)
 		:"=&r" (ret),"=&c" (dummy)
 		:"m" (*(unsigned long *)addr),
 		 "i" (-sizeof(unsigned long)),
diff --git a/arch/x86/include/asm/xsave.h b/arch/x86/include/asm/xsave.h
index 0415cda..7859666 100644
--- a/arch/x86/include/asm/xsave.h
+++ b/arch/x86/include/asm/xsave.h
@@ -50,7 +50,7 @@ static inline int fpu_xrstor_checking(struct xsave_struct *fx)
 		     "3:  movl $-1,%[err]\n"
 		     "    jmp  2b\n"
 		     ".previous\n"
-		     _ASM_EXTABLE(1b, 3b)
+		     _ASM_EXTABLE_ANY(1b, 3b)
 		     : [err] "=r" (err)
 		     : "D" (fx), "m" (*fx), "a" (-1), "d" (-1), "0" (0)
 		     : "memory");
@@ -77,7 +77,7 @@ static inline int xsave_user(struct xsave_struct __user *buf)
 			     "3:  movl $-1,%[err]\n"
 			     "    jmp  2b\n"
 			     ".previous\n"
-			     _ASM_EXTABLE(1b,3b)
+			     _ASM_EXTABLE_UACCESS(1b,3b)
 			     : [err] "=r" (err)
 			     : "D" (buf), "a" (-1), "d" (-1), "0" (0)
 			     : "memory");
@@ -98,7 +98,7 @@ static inline int xrestore_user(struct xsave_struct __user *buf, u64 mask)
 			     "3:  movl $-1,%[err]\n"
 			     "    jmp  2b\n"
 			     ".previous\n"
-			     _ASM_EXTABLE(1b,3b)
+			     _ASM_EXTABLE_UACCESS(1b,3b)
 			     : [err] "=r" (err)
 			     : "D" (xstate), "a" (lmask), "d" (hmask), "0" (0)
 			     : "memory");	/* memory required? */
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index 8f3e2de..fc85bb9 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -154,7 +154,7 @@
 99:	movl $0, (%esp)
 	jmp 98b
 .popsection
-	_ASM_EXTABLE(98b,99b)
+	_ASM_EXTABLE_ANY(98b,99b)
 .endm
 
 .macro PTGS_TO_GS
@@ -165,7 +165,7 @@
 99:	movl $0, PT_GS(%esp)
 	jmp 98b
 .popsection
-	_ASM_EXTABLE(98b,99b)
+	_ASM_EXTABLE_ANY(98b,99b)
 .endm
 
 .macro GS_TO_REG reg
@@ -248,9 +248,9 @@
 6:	movl $0, (%esp)
 	jmp 3b
 .popsection
-	_ASM_EXTABLE(1b,4b)
-	_ASM_EXTABLE(2b,5b)
-	_ASM_EXTABLE(3b,6b)
+	_ASM_EXTABLE_ANY(1b,4b)
+	_ASM_EXTABLE_ANY(2b,5b)
+	_ASM_EXTABLE_ANY(3b,6b)
 	POP_GS_EX
 .endm
 
@@ -426,7 +426,7 @@ sysenter_past_esp:
 1:	movl (%ebp),%ebp
 	ASM_CLAC
 	movl %ebp,PT_EBP(%esp)
-	_ASM_EXTABLE(1b,syscall_fault)
+	_ASM_EXTABLE_UACCESS(1b,syscall_fault)
 
 	GET_THREAD_INFO(%ebp)
 
@@ -494,7 +494,7 @@ sysexit_audit:
 2:	movl $0,PT_FS(%esp)
 	jmp 1b
 .popsection
-	_ASM_EXTABLE(1b,2b)
+	_ASM_EXTABLE_ANY(1b,2b)
 	PTGS_TO_GS_EX
 ENDPROC(ia32_sysenter_target)
 
@@ -550,7 +550,7 @@ ENTRY(iret_exc)
 	pushl $do_iret_error
 	jmp error_code
 .previous
-	_ASM_EXTABLE(irq_return,iret_exc)
+	_ASM_EXTABLE_ANY(irq_return,iret_exc)
 
 	CFI_RESTORE_STATE
 ldt_ss:
@@ -849,7 +849,7 @@ END(device_not_available)
 #ifdef CONFIG_PARAVIRT
 ENTRY(native_iret)
 	iret
-	_ASM_EXTABLE(native_iret, iret_exc)
+	_ASM_EXTABLE_ANY(native_iret, iret_exc)
 END(native_iret)
 
 ENTRY(native_irq_enable_sysexit)
@@ -1040,10 +1040,10 @@ ENTRY(xen_failsafe_callback)
 	movl %eax,16(%esp)
 	jmp 4b
 .previous
-	_ASM_EXTABLE(1b,6b)
-	_ASM_EXTABLE(2b,7b)
-	_ASM_EXTABLE(3b,8b)
-	_ASM_EXTABLE(4b,9b)
+	_ASM_EXTABLE_ANY(1b,6b)
+	_ASM_EXTABLE_ANY(2b,7b)
+	_ASM_EXTABLE_ANY(3b,8b)
+	_ASM_EXTABLE_ANY(4b,9b)
 ENDPROC(xen_failsafe_callback)
 
 BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index c1d01e6..be185cd 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1056,12 +1056,12 @@ restore_args:
 
 irq_return:
 	INTERRUPT_RETURN
-	_ASM_EXTABLE(irq_return, bad_iret)
+	_ASM_EXTABLE_ANY(irq_return, bad_iret)
 
 #ifdef CONFIG_PARAVIRT
 ENTRY(native_iret)
 	iretq
-	_ASM_EXTABLE(native_iret, bad_iret)
+	_ASM_EXTABLE_ANY(native_iret, bad_iret)
 #endif
 
 	.section .fixup,"ax"
@@ -1319,7 +1319,7 @@ gs_change:
 	CFI_ENDPROC
 END(native_load_gs_index)
 
-	_ASM_EXTABLE(gs_change,bad_gs)
+	_ASM_EXTABLE_ANY(gs_change,bad_gs)
 	.section .fixup,"ax"
 	/* running with kernelgs */
 bad_gs:
diff --git a/arch/x86/kernel/ftrace.c b/arch/x86/kernel/ftrace.c
index 42a392a..c6c4ebf 100644
--- a/arch/x86/kernel/ftrace.c
+++ b/arch/x86/kernel/ftrace.c
@@ -740,8 +740,8 @@ void prepare_ftrace_return(unsigned long *parent, unsigned long self_addr,
 		"   jmp 3b\n"
 		".previous\n"
 
-		_ASM_EXTABLE(1b, 4b)
-		_ASM_EXTABLE(2b, 4b)
+		_ASM_EXTABLE_ANY(1b, 4b)
+		_ASM_EXTABLE_ANY(2b, 4b)
 
 		: [old] "=&r" (old), [faulted] "=r" (faulted)
 		: [parent] "r" (parent), [return_hooker] "r" (return_hooker)
diff --git a/arch/x86/kernel/test_nx.c b/arch/x86/kernel/test_nx.c
index 3f92ce0..770cb68 100644
--- a/arch/x86/kernel/test_nx.c
+++ b/arch/x86/kernel/test_nx.c
@@ -92,7 +92,7 @@ static noinline int test_address(void *address)
 		"2:	mov %[zero], %[rslt]\n"
 		"	ret\n"
 		".previous\n"
-		_ASM_EXTABLE(0b,2b)
+		_ASM_EXTABLE_ANY(0b,2b)
 		: [rslt] "=r" (result)
 		: [fake_code] "r" (address), [zero] "r" (0UL), "0" (result)
 	);
diff --git a/arch/x86/kernel/test_rodata.c b/arch/x86/kernel/test_rodata.c
index b79133a..624e6af 100644
--- a/arch/x86/kernel/test_rodata.c
+++ b/arch/x86/kernel/test_rodata.c
@@ -43,7 +43,7 @@ int rodata_test(void)
 		".section .fixup,\"ax\"\n"
 		"2:	jmp 1b\n"
 		".previous\n"
-		_ASM_EXTABLE(0b,2b)
+		_ASM_EXTABLE_ANY(0b,2b)
 		: [rslt] "=r" (result)
 		: [rodata_test] "r" (&rodata_test_data), [zero] "r" (0UL)
 	);
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index a9c9d3e..fa7f66a 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -548,7 +548,7 @@ FOP_END;
 			"3: movb $1, %4 \n\t"				\
 			"jmp 2b \n\t"					\
 			".popsection \n\t"				\
-			_ASM_EXTABLE(1b, 3b)				\
+			_ASM_EXTABLE_UACCESS(1b, 3b)			\
 			: "=m" ((ctxt)->eflags), "=&r" (_tmp),		\
 			  "+a" (*rax), "+d" (*rdx), "+qm"(_ex)		\
 			: "i" (EFLAGS_MASK), "m" ((ctxt)->src.val));	\
@@ -4479,7 +4479,7 @@ static int flush_pending_x87_faults(struct x86_emulate_ctxt *ctxt)
 		     "movb $1, %[fault] \n\t"
 		     "jmp 2b \n\t"
 		     ".popsection \n\t"
-		     _ASM_EXTABLE(1b, 3b)
+		     _ASM_EXTABLE_ANY(1b, 3b)
 		     : [fault]"+qm"(fault));
 	ctxt->ops->put_fpu(ctxt);
 
diff --git a/arch/x86/lib/checksum_32.S b/arch/x86/lib/checksum_32.S
index 2af5df3..20523f0 100644
--- a/arch/x86/lib/checksum_32.S
+++ b/arch/x86/lib/checksum_32.S
@@ -283,11 +283,11 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
 
 #define SRC(y...)			\
 	9999: y;			\
-	_ASM_EXTABLE(9999b, 6001f)
+	_ASM_EXTABLE_UACCESS(9999b, 6001f)
 
 #define DST(y...)			\
 	9999: y;			\
-	_ASM_EXTABLE(9999b, 6002f)
+	_ASM_EXTABLE_UACCESS(9999b, 6002f)
 
 #ifndef CONFIG_X86_USE_PPRO_CHECKSUM
 
diff --git a/arch/x86/lib/copy_user_64.S b/arch/x86/lib/copy_user_64.S
index a30ca15..20c0258 100644
--- a/arch/x86/lib/copy_user_64.S
+++ b/arch/x86/lib/copy_user_64.S
@@ -65,8 +65,8 @@
 	jmp copy_user_handle_tail
 	.previous
 
-	_ASM_EXTABLE(100b,103b)
-	_ASM_EXTABLE(101b,103b)
+	_ASM_EXTABLE_UACCESS(100b,103b)
+	_ASM_EXTABLE_UACCESS(101b,103b)
 #endif
 	.endm
 
@@ -192,26 +192,26 @@ ENTRY(copy_user_generic_unrolled)
 60:	jmp copy_user_handle_tail /* ecx is zerorest also */
 	.previous
 
-	_ASM_EXTABLE(1b,30b)
-	_ASM_EXTABLE(2b,30b)
-	_ASM_EXTABLE(3b,30b)
-	_ASM_EXTABLE(4b,30b)
-	_ASM_EXTABLE(5b,30b)
-	_ASM_EXTABLE(6b,30b)
-	_ASM_EXTABLE(7b,30b)
-	_ASM_EXTABLE(8b,30b)
-	_ASM_EXTABLE(9b,30b)
-	_ASM_EXTABLE(10b,30b)
-	_ASM_EXTABLE(11b,30b)
-	_ASM_EXTABLE(12b,30b)
-	_ASM_EXTABLE(13b,30b)
-	_ASM_EXTABLE(14b,30b)
-	_ASM_EXTABLE(15b,30b)
-	_ASM_EXTABLE(16b,30b)
-	_ASM_EXTABLE(18b,40b)
-	_ASM_EXTABLE(19b,40b)
-	_ASM_EXTABLE(21b,50b)
-	_ASM_EXTABLE(22b,50b)
+	_ASM_EXTABLE_UACCESS(1b,30b)
+	_ASM_EXTABLE_UACCESS(2b,30b)
+	_ASM_EXTABLE_UACCESS(3b,30b)
+	_ASM_EXTABLE_UACCESS(4b,30b)
+	_ASM_EXTABLE_UACCESS(5b,30b)
+	_ASM_EXTABLE_UACCESS(6b,30b)
+	_ASM_EXTABLE_UACCESS(7b,30b)
+	_ASM_EXTABLE_UACCESS(8b,30b)
+	_ASM_EXTABLE_UACCESS(9b,30b)
+	_ASM_EXTABLE_UACCESS(10b,30b)
+	_ASM_EXTABLE_UACCESS(11b,30b)
+	_ASM_EXTABLE_UACCESS(12b,30b)
+	_ASM_EXTABLE_UACCESS(13b,30b)
+	_ASM_EXTABLE_UACCESS(14b,30b)
+	_ASM_EXTABLE_UACCESS(15b,30b)
+	_ASM_EXTABLE_UACCESS(16b,30b)
+	_ASM_EXTABLE_UACCESS(18b,40b)
+	_ASM_EXTABLE_UACCESS(19b,40b)
+	_ASM_EXTABLE_UACCESS(21b,50b)
+	_ASM_EXTABLE_UACCESS(22b,50b)
 	CFI_ENDPROC
 ENDPROC(copy_user_generic_unrolled)
 
@@ -259,8 +259,8 @@ ENTRY(copy_user_generic_string)
 	jmp copy_user_handle_tail
 	.previous
 
-	_ASM_EXTABLE(1b,11b)
-	_ASM_EXTABLE(3b,12b)
+	_ASM_EXTABLE_UACCESS(1b,11b)
+	_ASM_EXTABLE_UACCESS(3b,12b)
 	CFI_ENDPROC
 ENDPROC(copy_user_generic_string)
 
@@ -293,6 +293,6 @@ ENTRY(copy_user_enhanced_fast_string)
 	jmp copy_user_handle_tail
 	.previous
 
-	_ASM_EXTABLE(1b,12b)
+	_ASM_EXTABLE_UACCESS(1b,12b)
 	CFI_ENDPROC
 ENDPROC(copy_user_enhanced_fast_string)
diff --git a/arch/x86/lib/copy_user_nocache_64.S b/arch/x86/lib/copy_user_nocache_64.S
index 6a4f43c..c9b8193 100644
--- a/arch/x86/lib/copy_user_nocache_64.S
+++ b/arch/x86/lib/copy_user_nocache_64.S
@@ -38,8 +38,8 @@
 	jmp copy_user_handle_tail
 	.previous
 
-	_ASM_EXTABLE(100b,103b)
-	_ASM_EXTABLE(101b,103b)
+	_ASM_EXTABLE_UACCESS(100b,103b)
+	_ASM_EXTABLE_UACCESS(101b,103b)
 #endif
 	.endm
 
@@ -112,25 +112,25 @@ ENTRY(__copy_user_nocache)
 	jmp copy_user_handle_tail
 	.previous
 
-	_ASM_EXTABLE(1b,30b)
-	_ASM_EXTABLE(2b,30b)
-	_ASM_EXTABLE(3b,30b)
-	_ASM_EXTABLE(4b,30b)
-	_ASM_EXTABLE(5b,30b)
-	_ASM_EXTABLE(6b,30b)
-	_ASM_EXTABLE(7b,30b)
-	_ASM_EXTABLE(8b,30b)
-	_ASM_EXTABLE(9b,30b)
-	_ASM_EXTABLE(10b,30b)
-	_ASM_EXTABLE(11b,30b)
-	_ASM_EXTABLE(12b,30b)
-	_ASM_EXTABLE(13b,30b)
-	_ASM_EXTABLE(14b,30b)
-	_ASM_EXTABLE(15b,30b)
-	_ASM_EXTABLE(16b,30b)
-	_ASM_EXTABLE(18b,40b)
-	_ASM_EXTABLE(19b,40b)
-	_ASM_EXTABLE(21b,50b)
-	_ASM_EXTABLE(22b,50b)
+	_ASM_EXTABLE_UACCESS(1b,30b)
+	_ASM_EXTABLE_UACCESS(2b,30b)
+	_ASM_EXTABLE_UACCESS(3b,30b)
+	_ASM_EXTABLE_UACCESS(4b,30b)
+	_ASM_EXTABLE_UACCESS(5b,30b)
+	_ASM_EXTABLE_UACCESS(6b,30b)
+	_ASM_EXTABLE_UACCESS(7b,30b)
+	_ASM_EXTABLE_UACCESS(8b,30b)
+	_ASM_EXTABLE_UACCESS(9b,30b)
+	_ASM_EXTABLE_UACCESS(10b,30b)
+	_ASM_EXTABLE_UACCESS(11b,30b)
+	_ASM_EXTABLE_UACCESS(12b,30b)
+	_ASM_EXTABLE_UACCESS(13b,30b)
+	_ASM_EXTABLE_UACCESS(14b,30b)
+	_ASM_EXTABLE_UACCESS(15b,30b)
+	_ASM_EXTABLE_UACCESS(16b,30b)
+	_ASM_EXTABLE_UACCESS(18b,40b)
+	_ASM_EXTABLE_UACCESS(19b,40b)
+	_ASM_EXTABLE_UACCESS(21b,50b)
+	_ASM_EXTABLE_UACCESS(22b,50b)
 	CFI_ENDPROC
 ENDPROC(__copy_user_nocache)
diff --git a/arch/x86/lib/csum-copy_64.S b/arch/x86/lib/csum-copy_64.S
index 2419d5f..e6ecfc9 100644
--- a/arch/x86/lib/csum-copy_64.S
+++ b/arch/x86/lib/csum-copy_64.S
@@ -32,17 +32,17 @@
 
 	.macro source
 10:
-	_ASM_EXTABLE(10b, .Lbad_source)
+	_ASM_EXTABLE_UACCESS(10b, .Lbad_source)
 	.endm
 
 	.macro dest
 20:
-	_ASM_EXTABLE(20b, .Lbad_dest)
+	_ASM_EXTABLE_UACCESS(20b, .Lbad_dest)
 	.endm
 
 	.macro ignore L=.Lignore
 30:
-	_ASM_EXTABLE(30b, \L)
+	_ASM_EXTABLE_UACCESS(30b, \L)
 	.endm
 
 
diff --git a/arch/x86/lib/getuser.S b/arch/x86/lib/getuser.S
index a451235..8f15607 100644
--- a/arch/x86/lib/getuser.S
+++ b/arch/x86/lib/getuser.S
@@ -129,12 +129,12 @@ bad_get_user_8:
 END(bad_get_user_8)
 #endif
 
-	_ASM_EXTABLE(1b,bad_get_user)
-	_ASM_EXTABLE(2b,bad_get_user)
-	_ASM_EXTABLE(3b,bad_get_user)
+	_ASM_EXTABLE_UACCESS(1b,bad_get_user)
+	_ASM_EXTABLE_UACCESS(2b,bad_get_user)
+	_ASM_EXTABLE_UACCESS(3b,bad_get_user)
 #ifdef CONFIG_X86_64
-	_ASM_EXTABLE(4b,bad_get_user)
+	_ASM_EXTABLE_UACCESS(4b,bad_get_user)
 #else
-	_ASM_EXTABLE(4b,bad_get_user_8)
-	_ASM_EXTABLE(5b,bad_get_user_8)
+	_ASM_EXTABLE_UACCESS(4b,bad_get_user_8)
+	_ASM_EXTABLE_UACCESS(5b,bad_get_user_8)
 #endif
diff --git a/arch/x86/lib/mmx_32.c b/arch/x86/lib/mmx_32.c
index c9f2d9b..d1a21f7 100644
--- a/arch/x86/lib/mmx_32.c
+++ b/arch/x86/lib/mmx_32.c
@@ -49,7 +49,7 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
 		"   jmp 2b\n"
 		".previous\n"
-			_ASM_EXTABLE(1b, 3b)
+			_ASM_EXTABLE_UACCESS(1b, 3b)
 			: : "r" (from));
 
 	for ( ; i > 5; i--) {
@@ -75,7 +75,7 @@ void *_mmx_memcpy(void *to, const void *from, size_t len)
 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
 		"   jmp 2b\n"
 		".previous\n"
-			_ASM_EXTABLE(1b, 3b)
+			_ASM_EXTABLE_UACCESS(1b, 3b)
 			: : "r" (from), "r" (to) : "memory");
 
 		from += 64;
@@ -176,7 +176,7 @@ static void fast_copy_page(void *to, void *from)
 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
 		"   jmp 2b\n"
 		".previous\n"
-			_ASM_EXTABLE(1b, 3b) : : "r" (from));
+			_ASM_EXTABLE_UACCESS(1b, 3b) : : "r" (from));
 
 	for (i = 0; i < (4096-320)/64; i++) {
 		__asm__ __volatile__ (
@@ -201,7 +201,7 @@ static void fast_copy_page(void *to, void *from)
 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
 		"   jmp 2b\n"
 		".previous\n"
-		_ASM_EXTABLE(1b, 3b) : : "r" (from), "r" (to) : "memory");
+		_ASM_EXTABLE_UACCESS(1b, 3b) : : "r" (from), "r" (to) : "memory");
 
 		from += 64;
 		to += 64;
@@ -294,7 +294,7 @@ static void fast_copy_page(void *to, void *from)
 		"3: movw $0x1AEB, 1b\n"	/* jmp on 26 bytes */
 		"   jmp 2b\n"
 		".previous\n"
-			_ASM_EXTABLE(1b, 3b) : : "r" (from));
+			_ASM_EXTABLE_UACCESS(1b, 3b) : : "r" (from));
 
 	for (i = 0; i < 4096/64; i++) {
 		__asm__ __volatile__ (
@@ -319,7 +319,7 @@ static void fast_copy_page(void *to, void *from)
 		"3: movw $0x05EB, 1b\n"	/* jmp on 5 bytes */
 		"   jmp 2b\n"
 		".previous\n"
-			_ASM_EXTABLE(1b, 3b)
+			_ASM_EXTABLE_UACCESS(1b, 3b)
 			: : "r" (from), "r" (to) : "memory");
 
 		from += 64;
diff --git a/arch/x86/lib/msr-reg.S b/arch/x86/lib/msr-reg.S
index f6d13ee..ded3bd5 100644
--- a/arch/x86/lib/msr-reg.S
+++ b/arch/x86/lib/msr-reg.S
@@ -43,7 +43,7 @@ ENTRY(\op\()_safe_regs)
 	movl    $-EIO, %r11d
 	jmp     2b
 
-	_ASM_EXTABLE(1b, 3b)
+	_ASM_EXTABLE_ANY(1b, 3b)
 	CFI_ENDPROC
 ENDPROC(\op\()_safe_regs)
 .endm
@@ -90,7 +90,7 @@ ENTRY(\op\()_safe_regs)
 	movl    $-EIO, 4(%esp)
 	jmp     2b
 
-	_ASM_EXTABLE(1b, 3b)
+	_ASM_EXTABLE_ANY(1b, 3b)
 	CFI_ENDPROC
 ENDPROC(\op\()_safe_regs)
 .endm
diff --git a/arch/x86/lib/putuser.S b/arch/x86/lib/putuser.S
index fc6ba17..b2fbb72 100644
--- a/arch/x86/lib/putuser.S
+++ b/arch/x86/lib/putuser.S
@@ -92,10 +92,10 @@ bad_put_user:
 	EXIT
 END(bad_put_user)
 
-	_ASM_EXTABLE(1b,bad_put_user)
-	_ASM_EXTABLE(2b,bad_put_user)
-	_ASM_EXTABLE(3b,bad_put_user)
-	_ASM_EXTABLE(4b,bad_put_user)
+	_ASM_EXTABLE_UACCESS(1b,bad_put_user)
+	_ASM_EXTABLE_UACCESS(2b,bad_put_user)
+	_ASM_EXTABLE_UACCESS(3b,bad_put_user)
+	_ASM_EXTABLE_UACCESS(4b,bad_put_user)
 #ifdef CONFIG_X86_32
-	_ASM_EXTABLE(5b,bad_put_user)
+	_ASM_EXTABLE_UACCESS(5b,bad_put_user)
 #endif
diff --git a/arch/x86/lib/usercopy_32.c b/arch/x86/lib/usercopy_32.c
index f0312d7..0884951 100644
--- a/arch/x86/lib/usercopy_32.c
+++ b/arch/x86/lib/usercopy_32.c
@@ -51,8 +51,8 @@ do {									\
 		"3:	lea 0(%2,%0,4),%0\n"				\
 		"	jmp 2b\n"					\
 		".previous\n"						\
-		_ASM_EXTABLE(0b,3b)					\
-		_ASM_EXTABLE(1b,2b)					\
+		_ASM_EXTABLE_UACCESS(0b,3b)					\
+		_ASM_EXTABLE_UACCESS(1b,2b)					\
 		: "=&c"(size), "=&D" (__d0)				\
 		: "r"(size & 3), "0"(size / 4), "1"(addr), "a"(0));	\
 } while (0)
@@ -157,44 +157,44 @@ __copy_user_intel(void __user *to, const void *from, unsigned long size)
 		       "101:   lea 0(%%eax,%0,4),%0\n"
 		       "       jmp 100b\n"
 		       ".previous\n"
-		       _ASM_EXTABLE(1b,100b)
-		       _ASM_EXTABLE(2b,100b)
-		       _ASM_EXTABLE(3b,100b)
-		       _ASM_EXTABLE(4b,100b)
-		       _ASM_EXTABLE(5b,100b)
-		       _ASM_EXTABLE(6b,100b)
-		       _ASM_EXTABLE(7b,100b)
-		       _ASM_EXTABLE(8b,100b)
-		       _ASM_EXTABLE(9b,100b)
-		       _ASM_EXTABLE(10b,100b)
-		       _ASM_EXTABLE(11b,100b)
-		       _ASM_EXTABLE(12b,100b)
-		       _ASM_EXTABLE(13b,100b)
-		       _ASM_EXTABLE(14b,100b)
-		       _ASM_EXTABLE(15b,100b)
-		       _ASM_EXTABLE(16b,100b)
-		       _ASM_EXTABLE(17b,100b)
-		       _ASM_EXTABLE(18b,100b)
-		       _ASM_EXTABLE(19b,100b)
-		       _ASM_EXTABLE(20b,100b)
-		       _ASM_EXTABLE(21b,100b)
-		       _ASM_EXTABLE(22b,100b)
-		       _ASM_EXTABLE(23b,100b)
-		       _ASM_EXTABLE(24b,100b)
-		       _ASM_EXTABLE(25b,100b)
-		       _ASM_EXTABLE(26b,100b)
-		       _ASM_EXTABLE(27b,100b)
-		       _ASM_EXTABLE(28b,100b)
-		       _ASM_EXTABLE(29b,100b)
-		       _ASM_EXTABLE(30b,100b)
-		       _ASM_EXTABLE(31b,100b)
-		       _ASM_EXTABLE(32b,100b)
-		       _ASM_EXTABLE(33b,100b)
-		       _ASM_EXTABLE(34b,100b)
-		       _ASM_EXTABLE(35b,100b)
-		       _ASM_EXTABLE(36b,100b)
-		       _ASM_EXTABLE(37b,100b)
-		       _ASM_EXTABLE(99b,101b)
+		       _ASM_EXTABLE_UACCESS(1b,100b)
+		       _ASM_EXTABLE_UACCESS(2b,100b)
+		       _ASM_EXTABLE_UACCESS(3b,100b)
+		       _ASM_EXTABLE_UACCESS(4b,100b)
+		       _ASM_EXTABLE_UACCESS(5b,100b)
+		       _ASM_EXTABLE_UACCESS(6b,100b)
+		       _ASM_EXTABLE_UACCESS(7b,100b)
+		       _ASM_EXTABLE_UACCESS(8b,100b)
+		       _ASM_EXTABLE_UACCESS(9b,100b)
+		       _ASM_EXTABLE_UACCESS(10b,100b)
+		       _ASM_EXTABLE_UACCESS(11b,100b)
+		       _ASM_EXTABLE_UACCESS(12b,100b)
+		       _ASM_EXTABLE_UACCESS(13b,100b)
+		       _ASM_EXTABLE_UACCESS(14b,100b)
+		       _ASM_EXTABLE_UACCESS(15b,100b)
+		       _ASM_EXTABLE_UACCESS(16b,100b)
+		       _ASM_EXTABLE_UACCESS(17b,100b)
+		       _ASM_EXTABLE_UACCESS(18b,100b)
+		       _ASM_EXTABLE_UACCESS(19b,100b)
+		       _ASM_EXTABLE_UACCESS(20b,100b)
+		       _ASM_EXTABLE_UACCESS(21b,100b)
+		       _ASM_EXTABLE_UACCESS(22b,100b)
+		       _ASM_EXTABLE_UACCESS(23b,100b)
+		       _ASM_EXTABLE_UACCESS(24b,100b)
+		       _ASM_EXTABLE_UACCESS(25b,100b)
+		       _ASM_EXTABLE_UACCESS(26b,100b)
+		       _ASM_EXTABLE_UACCESS(27b,100b)
+		       _ASM_EXTABLE_UACCESS(28b,100b)
+		       _ASM_EXTABLE_UACCESS(29b,100b)
+		       _ASM_EXTABLE_UACCESS(30b,100b)
+		       _ASM_EXTABLE_UACCESS(31b,100b)
+		       _ASM_EXTABLE_UACCESS(32b,100b)
+		       _ASM_EXTABLE_UACCESS(33b,100b)
+		       _ASM_EXTABLE_UACCESS(34b,100b)
+		       _ASM_EXTABLE_UACCESS(35b,100b)
+		       _ASM_EXTABLE_UACCESS(36b,100b)
+		       _ASM_EXTABLE_UACCESS(37b,100b)
+		       _ASM_EXTABLE_UACCESS(99b,101b)
 		       : "=&c"(size), "=&D" (d0), "=&S" (d1)
 		       :  "1"(to), "2"(from), "0"(size)
 		       : "eax", "edx", "memory");
@@ -267,26 +267,26 @@ __copy_user_zeroing_intel(void *to, const void __user *from, unsigned long size)
 		       "        popl %0\n"
 		       "        jmp 8b\n"
 		       ".previous\n"
-		       _ASM_EXTABLE(0b,16b)
-		       _ASM_EXTABLE(1b,16b)
-		       _ASM_EXTABLE(2b,16b)
-		       _ASM_EXTABLE(21b,16b)
-		       _ASM_EXTABLE(3b,16b)
-		       _ASM_EXTABLE(31b,16b)
-		       _ASM_EXTABLE(4b,16b)
-		       _ASM_EXTABLE(41b,16b)
-		       _ASM_EXTABLE(10b,16b)
-		       _ASM_EXTABLE(51b,16b)
-		       _ASM_EXTABLE(11b,16b)
-		       _ASM_EXTABLE(61b,16b)
-		       _ASM_EXTABLE(12b,16b)
-		       _ASM_EXTABLE(71b,16b)
-		       _ASM_EXTABLE(13b,16b)
-		       _ASM_EXTABLE(81b,16b)
-		       _ASM_EXTABLE(14b,16b)
-		       _ASM_EXTABLE(91b,16b)
-		       _ASM_EXTABLE(6b,9b)
-		       _ASM_EXTABLE(7b,16b)
+		       _ASM_EXTABLE_UACCESS(0b,16b)
+		       _ASM_EXTABLE_UACCESS(1b,16b)
+		       _ASM_EXTABLE_UACCESS(2b,16b)
+		       _ASM_EXTABLE_UACCESS(21b,16b)
+		       _ASM_EXTABLE_UACCESS(3b,16b)
+		       _ASM_EXTABLE_UACCESS(31b,16b)
+		       _ASM_EXTABLE_UACCESS(4b,16b)
+		       _ASM_EXTABLE_UACCESS(41b,16b)
+		       _ASM_EXTABLE_UACCESS(10b,16b)
+		       _ASM_EXTABLE_UACCESS(51b,16b)
+		       _ASM_EXTABLE_UACCESS(11b,16b)
+		       _ASM_EXTABLE_UACCESS(61b,16b)
+		       _ASM_EXTABLE_UACCESS(12b,16b)
+		       _ASM_EXTABLE_UACCESS(71b,16b)
+		       _ASM_EXTABLE_UACCESS(13b,16b)
+		       _ASM_EXTABLE_UACCESS(81b,16b)
+		       _ASM_EXTABLE_UACCESS(14b,16b)
+		       _ASM_EXTABLE_UACCESS(91b,16b)
+		       _ASM_EXTABLE_UACCESS(6b,9b)
+		       _ASM_EXTABLE_UACCESS(7b,16b)
 		       : "=&c"(size), "=&D" (d0), "=&S" (d1)
 		       :  "1"(to), "2"(from), "0"(size)
 		       : "eax", "edx", "memory");
@@ -366,26 +366,26 @@ static unsigned long __copy_user_zeroing_intel_nocache(void *to,
 	       "        popl %0\n"
 	       "        jmp 8b\n"
 	       ".previous\n"
-	       _ASM_EXTABLE(0b,16b)
-	       _ASM_EXTABLE(1b,16b)
-	       _ASM_EXTABLE(2b,16b)
-	       _ASM_EXTABLE(21b,16b)
-	       _ASM_EXTABLE(3b,16b)
-	       _ASM_EXTABLE(31b,16b)
-	       _ASM_EXTABLE(4b,16b)
-	       _ASM_EXTABLE(41b,16b)
-	       _ASM_EXTABLE(10b,16b)
-	       _ASM_EXTABLE(51b,16b)
-	       _ASM_EXTABLE(11b,16b)
-	       _ASM_EXTABLE(61b,16b)
-	       _ASM_EXTABLE(12b,16b)
-	       _ASM_EXTABLE(71b,16b)
-	       _ASM_EXTABLE(13b,16b)
-	       _ASM_EXTABLE(81b,16b)
-	       _ASM_EXTABLE(14b,16b)
-	       _ASM_EXTABLE(91b,16b)
-	       _ASM_EXTABLE(6b,9b)
-	       _ASM_EXTABLE(7b,16b)
+	       _ASM_EXTABLE_UACCESS(0b,16b)
+	       _ASM_EXTABLE_UACCESS(1b,16b)
+	       _ASM_EXTABLE_UACCESS(2b,16b)
+	       _ASM_EXTABLE_UACCESS(21b,16b)
+	       _ASM_EXTABLE_UACCESS(3b,16b)
+	       _ASM_EXTABLE_UACCESS(31b,16b)
+	       _ASM_EXTABLE_UACCESS(4b,16b)
+	       _ASM_EXTABLE_UACCESS(41b,16b)
+	       _ASM_EXTABLE_UACCESS(10b,16b)
+	       _ASM_EXTABLE_UACCESS(51b,16b)
+	       _ASM_EXTABLE_UACCESS(11b,16b)
+	       _ASM_EXTABLE_UACCESS(61b,16b)
+	       _ASM_EXTABLE_UACCESS(12b,16b)
+	       _ASM_EXTABLE_UACCESS(71b,16b)
+	       _ASM_EXTABLE_UACCESS(13b,16b)
+	       _ASM_EXTABLE_UACCESS(81b,16b)
+	       _ASM_EXTABLE_UACCESS(14b,16b)
+	       _ASM_EXTABLE_UACCESS(91b,16b)
+	       _ASM_EXTABLE_UACCESS(6b,9b)
+	       _ASM_EXTABLE_UACCESS(7b,16b)
 	       : "=&c"(size), "=&D" (d0), "=&S" (d1)
 	       :  "1"(to), "2"(from), "0"(size)
 	       : "eax", "edx", "memory");
@@ -454,26 +454,26 @@ static unsigned long __copy_user_intel_nocache(void *to,
 	       "9:      lea 0(%%eax,%0,4),%0\n"
 	       "16:     jmp 8b\n"
 	       ".previous\n"
-	       _ASM_EXTABLE(0b,16b)
-	       _ASM_EXTABLE(1b,16b)
-	       _ASM_EXTABLE(2b,16b)
-	       _ASM_EXTABLE(21b,16b)
-	       _ASM_EXTABLE(3b,16b)
-	       _ASM_EXTABLE(31b,16b)
-	       _ASM_EXTABLE(4b,16b)
-	       _ASM_EXTABLE(41b,16b)
-	       _ASM_EXTABLE(10b,16b)
-	       _ASM_EXTABLE(51b,16b)
-	       _ASM_EXTABLE(11b,16b)
-	       _ASM_EXTABLE(61b,16b)
-	       _ASM_EXTABLE(12b,16b)
-	       _ASM_EXTABLE(71b,16b)
-	       _ASM_EXTABLE(13b,16b)
-	       _ASM_EXTABLE(81b,16b)
-	       _ASM_EXTABLE(14b,16b)
-	       _ASM_EXTABLE(91b,16b)
-	       _ASM_EXTABLE(6b,9b)
-	       _ASM_EXTABLE(7b,16b)
+	       _ASM_EXTABLE_UACCESS(0b,16b)
+	       _ASM_EXTABLE_UACCESS(1b,16b)
+	       _ASM_EXTABLE_UACCESS(2b,16b)
+	       _ASM_EXTABLE_UACCESS(21b,16b)
+	       _ASM_EXTABLE_UACCESS(3b,16b)
+	       _ASM_EXTABLE_UACCESS(31b,16b)
+	       _ASM_EXTABLE_UACCESS(4b,16b)
+	       _ASM_EXTABLE_UACCESS(41b,16b)
+	       _ASM_EXTABLE_UACCESS(10b,16b)
+	       _ASM_EXTABLE_UACCESS(51b,16b)
+	       _ASM_EXTABLE_UACCESS(11b,16b)
+	       _ASM_EXTABLE_UACCESS(61b,16b)
+	       _ASM_EXTABLE_UACCESS(12b,16b)
+	       _ASM_EXTABLE_UACCESS(71b,16b)
+	       _ASM_EXTABLE_UACCESS(13b,16b)
+	       _ASM_EXTABLE_UACCESS(81b,16b)
+	       _ASM_EXTABLE_UACCESS(14b,16b)
+	       _ASM_EXTABLE_UACCESS(91b,16b)
+	       _ASM_EXTABLE_UACCESS(6b,9b)
+	       _ASM_EXTABLE_UACCESS(7b,16b)
 	       : "=&c"(size), "=&D" (d0), "=&S" (d1)
 	       :  "1"(to), "2"(from), "0"(size)
 	       : "eax", "edx", "memory");
@@ -520,9 +520,9 @@ do {									\
 		"3:	lea 0(%3,%0,4),%0\n"				\
 		"	jmp 2b\n"					\
 		".previous\n"						\
-		_ASM_EXTABLE(4b,5b)					\
-		_ASM_EXTABLE(0b,3b)					\
-		_ASM_EXTABLE(1b,2b)					\
+		_ASM_EXTABLE_UACCESS(4b,5b)					\
+		_ASM_EXTABLE_UACCESS(0b,3b)					\
+		_ASM_EXTABLE_UACCESS(1b,2b)					\
 		: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)	\
 		: "3"(size), "0"(size), "1"(to), "2"(from)		\
 		: "memory");						\
@@ -559,9 +559,9 @@ do {									\
 		"	popl %0\n"					\
 		"	jmp 2b\n"					\
 		".previous\n"						\
-		_ASM_EXTABLE(4b,5b)					\
-		_ASM_EXTABLE(0b,3b)					\
-		_ASM_EXTABLE(1b,6b)					\
+		_ASM_EXTABLE_UACCESS(4b,5b)					\
+		_ASM_EXTABLE_UACCESS(0b,3b)					\
+		_ASM_EXTABLE_UACCESS(1b,6b)					\
 		: "=&c"(size), "=&D" (__d0), "=&S" (__d1), "=r"(__d2)	\
 		: "3"(size), "0"(size), "1"(to), "2"(from)		\
 		: "memory");						\
diff --git a/arch/x86/lib/usercopy_64.c b/arch/x86/lib/usercopy_64.c
index 906fea3..bcc15a1 100644
--- a/arch/x86/lib/usercopy_64.c
+++ b/arch/x86/lib/usercopy_64.c
@@ -36,8 +36,8 @@ unsigned long __clear_user(void __user *addr, unsigned long size)
 		"3:	lea 0(%[size1],%[size8],8),%[size8]\n"
 		"	jmp 2b\n"
 		".previous\n"
-		_ASM_EXTABLE(0b,3b)
-		_ASM_EXTABLE(1b,2b)
+		_ASM_EXTABLE_UACCESS(0b,3b)
+		_ASM_EXTABLE_UACCESS(1b,2b)
 		: [size8] "=&c"(size), [dst] "=&D" (__d0)
 		: [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
 		  [zero] "r" (0UL), [eight] "r" (8UL));
diff --git a/arch/x86/mm/init_32.c b/arch/x86/mm/init_32.c
index 2d19001..47471d0 100644
--- a/arch/x86/mm/init_32.c
+++ b/arch/x86/mm/init_32.c
@@ -890,7 +890,7 @@ static noinline int do_test_wp_bit(void)
 		"1:	movb %1, %0	\n"
 		"	xorl %2, %2	\n"
 		"2:			\n"
-		_ASM_EXTABLE(1b,2b)
+		_ASM_EXTABLE_ANY(1b,2b)
 		:"=m" (*(char *)fix_to_virt(FIX_WP_TEST)),
 		 "=q" (tmp_reg),
 		 "=r" (flag)
diff --git a/arch/x86/um/checksum_32.S b/arch/x86/um/checksum_32.S
index 8d0c420..30289b8 100644
--- a/arch/x86/um/checksum_32.S
+++ b/arch/x86/um/checksum_32.S
@@ -233,11 +233,11 @@ unsigned int csum_partial_copy_generic (const char *src, char *dst,
 
 #define SRC(y...)			\
 	9999: y;			\
-	_ASM_EXTABLE(9999b, 6001f)
+	_ASM_EXTABLE_UACCESS(9999b, 6001f)
 
 #define DST(y...)			\
 	9999: y;			\
-	_ASM_EXTABLE(9999b, 6002f)
+	_ASM_EXTABLE_UACCESS(9999b, 6002f)
 
 .align 4
 
diff --git a/arch/x86/xen/xen-asm_32.S b/arch/x86/xen/xen-asm_32.S
index 33ca6e4..57c63ac 100644
--- a/arch/x86/xen/xen-asm_32.S
+++ b/arch/x86/xen/xen-asm_32.S
@@ -138,7 +138,7 @@ iret_restore_end:
 
 1:	iret
 xen_iret_end_crit:
-	_ASM_EXTABLE(1b, iret_exc)
+	_ASM_EXTABLE_ANY(1b, iret_exc)
 
 hyper_iret:
 	/* put this out of line since its very rarely used */
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 4/5] x86: Don't fixup uaccess faults to kernel or non-canonical addresses
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
                   ` (2 preceding siblings ...)
  2013-05-22 21:07 ` [PATCH 3/5] x86: Annotate _ASM_EXTABLE users to distinguish uaccess from everything else Andy Lutomirski
@ 2013-05-22 21:07 ` Andy Lutomirski
  2013-05-22 21:07 ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Andy Lutomirski
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-05-22 21:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: x86, trinity, Andy Lutomirski, Ananth N Mavinakayanahalli,
	Anil S Keshavamurthy, David S. Miller, Masami Hiramatsu

These don't inherently cause crashes, but they're bugs and, if
there's one triggerable from userspace, it can be used to probe
KASLR.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

I don't know what the kprobes code is doing, so I made the conservative
change.  This can probably be improved.

Kprobes people: what does this code do?

 arch/x86/include/asm/uaccess.h |  2 +-
 arch/x86/kernel/kprobes/core.c |  4 +++-
 arch/x86/kernel/traps.c        | 10 +++++++---
 arch/x86/mm/extable.c          |  7 +++++--
 arch/x86/mm/fault.c            | 17 ++++++++++-------
 5 files changed, 26 insertions(+), 14 deletions(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index ed2d77a..a2a92d8 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -101,7 +101,7 @@ struct exception_table_entry {
 #define ARCH_HAS_SORT_EXTABLE
 #define ARCH_HAS_SEARCH_EXTABLE
 
-extern int fixup_exception(struct pt_regs *regs);
+extern int fixup_exception(struct pt_regs *regs, bool uaccess_ok);
 extern int early_fixup_exception(unsigned long *ip);
 
 /*
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index 7bfe318..64932d2 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -927,8 +927,10 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, int trapnr)
 		/*
 		 * In case the user-specified fault handler returned
 		 * zero, try to fix up.
+		 *
+		 * XXX: This could be much more conservative.
 		 */
-		if (fixup_exception(regs))
+		if (fixup_exception(regs, true))
 			return 1;
 
 		/*
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 8647670..a9453b0 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -124,7 +124,7 @@ do_trap_no_signal(struct task_struct *tsk, int trapnr, char *str,
 	}
 #endif
 	if (!user_mode(regs)) {
-		if (!fixup_exception(regs)) {
+		if (!fixup_exception(regs, false)) {
 			tsk->thread.error_code = error_code;
 			tsk->thread.trap_nr = trapnr;
 			die(str, regs, error_code);
@@ -277,7 +277,11 @@ do_general_protection(struct pt_regs *regs, long error_code)
 	if (!user_mode(regs)) {
 		fixup_pnpbios_exception(regs);  /* Might not return */
 
-		if (fixup_exception(regs))
+		/*
+		 * This could be a non-canonical address in uaccess.  If so,
+		 * this is bad.
+		 */
+		if (fixup_exception(regs, false))
 			goto exit;
 
 		tsk->thread.error_code = error_code;
@@ -491,7 +495,7 @@ void math_error(struct pt_regs *regs, int error_code, int trapnr)
 
 	if (!user_mode_vm(regs))
 	{
-		if (!fixup_exception(regs)) {
+		if (!fixup_exception(regs, false)) {
 			task->thread.error_code = error_code;
 			task->thread.trap_nr = trapnr;
 			die(str, regs, error_code);
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 85f45d4..05e078a 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -22,7 +22,7 @@ ex_fixup_addr(const struct exception_table_entry *x)
 	return (unsigned long)&x->fixup + offset;
 }
 
-int fixup_exception(struct pt_regs *regs)
+int fixup_exception(struct pt_regs *regs, bool uaccess_ok)
 {
 	const struct exception_table_entry *fixup;
 	unsigned long new_ip;
@@ -33,6 +33,9 @@ int fixup_exception(struct pt_regs *regs)
 		class = ex_class(fixup);
 		new_ip = ex_fixup_addr(fixup);
 
+		if (class != _EXTABLE_CLASS_ANY && !uaccess_ok)
+			return 0;
+
 		if (class == _EXTABLE_CLASS_EX) {
 			/* Special hack for uaccess_err */
 			current_thread_info()->uaccess_err = 1;
@@ -51,7 +54,7 @@ int __init early_fixup_exception(unsigned long *ip)
 
 	fixup = search_exception_tables(*ip);
 	if (fixup) {
-		if (ex_class(fixup) == _EXTABLE_CLASS_EX) {
+		if (ex_class(fixup) != _EXTABLE_CLASS_ANY) {
 			/* uaccess handling not supported during early boot */
 			return 0;
 		}
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
index 58afb50..c9fdf7d 100644
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -644,6 +644,11 @@ pgtable_bad(struct pt_regs *regs, unsigned long error_code,
 	oops_end(flags, regs, sig);
 }
 
+static int fault_in_kernel_space(unsigned long address)
+{
+	return address >= TASK_SIZE_MAX;
+}
+
 static noinline void
 no_context(struct pt_regs *regs, unsigned long error_code,
 	   unsigned long address, int signal, int si_code)
@@ -655,8 +660,11 @@ no_context(struct pt_regs *regs, unsigned long error_code,
 
 	fixup_pnpbios_exception(regs);  /* Might not return */
 
-	/* Are we prepared to handle this kernel fault? */
-	if (fixup_exception(regs)) {
+	/*
+	 * Are we prepared to handle this kernel fault?  If this is a
+	 * uaccess fault, then the faulting address must be in user space.
+	 */
+	if (fixup_exception(regs, !fault_in_kernel_space(address))) {
 		if (current_thread_info()->sig_on_uaccess_error && signal) {
 			tsk->thread.trap_nr = X86_TRAP_PF;
 			tsk->thread.error_code = error_code | PF_USER;
@@ -1001,11 +1009,6 @@ access_error(unsigned long error_code, struct vm_area_struct *vma)
 	return 0;
 }
 
-static int fault_in_kernel_space(unsigned long address)
-{
-	return address >= TASK_SIZE_MAX;
-}
-
 static inline bool smap_violation(int error_code, struct pt_regs *regs)
 {
 	if (error_code & PF_USER)
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
                   ` (3 preceding siblings ...)
  2013-05-22 21:07 ` [PATCH 4/5] x86: Don't fixup uaccess faults to kernel or non-canonical addresses Andy Lutomirski
@ 2013-05-22 21:07 ` Andy Lutomirski
  2013-05-28  8:56   ` [PATCH/FIX] " Ingo Molnar
  2013-06-06  2:56   ` [PATCH 5/5] " Michael Neuling
  2013-05-22 21:28 ` [PATCH 0/5] x86: oops on uaccess faults outside of user addresses David Miller
  2013-06-13 22:00 ` Andy Lutomirski
  6 siblings, 2 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-05-22 21:07 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, trinity, Andy Lutomirski, netdev, David S. Miller

MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
it's a hack that steals a bit to indicate to other networking code
that a compat entry was used.  So don't allow it from a non-compat
syscall.

This prevents an oops when running this code:

int main()
{
	int s;
	struct sockaddr_in addr;
	struct msghdr *hdr;

	char *highpage = mmap((void*)(TASK_SIZE_MAX - 4096), 4096,
	                      PROT_READ | PROT_WRITE,
	                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
	if (highpage == MAP_FAILED)
		err(1, "mmap");

	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == -1)
		err(1, "socket");

        addr.sin_family = AF_INET;
        addr.sin_port = htons(1);
        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) != 0)
		err(1, "connect");

	void *evil = highpage + 4096 - COMPAT_MSGHDR_SIZE;
	printf("Evil address is %p\n", evil);

	if (syscall(__NR_sendmmsg, s, evil, 1, MSG_CMSG_COMPAT) < 0)
		err(1, "sendmmsg");

	return 0;
}

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 net/socket.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 88f759a..0e16888 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2097,8 +2097,12 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, fla
 {
 	int fput_needed, err;
 	struct msghdr msg_sys;
-	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
+	struct socket *sock;
+
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -2171,6 +2175,8 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
 		unsigned int, vlen, unsigned int, flags)
 {
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
 }
 
@@ -2271,8 +2277,12 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
 {
 	int fput_needed, err;
 	struct msghdr msg_sys;
-	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
+	struct socket *sock;
+
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -2397,6 +2407,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
 	int datagrams;
 	struct timespec timeout_sys;
 
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+
 	if (!timeout)
 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
 
@@ -2512,15 +2525,31 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
 				   (int __user *)a[4]);
 		break;
 	case SYS_SENDMSG:
+		if (a[2] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
 		break;
 	case SYS_SENDMMSG:
+		if (a[3] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
 		break;
 	case SYS_RECVMSG:
+		if (a[2] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
 		break;
 	case SYS_RECVMMSG:
+		if (a[3] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
 				   (struct timespec __user *)a[4]);
 		break;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/5] x86: oops on uaccess faults outside of user addresses
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
                   ` (4 preceding siblings ...)
  2013-05-22 21:07 ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Andy Lutomirski
@ 2013-05-22 21:28 ` David Miller
  2013-05-28  8:25   ` Ingo Molnar
  2013-06-13 22:00 ` Andy Lutomirski
  6 siblings, 1 reply; 24+ messages in thread
From: David Miller @ 2013-05-22 21:28 UTC (permalink / raw)
  To: luto; +Cc: linux-kernel, x86, trinity


Please don't mix networking and non-networking changes into a patch
series.

Submit the networking patch to netdev@vger.kernel.org

Thanks.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/5] x86: oops on uaccess faults outside of user addresses
  2013-05-22 21:28 ` [PATCH 0/5] x86: oops on uaccess faults outside of user addresses David Miller
@ 2013-05-28  8:25   ` Ingo Molnar
  2013-05-28  8:51     ` David Miller
  0 siblings, 1 reply; 24+ messages in thread
From: Ingo Molnar @ 2013-05-28  8:25 UTC (permalink / raw)
  To: David Miller; +Cc: luto, linux-kernel, x86, trinity


* David Miller <davem@davemloft.net> wrote:

> Please don't mix networking and non-networking changes into a patch
> series.

As explained in 0/5 the networking fix justifies the first 4 patches. The 
networking fix is independent of the first 4 patches.

> Submit the networking patch to netdev@vger.kernel.org

He Cc:-ed the patch to netdev@vger.kernel.org. If you agree with it then 
the fix should probably be picked up ASAP.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/5] x86: oops on uaccess faults outside of user addresses
  2013-05-28  8:25   ` Ingo Molnar
@ 2013-05-28  8:51     ` David Miller
  2013-05-28  8:54       ` Ingo Molnar
  0 siblings, 1 reply; 24+ messages in thread
From: David Miller @ 2013-05-28  8:51 UTC (permalink / raw)
  To: mingo; +Cc: luto, linux-kernel, x86, trinity

From: Ingo Molnar <mingo@kernel.org>
Date: Tue, 28 May 2013 10:25:14 +0200

> 
> * David Miller <davem@davemloft.net> wrote:
> 
>> Please don't mix networking and non-networking changes into a patch
>> series.
> 
> As explained in 0/5 the networking fix justifies the first 4 patches. The 
> networking fix is independent of the first 4 patches.
> 
>> Submit the networking patch to netdev@vger.kernel.org
> 
> He Cc:-ed the patch to netdev@vger.kernel.org. If you agree with it then 
> the fix should probably be picked up ASAP.

He submitted it as part of a series which implies that it belongs together
with the others.

If it does not, he should submit it seperately.

If they belong together, then the entire series should be CC:'d to netdev
so that networking developers can see all of the context and participate
in the patches that the networking "enables".

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/5] x86: oops on uaccess faults outside of user addresses
  2013-05-28  8:51     ` David Miller
@ 2013-05-28  8:54       ` Ingo Molnar
  0 siblings, 0 replies; 24+ messages in thread
From: Ingo Molnar @ 2013-05-28  8:54 UTC (permalink / raw)
  To: David Miller; +Cc: luto, linux-kernel, x86, trinity


* David Miller <davem@davemloft.net> wrote:

> From: Ingo Molnar <mingo@kernel.org>
> Date: Tue, 28 May 2013 10:25:14 +0200
> 
> > 
> > * David Miller <davem@davemloft.net> wrote:
> > 
> >> Please don't mix networking and non-networking changes into a patch
> >> series.
> > 
> > As explained in 0/5 the networking fix justifies the first 4 patches. The 
> > networking fix is independent of the first 4 patches.
> > 
> >> Submit the networking patch to netdev@vger.kernel.org
> > 
> > He Cc:-ed the patch to netdev@vger.kernel.org. If you agree with it then 
> > the fix should probably be picked up ASAP.
> 
> He submitted it as part of a series which implies that it belongs together
> with the others.

And then described it in the 0/5 patch that it's not. It's also visible 
from the title, the changelog and the diff of the 5/5 patch that it's a 
separate fix.

So please consider it submitted.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH/FIX] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-05-22 21:07 ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Andy Lutomirski
@ 2013-05-28  8:56   ` Ingo Molnar
  2013-05-29  6:56     ` David Miller
  2013-06-06  2:56   ` [PATCH 5/5] " Michael Neuling
  1 sibling, 1 reply; 24+ messages in thread
From: Ingo Molnar @ 2013-05-28  8:56 UTC (permalink / raw)
  To: Andy Lutomirski, netdev
  Cc: linux-kernel, x86, trinity, netdev, David S. Miller


(edited the title to make sure everyone sees that this fix is standalone.)

----- Forwarded message from Andy Lutomirski <luto@amacapital.net> -----

Date: Wed, 22 May 2013 14:07:44 -0700
From: Andy Lutomirski <luto@amacapital.net>
To: linux-kernel@vger.kernel.org
Cc: x86@kernel.org, trinity@vger.kernel.org, Andy Lutomirski <luto@amacapital.net>, netdev@vger.kernel.org, "David S.
	Miller" <davem@davemloft.net>
Subject: [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg

MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
it's a hack that steals a bit to indicate to other networking code
that a compat entry was used.  So don't allow it from a non-compat
syscall.

This prevents an oops when running this code:

int main()
{
	int s;
	struct sockaddr_in addr;
	struct msghdr *hdr;

	char *highpage = mmap((void*)(TASK_SIZE_MAX - 4096), 4096,
	                      PROT_READ | PROT_WRITE,
	                      MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
	if (highpage == MAP_FAILED)
		err(1, "mmap");

	s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
	if (s == -1)
		err(1, "socket");

        addr.sin_family = AF_INET;
        addr.sin_port = htons(1);
        addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
	if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) != 0)
		err(1, "connect");

	void *evil = highpage + 4096 - COMPAT_MSGHDR_SIZE;
	printf("Evil address is %p\n", evil);

	if (syscall(__NR_sendmmsg, s, evil, 1, MSG_CMSG_COMPAT) < 0)
		err(1, "sendmmsg");

	return 0;
}

Cc: David S. Miller <davem@davemloft.net>
Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---
 net/socket.c | 33 +++++++++++++++++++++++++++++++--
 1 file changed, 31 insertions(+), 2 deletions(-)

diff --git a/net/socket.c b/net/socket.c
index 88f759a..0e16888 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2097,8 +2097,12 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, fla
 {
 	int fput_needed, err;
 	struct msghdr msg_sys;
-	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
+	struct socket *sock;
+
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -2171,6 +2175,8 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
 		unsigned int, vlen, unsigned int, flags)
 {
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
 }
 
@@ -2271,8 +2277,12 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
 {
 	int fput_needed, err;
 	struct msghdr msg_sys;
-	struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
+	struct socket *sock;
+
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 
+	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
@@ -2397,6 +2407,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
 	int datagrams;
 	struct timespec timeout_sys;
 
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+
 	if (!timeout)
 		return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
 
@@ -2512,15 +2525,31 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
 				   (int __user *)a[4]);
 		break;
 	case SYS_SENDMSG:
+		if (a[2] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
 		break;
 	case SYS_SENDMMSG:
+		if (a[3] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
 		break;
 	case SYS_RECVMSG:
+		if (a[2] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
 		break;
 	case SYS_RECVMMSG:
+		if (a[3] & MSG_CMSG_COMPAT) {
+			err = -EINVAL;
+			break;
+		}
 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
 				   (struct timespec __user *)a[4]);
 		break;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH/FIX] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-05-28  8:56   ` [PATCH/FIX] " Ingo Molnar
@ 2013-05-29  6:56     ` David Miller
  2013-05-29  8:11       ` Ingo Molnar
  0 siblings, 1 reply; 24+ messages in thread
From: David Miller @ 2013-05-29  6:56 UTC (permalink / raw)
  To: mingo; +Cc: luto, netdev, linux-kernel, x86, trinity

From: Ingo Molnar <mingo@kernel.org>
Date: Tue, 28 May 2013 10:56:00 +0200

> MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
> it's a hack that steals a bit to indicate to other networking code
> that a compat entry was used.  So don't allow it from a non-compat
> syscall.
> 
> This prevents an oops when running this code:
 ...
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>

Applied and queued up for -stable.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH/FIX] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-05-29  6:56     ` David Miller
@ 2013-05-29  8:11       ` Ingo Molnar
  0 siblings, 0 replies; 24+ messages in thread
From: Ingo Molnar @ 2013-05-29  8:11 UTC (permalink / raw)
  To: David Miller; +Cc: luto, netdev, linux-kernel, x86, trinity


* David Miller <davem@davemloft.net> wrote:

> From: Ingo Molnar <mingo@kernel.org>
> Date: Tue, 28 May 2013 10:56:00 +0200
> 
> > MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
> > it's a hack that steals a bit to indicate to other networking code
> > that a compat entry was used.  So don't allow it from a non-compat
> > syscall.
> > 
> > This prevents an oops when running this code:
>  ...
> > Cc: David S. Miller <davem@davemloft.net>
> > Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> 
> Applied and queued up for -stable.

Thanks David!

	Ingo

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-05-22 21:07 ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Andy Lutomirski
  2013-05-28  8:56   ` [PATCH/FIX] " Ingo Molnar
@ 2013-06-06  2:56   ` Michael Neuling
  2013-06-06  3:01     ` Anton Blanchard
  2013-06-06  4:35     ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Eric Dumazet
  1 sibling, 2 replies; 24+ messages in thread
From: Michael Neuling @ 2013-06-06  2:56 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: linux-kernel, x86, trinity, netdev, David S. Miller,
	Anton Blanchard, Benjamin Herrenschmidt, Linux PPC dev, torvalds

On Thu, May 23, 2013 at 7:07 AM, Andy Lutomirski <luto@amacapital.net> wrote:
> MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
> it's a hack that steals a bit to indicate to other networking code
> that a compat entry was used.  So don't allow it from a non-compat
> syscall.

Dave & Linus

This is causing a regression on 64bit powerpc with 32bit usermode.
When I hit userspace, udev is broken and I suspect all networking is
broken as well.

Can we please revert 1be374a0518a288147c6a7398792583200a67261 upstream?

Found via bisect.

Mikey

>
> This prevents an oops when running this code:
>
> int main()
> {
>         int s;
>         struct sockaddr_in addr;
>         struct msghdr *hdr;
>
>         char *highpage = mmap((void*)(TASK_SIZE_MAX - 4096), 4096,
>                               PROT_READ | PROT_WRITE,
>                               MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
>         if (highpage == MAP_FAILED)
>                 err(1, "mmap");
>
>         s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
>         if (s == -1)
>                 err(1, "socket");
>
>         addr.sin_family = AF_INET;
>         addr.sin_port = htons(1);
>         addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);This is upster

>         if (connect(s, (struct sockaddr*)&addr, sizeof(addr)) != 0)
>                 err(1, "connect");
>
>         void *evil = highpage + 4096 - COMPAT_MSGHDR_SIZE;
>         printf("Evil address is %p\n", evil);
>
>         if (syscall(__NR_sendmmsg, s, evil, 1, MSG_CMSG_COMPAT) < 0)
>                 err(1, "sendmmsg");
>
>         return 0;
> }
>
> Cc: David S. Miller <davem@davemloft.net>
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
>  net/socket.c | 33 +++++++++++++++++++++++++++++++--
>  1 file changed, 31 insertions(+), 2 deletions(-)
>
> diff --git a/net/socket.c b/net/socket.c
> index 88f759a..0e16888 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -2097,8 +2097,12 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, fla
>  {
>         int fput_needed, err;
>         struct msghdr msg_sys;
> -       struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
> +       struct socket *sock;
> +
> +       if (flags & MSG_CMSG_COMPAT)
> +               return -EINVAL;
>
> +       sock = sockfd_lookup_light(fd, &err, &fput_needed);
>         if (!sock)
>                 goto out;
>
> @@ -2171,6 +2175,8 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
>                 unsigned int, vlen, unsigned int, flags)
>  {
> +       if (flags & MSG_CMSG_COMPAT)
> +               return -EINVAL;
>         return __sys_sendmmsg(fd, mmsg, vlen, flags);
>  }
>
> @@ -2271,8 +2277,12 @@ SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
>  {
>         int fput_needed, err;
>         struct msghdr msg_sys;
> -       struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed);
> +       struct socket *sock;
> +
> +       if (flags & MSG_CMSG_COMPAT)
> +               return -EINVAL;
>
> +       sock = sockfd_lookup_light(fd, &err, &fput_needed);
>         if (!sock)
>                 goto out;
>
> @@ -2397,6 +2407,9 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg,
>         int datagrams;
>         struct timespec timeout_sys;
>
> +       if (flags & MSG_CMSG_COMPAT)
> +               return -EINVAL;
> +
>         if (!timeout)
>                 return __sys_recvmmsg(fd, mmsg, vlen, flags, NULL);
>
> @@ -2512,15 +2525,31 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
>                                    (int __user *)a[4]);
>                 break;
>         case SYS_SENDMSG:
> +               if (a[2] & MSG_CMSG_COMPAT) {
> +                       err = -EINVAL;
> +                       break;
> +               }
>                 err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
>                 break;
>         case SYS_SENDMMSG:
> +               if (a[3] & MSG_CMSG_COMPAT) {
> +                       err = -EINVAL;
> +                       break;
> +               }
>                 err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
>                 break;
>         case SYS_RECVMSG:
> +               if (a[2] & MSG_CMSG_COMPAT) {
> +                       err = -EINVAL;
> +                       break;
> +               }
>                 err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
>                 break;
>         case SYS_RECVMMSG:
> +               if (a[3] & MSG_CMSG_COMPAT) {
> +                       err = -EINVAL;
> +                       break;
> +               }
>                 err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
>                                    (struct timespec __user *)a[4]);
>                 break;
> --
> 1.8.1.4
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
>

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-06-06  2:56   ` [PATCH 5/5] " Michael Neuling
@ 2013-06-06  3:01     ` Anton Blanchard
  2013-06-06  3:29       ` Stephen Rothwell
  2013-06-06  4:35     ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Eric Dumazet
  1 sibling, 1 reply; 24+ messages in thread
From: Anton Blanchard @ 2013-06-06  3:01 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Andy Lutomirski, linux-kernel, x86, trinity, netdev,
	David S. Miller, Benjamin Herrenschmidt, Linux PPC dev, torvalds

Hi,

> This is causing a regression on 64bit powerpc with 32bit usermode.
> When I hit userspace, udev is broken and I suspect all networking is
> broken as well.
> 
> Can we please revert 1be374a0518a288147c6a7398792583200a67261
> upstream?
> 
> Found via bisect.

Doesn't this patch break compat_sys_sendmsg and compat_sys_recvmsg?
We'd need to move the guts of sys_* into compat_sys_* to fix it.

Anton

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-06-06  3:01     ` Anton Blanchard
@ 2013-06-06  3:29       ` Stephen Rothwell
  2013-06-06  5:38         ` [PATCH] net: Unbreak compat_sys_{send,recv}msg Andy Lutomirski
  0 siblings, 1 reply; 24+ messages in thread
From: Stephen Rothwell @ 2013-06-06  3:29 UTC (permalink / raw)
  To: Anton Blanchard
  Cc: Michael Neuling, netdev, x86, linux-kernel, Andy Lutomirski,
	Linux PPC dev, trinity, torvalds, David S. Miller

[-- Attachment #1: Type: text/plain, Size: 826 bytes --]

Hi Anton,

On Thu, 6 Jun 2013 13:01:05 +1000 Anton Blanchard <anton@samba.org> wrote:
>
> > This is causing a regression on 64bit powerpc with 32bit usermode.
> > When I hit userspace, udev is broken and I suspect all networking is
> > broken as well.
> > 
> > Can we please revert 1be374a0518a288147c6a7398792583200a67261
> > upstream?
> > 
> > Found via bisect.
> 
> Doesn't this patch break compat_sys_sendmsg and compat_sys_recvmsg?
> We'd need to move the guts of sys_* into compat_sys_* to fix it.

What you really need is a set of common functions that the sys_ and
compat_sys_ functions can call - with the sys_ funtions forbidding
MSG_CMSG_COMPAT and the compat_sys_ functions setting it.

-- 
Cheers,
Stephen Rothwell                    sfr@canb.auug.org.au
http://www.canb.auug.org.au/~sfr/

[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-06-06  2:56   ` [PATCH 5/5] " Michael Neuling
  2013-06-06  3:01     ` Anton Blanchard
@ 2013-06-06  4:35     ` Eric Dumazet
  2013-06-06  5:00       ` David Miller
  1 sibling, 1 reply; 24+ messages in thread
From: Eric Dumazet @ 2013-06-06  4:35 UTC (permalink / raw)
  To: Michael Neuling
  Cc: Andy Lutomirski, linux-kernel, x86, trinity, netdev,
	David S. Miller, Anton Blanchard, Benjamin Herrenschmidt,
	Linux PPC dev, torvalds

On Thu, 2013-06-06 at 12:56 +1000, Michael Neuling wrote:
> On Thu, May 23, 2013 at 7:07 AM, Andy Lutomirski <luto@amacapital.net> wrote:
> > MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
> > it's a hack that steals a bit to indicate to other networking code
> > that a compat entry was used.  So don't allow it from a non-compat
> > syscall.
> 
> Dave & Linus
> 
> This is causing a regression on 64bit powerpc with 32bit usermode.
> When I hit userspace, udev is broken and I suspect all networking is
> broken as well.
> 
> Can we please revert 1be374a0518a288147c6a7398792583200a67261 upstream?
> 

It seems to also break x86_64, if using 32bit usermode.




^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
  2013-06-06  4:35     ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Eric Dumazet
@ 2013-06-06  5:00       ` David Miller
  0 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2013-06-06  5:00 UTC (permalink / raw)
  To: eric.dumazet
  Cc: mikey, luto, linux-kernel, x86, trinity, netdev, anton, benh,
	linuxppc-dev, torvalds

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Wed, 05 Jun 2013 21:35:25 -0700

> On Thu, 2013-06-06 at 12:56 +1000, Michael Neuling wrote:
>> On Thu, May 23, 2013 at 7:07 AM, Andy Lutomirski <luto@amacapital.net> wrote:
>> > MSG_CMSG_COMPAT is (AFAIK) not intended to be part of the API --
>> > it's a hack that steals a bit to indicate to other networking code
>> > that a compat entry was used.  So don't allow it from a non-compat
>> > syscall.
>> 
>> Dave & Linus
>> 
>> This is causing a regression on 64bit powerpc with 32bit usermode.
>> When I hit userspace, udev is broken and I suspect all networking is
>> broken as well.
>> 
>> Can we please revert 1be374a0518a288147c6a7398792583200a67261 upstream?
>> 
> 
> It seems to also break x86_64, if using 32bit usermode.

Sorry, I only merged this because Ingo Molnar and others kept beating
me over the head about merging this fix.

Linus please revert, and I will not bow to such pressure in the future,
I should know better.


^ permalink raw reply	[flat|nested] 24+ messages in thread

* [PATCH] net: Unbreak compat_sys_{send,recv}msg
  2013-06-06  3:29       ` Stephen Rothwell
@ 2013-06-06  5:38         ` Andy Lutomirski
  2013-06-06  5:48           ` Michael Neuling
  2013-06-06  7:26           ` David Miller
  0 siblings, 2 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-06-06  5:38 UTC (permalink / raw)
  To: x86, torvalds, David S. Miller
  Cc: Michael Neuling, netdev, linux-kernel, Andy Lutomirski,
	Linux PPC dev, trinity

I broke them in this commit:

    commit 1be374a0518a288147c6a7398792583200a67261
    Author: Andy Lutomirski <luto@amacapital.net>
    Date:   Wed May 22 14:07:44 2013 -0700

        net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg

This patch adds __sys_sendmsg and __sys_sendmsg as common helpers that accept
MSG_CMSG_COMPAT and blocks MSG_CMSG_COMPAT at the syscall entrypoints.  It
also reverts some unnecessary checks in sys_socketcall.

Apparently I was suffering from underscore blindness the first time around.

Signed-off-by: Andy Lutomirski <luto@amacapital.net>
---

I've tested this a little, but I'm not sure I have a great test case.

If the decision is that it's better to leave this for the 3.11, I can send
a squashed version.  Note that the oops that this fixes is only an oops if
the other patches in the original series are applied.

(FWIW, I wasn't sure how to submit this stuff in the first place.  I submitted
some kernel hardening patches for the x86 tree that converted an access_ok
oddity in the net code into an actual oops.  In a bit of looking, I couldn't
find any failure mode other than a -EFAULT return without the other patches
applied.  This was clear in the patch series description but not in the
change log message for the net part.)

 include/linux/socket.h |  3 +++
 net/compat.c           | 13 +++++++--
 net/socket.c           | 72 +++++++++++++++++++++++---------------------------
 3 files changed, 47 insertions(+), 41 deletions(-)

diff --git a/include/linux/socket.h b/include/linux/socket.h
index 2b9f74b..e897bdc 100644
--- a/include/linux/socket.h
+++ b/include/linux/socket.h
@@ -321,6 +321,9 @@ extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
 
 struct timespec;
 
+/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
+extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
+extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
 extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 			  unsigned int flags, struct timespec *timeout);
 extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
diff --git a/net/compat.c b/net/compat.c
index 79ae884..f0a1ba6 100644
--- a/net/compat.c
+++ b/net/compat.c
@@ -734,19 +734,25 @@ static unsigned char nas[21] = {
 
 asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
-	return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+	return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
 				    unsigned int vlen, unsigned int flags)
 {
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
 	return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
 			      flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
 {
-	return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+	return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
 }
 
 asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags)
@@ -768,6 +774,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
 	int datagrams;
 	struct timespec ktspec;
 
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+
 	if (COMPAT_USE_64BIT_TIME)
 		return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
 				      flags | MSG_CMSG_COMPAT,
diff --git a/net/socket.c b/net/socket.c
index 0e16888..e216502 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1978,7 +1978,7 @@ struct used_address {
 	unsigned int name_len;
 };
 
-static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
+static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
 			 struct msghdr *msg_sys, unsigned int flags,
 			 struct used_address *used_address)
 {
@@ -2093,26 +2093,30 @@ out:
  *	BSD sendmsg interface
  */
 
-SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
+long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
 {
 	int fput_needed, err;
 	struct msghdr msg_sys;
 	struct socket *sock;
 
-	if (flags & MSG_CMSG_COMPAT)
-		return -EINVAL;
-
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
-	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
+	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
 
 	fput_light(sock->file, fput_needed);
 out:
 	return err;
 }
 
+SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
+{
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+	return __sys_sendmsg(fd, msg, flags);
+}
+
 /*
  *	Linux sendmmsg interface
  */
@@ -2143,15 +2147,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 
 	while (datagrams < vlen) {
 		if (MSG_CMSG_COMPAT & flags) {
-			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
-					    &msg_sys, flags, &used_address);
+			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
+					     &msg_sys, flags, &used_address);
 			if (err < 0)
 				break;
 			err = __put_user(err, &compat_entry->msg_len);
 			++compat_entry;
 		} else {
-			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
-					    &msg_sys, flags, &used_address);
+			err = ___sys_sendmsg(sock,
+					     (struct msghdr __user *)entry,
+					     &msg_sys, flags, &used_address);
 			if (err < 0)
 				break;
 			err = put_user(err, &entry->msg_len);
@@ -2180,7 +2185,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
 	return __sys_sendmmsg(fd, mmsg, vlen, flags);
 }
 
-static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
+static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
 			 struct msghdr *msg_sys, unsigned int flags, int nosec)
 {
 	struct compat_msghdr __user *msg_compat =
@@ -2272,27 +2277,31 @@ out:
  *	BSD recvmsg interface
  */
 
-SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
-		unsigned int, flags)
+long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
 {
 	int fput_needed, err;
 	struct msghdr msg_sys;
 	struct socket *sock;
 
-	if (flags & MSG_CMSG_COMPAT)
-		return -EINVAL;
-
 	sock = sockfd_lookup_light(fd, &err, &fput_needed);
 	if (!sock)
 		goto out;
 
-	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
+	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
 
 	fput_light(sock->file, fput_needed);
 out:
 	return err;
 }
 
+SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
+		unsigned int, flags)
+{
+	if (flags & MSG_CMSG_COMPAT)
+		return -EINVAL;
+	return __sys_recvmsg(fd, msg, flags);
+}
+
 /*
  *     Linux recvmmsg interface
  */
@@ -2330,17 +2339,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
 		 * No need to ask LSM for more than the first datagram.
 		 */
 		if (MSG_CMSG_COMPAT & flags) {
-			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
-					    &msg_sys, flags & ~MSG_WAITFORONE,
-					    datagrams);
+			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
+					     &msg_sys, flags & ~MSG_WAITFORONE,
+					     datagrams);
 			if (err < 0)
 				break;
 			err = __put_user(err, &compat_entry->msg_len);
 			++compat_entry;
 		} else {
-			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
-					    &msg_sys, flags & ~MSG_WAITFORONE,
-					    datagrams);
+			err = ___sys_recvmsg(sock,
+					     (struct msghdr __user *)entry,
+					     &msg_sys, flags & ~MSG_WAITFORONE,
+					     datagrams);
 			if (err < 0)
 				break;
 			err = put_user(err, &entry->msg_len);
@@ -2525,31 +2535,15 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
 				   (int __user *)a[4]);
 		break;
 	case SYS_SENDMSG:
-		if (a[2] & MSG_CMSG_COMPAT) {
-			err = -EINVAL;
-			break;
-		}
 		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
 		break;
 	case SYS_SENDMMSG:
-		if (a[3] & MSG_CMSG_COMPAT) {
-			err = -EINVAL;
-			break;
-		}
 		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
 		break;
 	case SYS_RECVMSG:
-		if (a[2] & MSG_CMSG_COMPAT) {
-			err = -EINVAL;
-			break;
-		}
 		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
 		break;
 	case SYS_RECVMMSG:
-		if (a[3] & MSG_CMSG_COMPAT) {
-			err = -EINVAL;
-			break;
-		}
 		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
 				   (struct timespec __user *)a[4]);
 		break;
-- 
1.8.1.4


^ permalink raw reply related	[flat|nested] 24+ messages in thread

* Re: [PATCH] net: Unbreak compat_sys_{send,recv}msg
  2013-06-06  5:38         ` [PATCH] net: Unbreak compat_sys_{send,recv}msg Andy Lutomirski
@ 2013-06-06  5:48           ` Michael Neuling
  2013-06-06  7:26           ` David Miller
  1 sibling, 0 replies; 24+ messages in thread
From: Michael Neuling @ 2013-06-06  5:48 UTC (permalink / raw)
  To: Andy Lutomirski
  Cc: x86, torvalds, David S. Miller, netdev, linux-kernel,
	Linux PPC dev, trinity

Andy Lutomirski <luto@amacapital.net> wrote:

> I broke them in this commit:
> 
>     commit 1be374a0518a288147c6a7398792583200a67261
>     Author: Andy Lutomirski <luto@amacapital.net>
>     Date:   Wed May 22 14:07:44 2013 -0700
> 
>         net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
> 
> This patch adds __sys_sendmsg and __sys_sendmsg as common helpers that accept
> MSG_CMSG_COMPAT and blocks MSG_CMSG_COMPAT at the syscall entrypoints.  It
> also reverts some unnecessary checks in sys_socketcall.
> 
> Apparently I was suffering from underscore blindness the first time around.

FWIW This fixes the problem I was seeing with powerpc 32bit user on 64
bit kernel.

Mikey

> 
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> ---
> 
> I've tested this a little, but I'm not sure I have a great test case.
> 
> If the decision is that it's better to leave this for the 3.11, I can send
> a squashed version.  Note that the oops that this fixes is only an oops if
> the other patches in the original series are applied.
> 
> (FWIW, I wasn't sure how to submit this stuff in the first place.  I submitted
> some kernel hardening patches for the x86 tree that converted an access_ok
> oddity in the net code into an actual oops.  In a bit of looking, I couldn't
> find any failure mode other than a -EFAULT return without the other patches
> applied.  This was clear in the patch series description but not in the
> change log message for the net part.)
> 
>  include/linux/socket.h |  3 +++
>  net/compat.c           | 13 +++++++--
>  net/socket.c           | 72 +++++++++++++++++++++++---------------------------
>  3 files changed, 47 insertions(+), 41 deletions(-)
> 
> diff --git a/include/linux/socket.h b/include/linux/socket.h
> index 2b9f74b..e897bdc 100644
> --- a/include/linux/socket.h
> +++ b/include/linux/socket.h
> @@ -321,6 +321,9 @@ extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
>  
>  struct timespec;
>  
> +/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
> +extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
> +extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
>  extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  			  unsigned int flags, struct timespec *timeout);
>  extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
> diff --git a/net/compat.c b/net/compat.c
> index 79ae884..f0a1ba6 100644
> --- a/net/compat.c
> +++ b/net/compat.c
> @@ -734,19 +734,25 @@ static unsigned char nas[21] = {
>  
>  asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
>  {
> -	return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
>  }
>  
>  asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
>  				    unsigned int vlen, unsigned int flags)
>  {
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
>  	return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
>  			      flags | MSG_CMSG_COMPAT);
>  }
>  
>  asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
>  {
> -	return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
>  }
>  
>  asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags)
> @@ -768,6 +774,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
>  	int datagrams;
>  	struct timespec ktspec;
>  
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +
>  	if (COMPAT_USE_64BIT_TIME)
>  		return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
>  				      flags | MSG_CMSG_COMPAT,
> diff --git a/net/socket.c b/net/socket.c
> index 0e16888..e216502 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -1978,7 +1978,7 @@ struct used_address {
>  	unsigned int name_len;
>  };
>  
> -static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
> +static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
>  			 struct msghdr *msg_sys, unsigned int flags,
>  			 struct used_address *used_address)
>  {
> @@ -2093,26 +2093,30 @@ out:
>   *	BSD sendmsg interface
>   */
>  
> -SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
> +long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
>  {
>  	int fput_needed, err;
>  	struct msghdr msg_sys;
>  	struct socket *sock;
>  
> -	if (flags & MSG_CMSG_COMPAT)
> -		return -EINVAL;
> -
>  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
>  	if (!sock)
>  		goto out;
>  
> -	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
> +	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
>  
>  	fput_light(sock->file, fput_needed);
>  out:
>  	return err;
>  }
>  
> +SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
> +{
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_sendmsg(fd, msg, flags);
> +}
> +
>  /*
>   *	Linux sendmmsg interface
>   */
> @@ -2143,15 +2147,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  
>  	while (datagrams < vlen) {
>  		if (MSG_CMSG_COMPAT & flags) {
> -			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
> -					    &msg_sys, flags, &used_address);
> +			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
> +					     &msg_sys, flags, &used_address);
>  			if (err < 0)
>  				break;
>  			err = __put_user(err, &compat_entry->msg_len);
>  			++compat_entry;
>  		} else {
> -			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
> -					    &msg_sys, flags, &used_address);
> +			err = ___sys_sendmsg(sock,
> +					     (struct msghdr __user *)entry,
> +					     &msg_sys, flags, &used_address);
>  			if (err < 0)
>  				break;
>  			err = put_user(err, &entry->msg_len);
> @@ -2180,7 +2185,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
>  	return __sys_sendmmsg(fd, mmsg, vlen, flags);
>  }
>  
> -static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
> +static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
>  			 struct msghdr *msg_sys, unsigned int flags, int nosec)
>  {
>  	struct compat_msghdr __user *msg_compat =
> @@ -2272,27 +2277,31 @@ out:
>   *	BSD recvmsg interface
>   */
>  
> -SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
> -		unsigned int, flags)
> +long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
>  {
>  	int fput_needed, err;
>  	struct msghdr msg_sys;
>  	struct socket *sock;
>  
> -	if (flags & MSG_CMSG_COMPAT)
> -		return -EINVAL;
> -
>  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
>  	if (!sock)
>  		goto out;
>  
> -	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
> +	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
>  
>  	fput_light(sock->file, fput_needed);
>  out:
>  	return err;
>  }
>  
> +SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
> +		unsigned int, flags)
> +{
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_recvmsg(fd, msg, flags);
> +}
> +
>  /*
>   *     Linux recvmmsg interface
>   */
> @@ -2330,17 +2339,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  		 * No need to ask LSM for more than the first datagram.
>  		 */
>  		if (MSG_CMSG_COMPAT & flags) {
> -			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
> -					    &msg_sys, flags & ~MSG_WAITFORONE,
> -					    datagrams);
> +			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
> +					     &msg_sys, flags & ~MSG_WAITFORONE,
> +					     datagrams);
>  			if (err < 0)
>  				break;
>  			err = __put_user(err, &compat_entry->msg_len);
>  			++compat_entry;
>  		} else {
> -			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
> -					    &msg_sys, flags & ~MSG_WAITFORONE,
> -					    datagrams);
> +			err = ___sys_recvmsg(sock,
> +					     (struct msghdr __user *)entry,
> +					     &msg_sys, flags & ~MSG_WAITFORONE,
> +					     datagrams);
>  			if (err < 0)
>  				break;
>  			err = put_user(err, &entry->msg_len);
> @@ -2525,31 +2535,15 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
>  				   (int __user *)a[4]);
>  		break;
>  	case SYS_SENDMSG:
> -		if (a[2] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
>  		break;
>  	case SYS_SENDMMSG:
> -		if (a[3] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
>  		break;
>  	case SYS_RECVMSG:
> -		if (a[2] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
>  		break;
>  	case SYS_RECVMMSG:
> -		if (a[3] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
>  				   (struct timespec __user *)a[4]);
>  		break;
> -- 
> 1.8.1.4
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] net: Unbreak compat_sys_{send,recv}msg
  2013-06-06  5:38         ` [PATCH] net: Unbreak compat_sys_{send,recv}msg Andy Lutomirski
  2013-06-06  5:48           ` Michael Neuling
@ 2013-06-06  7:26           ` David Miller
  2013-06-06 13:45             ` Eric Dumazet
  1 sibling, 1 reply; 24+ messages in thread
From: David Miller @ 2013-06-06  7:26 UTC (permalink / raw)
  To: luto
  Cc: x86, torvalds, mikey, netdev, linux-kernel, linuxppc-dev,
	trinity, eric.dumazet

From: Andy Lutomirski <luto@amacapital.net>
Date: Wed,  5 Jun 2013 22:38:26 -0700

> I broke them in this commit:
> 
>     commit 1be374a0518a288147c6a7398792583200a67261
>     Author: Andy Lutomirski <luto@amacapital.net>
>     Date:   Wed May 22 14:07:44 2013 -0700
> 
>         net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
> 
> This patch adds __sys_sendmsg and __sys_sendmsg as common helpers that accept
> MSG_CMSG_COMPAT and blocks MSG_CMSG_COMPAT at the syscall entrypoints.  It
> also reverts some unnecessary checks in sys_socketcall.
> 
> Apparently I was suffering from underscore blindness the first time around.
> 
> Signed-off-by: Andy Lutomirski <luto@amacapital.net>

Eric, can you test this patch too?

Thanks.

> ---
> 
> I've tested this a little, but I'm not sure I have a great test case.
> 
> If the decision is that it's better to leave this for the 3.11, I can send
> a squashed version.  Note that the oops that this fixes is only an oops if
> the other patches in the original series are applied.
> 
> (FWIW, I wasn't sure how to submit this stuff in the first place.  I submitted
> some kernel hardening patches for the x86 tree that converted an access_ok
> oddity in the net code into an actual oops.  In a bit of looking, I couldn't
> find any failure mode other than a -EFAULT return without the other patches
> applied.  This was clear in the patch series description but not in the
> change log message for the net part.)
> 
>  include/linux/socket.h |  3 +++
>  net/compat.c           | 13 +++++++--
>  net/socket.c           | 72 +++++++++++++++++++++++---------------------------
>  3 files changed, 47 insertions(+), 41 deletions(-)
> 
> diff --git a/include/linux/socket.h b/include/linux/socket.h
> index 2b9f74b..e897bdc 100644
> --- a/include/linux/socket.h
> +++ b/include/linux/socket.h
> @@ -321,6 +321,9 @@ extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
>  
>  struct timespec;
>  
> +/* The __sys_...msg variants allow MSG_CMSG_COMPAT */
> +extern long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags);
> +extern long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags);
>  extern int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  			  unsigned int flags, struct timespec *timeout);
>  extern int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg,
> diff --git a/net/compat.c b/net/compat.c
> index 79ae884..f0a1ba6 100644
> --- a/net/compat.c
> +++ b/net/compat.c
> @@ -734,19 +734,25 @@ static unsigned char nas[21] = {
>  
>  asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
>  {
> -	return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
>  }
>  
>  asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg,
>  				    unsigned int vlen, unsigned int flags)
>  {
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
>  	return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
>  			      flags | MSG_CMSG_COMPAT);
>  }
>  
>  asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags)
>  {
> -	return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT);
>  }
>  
>  asmlinkage long compat_sys_recv(int fd, void __user *buf, size_t len, unsigned int flags)
> @@ -768,6 +774,9 @@ asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg,
>  	int datagrams;
>  	struct timespec ktspec;
>  
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +
>  	if (COMPAT_USE_64BIT_TIME)
>  		return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen,
>  				      flags | MSG_CMSG_COMPAT,
> diff --git a/net/socket.c b/net/socket.c
> index 0e16888..e216502 100644
> --- a/net/socket.c
> +++ b/net/socket.c
> @@ -1978,7 +1978,7 @@ struct used_address {
>  	unsigned int name_len;
>  };
>  
> -static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
> +static int ___sys_sendmsg(struct socket *sock, struct msghdr __user *msg,
>  			 struct msghdr *msg_sys, unsigned int flags,
>  			 struct used_address *used_address)
>  {
> @@ -2093,26 +2093,30 @@ out:
>   *	BSD sendmsg interface
>   */
>  
> -SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
> +long __sys_sendmsg(int fd, struct msghdr __user *msg, unsigned flags)
>  {
>  	int fput_needed, err;
>  	struct msghdr msg_sys;
>  	struct socket *sock;
>  
> -	if (flags & MSG_CMSG_COMPAT)
> -		return -EINVAL;
> -
>  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
>  	if (!sock)
>  		goto out;
>  
> -	err = __sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
> +	err = ___sys_sendmsg(sock, msg, &msg_sys, flags, NULL);
>  
>  	fput_light(sock->file, fput_needed);
>  out:
>  	return err;
>  }
>  
> +SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned int, flags)
> +{
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_sendmsg(fd, msg, flags);
> +}
> +
>  /*
>   *	Linux sendmmsg interface
>   */
> @@ -2143,15 +2147,16 @@ int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  
>  	while (datagrams < vlen) {
>  		if (MSG_CMSG_COMPAT & flags) {
> -			err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
> -					    &msg_sys, flags, &used_address);
> +			err = ___sys_sendmsg(sock, (struct msghdr __user *)compat_entry,
> +					     &msg_sys, flags, &used_address);
>  			if (err < 0)
>  				break;
>  			err = __put_user(err, &compat_entry->msg_len);
>  			++compat_entry;
>  		} else {
> -			err = __sys_sendmsg(sock, (struct msghdr __user *)entry,
> -					    &msg_sys, flags, &used_address);
> +			err = ___sys_sendmsg(sock,
> +					     (struct msghdr __user *)entry,
> +					     &msg_sys, flags, &used_address);
>  			if (err < 0)
>  				break;
>  			err = put_user(err, &entry->msg_len);
> @@ -2180,7 +2185,7 @@ SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg,
>  	return __sys_sendmmsg(fd, mmsg, vlen, flags);
>  }
>  
> -static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
> +static int ___sys_recvmsg(struct socket *sock, struct msghdr __user *msg,
>  			 struct msghdr *msg_sys, unsigned int flags, int nosec)
>  {
>  	struct compat_msghdr __user *msg_compat =
> @@ -2272,27 +2277,31 @@ out:
>   *	BSD recvmsg interface
>   */
>  
> -SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
> -		unsigned int, flags)
> +long __sys_recvmsg(int fd, struct msghdr __user *msg, unsigned flags)
>  {
>  	int fput_needed, err;
>  	struct msghdr msg_sys;
>  	struct socket *sock;
>  
> -	if (flags & MSG_CMSG_COMPAT)
> -		return -EINVAL;
> -
>  	sock = sockfd_lookup_light(fd, &err, &fput_needed);
>  	if (!sock)
>  		goto out;
>  
> -	err = __sys_recvmsg(sock, msg, &msg_sys, flags, 0);
> +	err = ___sys_recvmsg(sock, msg, &msg_sys, flags, 0);
>  
>  	fput_light(sock->file, fput_needed);
>  out:
>  	return err;
>  }
>  
> +SYSCALL_DEFINE3(recvmsg, int, fd, struct msghdr __user *, msg,
> +		unsigned int, flags)
> +{
> +	if (flags & MSG_CMSG_COMPAT)
> +		return -EINVAL;
> +	return __sys_recvmsg(fd, msg, flags);
> +}
> +
>  /*
>   *     Linux recvmmsg interface
>   */
> @@ -2330,17 +2339,18 @@ int __sys_recvmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen,
>  		 * No need to ask LSM for more than the first datagram.
>  		 */
>  		if (MSG_CMSG_COMPAT & flags) {
> -			err = __sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
> -					    &msg_sys, flags & ~MSG_WAITFORONE,
> -					    datagrams);
> +			err = ___sys_recvmsg(sock, (struct msghdr __user *)compat_entry,
> +					     &msg_sys, flags & ~MSG_WAITFORONE,
> +					     datagrams);
>  			if (err < 0)
>  				break;
>  			err = __put_user(err, &compat_entry->msg_len);
>  			++compat_entry;
>  		} else {
> -			err = __sys_recvmsg(sock, (struct msghdr __user *)entry,
> -					    &msg_sys, flags & ~MSG_WAITFORONE,
> -					    datagrams);
> +			err = ___sys_recvmsg(sock,
> +					     (struct msghdr __user *)entry,
> +					     &msg_sys, flags & ~MSG_WAITFORONE,
> +					     datagrams);
>  			if (err < 0)
>  				break;
>  			err = put_user(err, &entry->msg_len);
> @@ -2525,31 +2535,15 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args)
>  				   (int __user *)a[4]);
>  		break;
>  	case SYS_SENDMSG:
> -		if (a[2] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]);
>  		break;
>  	case SYS_SENDMMSG:
> -		if (a[3] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]);
>  		break;
>  	case SYS_RECVMSG:
> -		if (a[2] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]);
>  		break;
>  	case SYS_RECVMMSG:
> -		if (a[3] & MSG_CMSG_COMPAT) {
> -			err = -EINVAL;
> -			break;
> -		}
>  		err = sys_recvmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3],
>  				   (struct timespec __user *)a[4]);
>  		break;
> -- 
> 1.8.1.4
> 
> --
> To unsubscribe from this list: send the line "unsubscribe trinity" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] net: Unbreak compat_sys_{send,recv}msg
  2013-06-06  7:26           ` David Miller
@ 2013-06-06 13:45             ` Eric Dumazet
  2013-06-06 18:53               ` David Miller
  0 siblings, 1 reply; 24+ messages in thread
From: Eric Dumazet @ 2013-06-06 13:45 UTC (permalink / raw)
  To: David Miller
  Cc: luto, x86, torvalds, mikey, netdev, linux-kernel, linuxppc-dev, trinity

On Thu, 2013-06-06 at 00:26 -0700, David Miller wrote:
> From: Andy Lutomirski <luto@amacapital.net>
> Date: Wed,  5 Jun 2013 22:38:26 -0700
> 
> > I broke them in this commit:
> > 
> >     commit 1be374a0518a288147c6a7398792583200a67261
> >     Author: Andy Lutomirski <luto@amacapital.net>
> >     Date:   Wed May 22 14:07:44 2013 -0700
> > 
> >         net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
> > 
> > This patch adds __sys_sendmsg and __sys_sendmsg as common helpers that accept
> > MSG_CMSG_COMPAT and blocks MSG_CMSG_COMPAT at the syscall entrypoints.  It
> > also reverts some unnecessary checks in sys_socketcall.
> > 
> > Apparently I was suffering from underscore blindness the first time around.
> > 
> > Signed-off-by: Andy Lutomirski <luto@amacapital.net>
> 
> Eric, can you test this patch too?

Yes, this fixes the problem as well on x86_64

Tested-by: Eric Dumazet <edumazet@google.com>

Thanks !

PS: I had following fuzz while applying on Linus tree :

patching file include/linux/socket.h
Hunk #1 succeeded at 320 (offset -1 lines).
patching file net/compat.c
patching file net/socket.c
Hunk #1 succeeded at 1956 (offset -22 lines).
Hunk #2 succeeded at 2071 (offset -22 lines).
Hunk #3 succeeded at 2125 (offset -22 lines).
Hunk #4 succeeded at 2163 (offset -22 lines).
Hunk #5 succeeded at 2255 (offset -22 lines).
Hunk #6 succeeded at 2317 (offset -22 lines).
Hunk #7 succeeded at 2515 (offset -20 lines).



^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH] net: Unbreak compat_sys_{send,recv}msg
  2013-06-06 13:45             ` Eric Dumazet
@ 2013-06-06 18:53               ` David Miller
  0 siblings, 0 replies; 24+ messages in thread
From: David Miller @ 2013-06-06 18:53 UTC (permalink / raw)
  To: eric.dumazet
  Cc: luto, x86, torvalds, mikey, netdev, linux-kernel, linuxppc-dev, trinity

From: Eric Dumazet <eric.dumazet@gmail.com>
Date: Thu, 06 Jun 2013 06:45:37 -0700

> On Thu, 2013-06-06 at 00:26 -0700, David Miller wrote:
>> From: Andy Lutomirski <luto@amacapital.net>
>> Date: Wed,  5 Jun 2013 22:38:26 -0700
>> 
>> > I broke them in this commit:
>> > 
>> >     commit 1be374a0518a288147c6a7398792583200a67261
>> >     Author: Andy Lutomirski <luto@amacapital.net>
>> >     Date:   Wed May 22 14:07:44 2013 -0700
>> > 
>> >         net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg
>> > 
>> > This patch adds __sys_sendmsg and __sys_sendmsg as common helpers that accept
>> > MSG_CMSG_COMPAT and blocks MSG_CMSG_COMPAT at the syscall entrypoints.  It
>> > also reverts some unnecessary checks in sys_socketcall.
>> > 
>> > Apparently I was suffering from underscore blindness the first time around.
>> > 
>> > Signed-off-by: Andy Lutomirski <luto@amacapital.net>
>> 
>> Eric, can you test this patch too?
> 
> Yes, this fixes the problem as well on x86_64
> 
> Tested-by: Eric Dumazet <edumazet@google.com>

Applied, thanks.

^ permalink raw reply	[flat|nested] 24+ messages in thread

* Re: [PATCH 0/5] x86: oops on uaccess faults outside of user addresses
  2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
                   ` (5 preceding siblings ...)
  2013-05-22 21:28 ` [PATCH 0/5] x86: oops on uaccess faults outside of user addresses David Miller
@ 2013-06-13 22:00 ` Andy Lutomirski
  6 siblings, 0 replies; 24+ messages in thread
From: Andy Lutomirski @ 2013-06-13 22:00 UTC (permalink / raw)
  To: linux-kernel; +Cc: x86, trinity, Andy Lutomirski

On Wed, May 22, 2013 at 2:07 PM, Andy Lutomirski <luto@amacapital.net> wrote:
> Currently, __get_user can't trigger an OOPS -- any exception will be
> caught and return -EFAULT.  This means that, if an access_ok check is
> missing somewhere, then an attacker can freely use it to probe for valid
> kernel mappings.
>
> This series annotates all of the exception fixups as "catch anything" or
> "catch valid uaccess faults", and skips the fixup (and hence oopses) if
> an instruction of the latter type faults for any reason other than a
> page fault to a user address.
>
> I know of only one bug of this type; it's fixed in patch 5.
>
> Perhaps surprisingly, this seems to survive Trinity fairly well.
>
> Andy Lutomirski (5):
>   x86: Split "utter crap" pnpbios fixup out of fixup_exception
>   x86: Clean up extable entry format (and free up a bit)
>   x86: Annotate _ASM_EXTABLE users to distinguish uaccess from
>     everything else
>   x86: Don't fixup uaccess faults to kernel or non-canonical addresses
>   net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg

Patch 5 is (for better or for worse) in -linus now.  What's the status
of the other four?  (They're certainly not 3.10 material.)

--Andy

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2013-06-13 22:01 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-05-22 21:07 [PATCH 0/5] x86: oops on uaccess faults outside of user addresses Andy Lutomirski
2013-05-22 21:07 ` [PATCH 1/5] x86: Split "utter crap" pnpbios fixup out of fixup_exception Andy Lutomirski
2013-05-22 21:07 ` [PATCH 2/5] x86: Clean up extable entry format (and free up a bit) Andy Lutomirski
2013-05-22 21:07 ` [PATCH 3/5] x86: Annotate _ASM_EXTABLE users to distinguish uaccess from everything else Andy Lutomirski
2013-05-22 21:07 ` [PATCH 4/5] x86: Don't fixup uaccess faults to kernel or non-canonical addresses Andy Lutomirski
2013-05-22 21:07 ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Andy Lutomirski
2013-05-28  8:56   ` [PATCH/FIX] " Ingo Molnar
2013-05-29  6:56     ` David Miller
2013-05-29  8:11       ` Ingo Molnar
2013-06-06  2:56   ` [PATCH 5/5] " Michael Neuling
2013-06-06  3:01     ` Anton Blanchard
2013-06-06  3:29       ` Stephen Rothwell
2013-06-06  5:38         ` [PATCH] net: Unbreak compat_sys_{send,recv}msg Andy Lutomirski
2013-06-06  5:48           ` Michael Neuling
2013-06-06  7:26           ` David Miller
2013-06-06 13:45             ` Eric Dumazet
2013-06-06 18:53               ` David Miller
2013-06-06  4:35     ` [PATCH 5/5] net: Block MSG_CMSG_COMPAT in send(m)msg and recv(m)msg Eric Dumazet
2013-06-06  5:00       ` David Miller
2013-05-22 21:28 ` [PATCH 0/5] x86: oops on uaccess faults outside of user addresses David Miller
2013-05-28  8:25   ` Ingo Molnar
2013-05-28  8:51     ` David Miller
2013-05-28  8:54       ` Ingo Molnar
2013-06-13 22:00 ` Andy Lutomirski

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).