linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [RFC -tip 0/4] x86: reduce fixup of uaccess
@ 2009-01-06  3:06 Hiroshi Shimamoto
  2009-01-06  3:08 ` [RFC -tip 1/4] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64() Hiroshi Shimamoto
                   ` (5 more replies)
  0 siblings, 6 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-06  3:06 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel

This is my second try to reduce fixup code size for exceptions of uaccess.

This patch series reduces fixup code for exceptions of uaccess in signal.

I gave up to make direct jump to end of function when an exception occurs.
However, I thought fixup code could be reduced. The concept is that to add
uaccess_err in thread_info and set it to -EFAULT on exception, finally check
this value on the last of function.

Is this good to reduce code size?

The code size reductions are below;
$ size *signal*.o.*
   text	   data	    bss	    dec	    hex	filename
   4741	      0	      0	   4741	   1285	ia32_signal.o.new
   6006	      0	      0	   6006	   1776	ia32_signal.o.old
   3577	      0	      0	   3577	    df9	signal.o.new
   4540	      0	      0	   4540	   11bc	signal.o.old
   3855	      0	      0	   3855	    f0f	signal32.o.new
   4876	      0	      0	   4876	   130c	signal32.o.old

Thanks,
Hiroshi

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

* [RFC -tip 1/4] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64()
  2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
@ 2009-01-06  3:08 ` Hiroshi Shimamoto
  2009-01-06  3:08 ` [RFC -tip 2/4] x86: uaccess: introduce new __{get|put}_user exception handling framework Hiroshi Shimamoto
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-06  3:08 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: cleanup

Rename __put_user_u64() to __put_user_asm_u64() like __get_user_asm_u64().

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/include/asm/uaccess.h |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 4340055..1a38180 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -186,7 +186,7 @@ extern int __get_user_bad(void);
 
 
 #ifdef CONFIG_X86_32
-#define __put_user_u64(x, addr, err)					\
+#define __put_user_asm_u64(x, addr, err)				\
 	asm volatile("1:	movl %%eax,0(%2)\n"			\
 		     "2:	movl %%edx,4(%2)\n"			\
 		     "3:\n"						\
@@ -203,7 +203,7 @@ extern int __get_user_bad(void);
 	asm volatile("call __put_user_8" : "=a" (__ret_pu)	\
 		     : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
 #else
-#define __put_user_u64(x, ptr, retval) \
+#define __put_user_asm_u64(x, ptr, retval) \
 	__put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT)
 #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
 #endif
@@ -279,7 +279,7 @@ do {									\
 		__put_user_asm(x, ptr, retval, "l", "k",  "ir", errret);\
 		break;							\
 	case 8:								\
-		__put_user_u64((__typeof__(*ptr))(x), ptr, retval);	\
+		__put_user_asm_u64((__typeof__(*ptr))(x), ptr, retval);	\
 		break;							\
 	default:							\
 		__put_user_bad();					\
-- 
1.6.0.4


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

* [RFC -tip 2/4] x86: uaccess: introduce new __{get|put}_user exception handling framework
  2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
  2009-01-06  3:08 ` [RFC -tip 1/4] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64() Hiroshi Shimamoto
@ 2009-01-06  3:08 ` Hiroshi Shimamoto
  2009-01-06  3:09 ` [RFC -tip 3/4] x86: signal: use __{get|put}_user_ex " Hiroshi Shimamoto
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-06  3:08 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: introduce new uaccess exception handling framework

Introduce new uaccess exception handling framework.

__{get|put}_user_ex_try() begins exception block and
__{get|put}_user_ex_catch() ends block and if an exeption occurred in this
block using __{get|put}_user_ex, thread_info->uaccess_err is set to -EFAULT
and err is set at __{get|put}_user_ex_catch().

int func()
{
	int err = 0;

	__get_user_ex_try();

	__get_user_ex(...);
	__get_user_ex(...);
	:

	__get_user_ex_catch(&err);
	return err;
}

Note: __get_user_ex() is not clear the value when an exception occurs, it's
different from the behavior of __get_user(), but I think it doesn't matter.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/include/asm/thread_info.h |    1 +
 arch/x86/include/asm/uaccess.h     |  100 ++++++++++++++++++++++++++++++++++++
 arch/x86/mm/extable.c              |    5 ++
 3 files changed, 106 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index efdf938..46beb17 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -40,6 +40,7 @@ struct thread_info {
 						*/
 	__u8			supervisor_stack[0];
 #endif
+	int			uaccess_err;
 };
 
 #define INIT_THREAD_INFO(tsk)			\
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 1a38180..d3ac43e 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -199,12 +199,22 @@ extern int __get_user_bad(void);
 		     : "=r" (err)					\
 		     : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err))
 
+#define __put_user_asm_ex_u64(x, addr)					\
+	asm volatile("1:	movl %%eax,0(%1)\n"			\
+		     "2:	movl %%edx,4(%1)\n"			\
+		     "3:\n"						\
+		     _ASM_EXTABLE(1b, 2b - 1b)				\
+		     _ASM_EXTABLE(2b, 3b - 2b)				\
+		     : : "A" (x), "r" (addr))
+
 #define __put_user_x8(x, ptr, __ret_pu)				\
 	asm volatile("call __put_user_8" : "=a" (__ret_pu)	\
 		     : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
 #else
 #define __put_user_asm_u64(x, ptr, retval) \
 	__put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT)
+#define __put_user_asm_ex_u64(x, addr)	\
+	__put_user_asm_ex(x, addr, "q", "", "Zr")
 #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
 #endif
 
@@ -286,6 +296,27 @@ do {									\
 	}								\
 } while (0)
 
+#define __put_user_size_ex(x, ptr, size)				\
+do {									\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	case 1:								\
+		__put_user_asm_ex(x, ptr, "b", "b", "iq");		\
+		break;							\
+	case 2:								\
+		__put_user_asm_ex(x, ptr, "w", "w", "ir");		\
+		break;							\
+	case 4:								\
+		__put_user_asm_ex(x, ptr, "l", "k", "ir");		\
+		break;							\
+	case 8:								\
+		__put_user_asm_ex_u64((__typeof__(*ptr))(x), ptr);	\
+		break;							\
+	default:							\
+		__put_user_bad();					\
+	}								\
+} while (0)
+
 #else
 
 #define __put_user_size(x, ptr, size, retval, errret)			\
@@ -311,9 +342,12 @@ do {									\
 
 #ifdef CONFIG_X86_32
 #define __get_user_asm_u64(x, ptr, retval, errret)	(x) = __get_user_bad()
+#define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else
 #define __get_user_asm_u64(x, ptr, retval, errret) \
 	 __get_user_asm(x, ptr, retval, "q", "", "=r", errret)
+#define __get_user_asm_ex_u64(x, ptr) \
+	 __get_user_asm_ex(x, ptr, "q", "", "=r")
 #endif
 
 #define __get_user_size(x, ptr, size, retval, errret)			\
@@ -350,6 +384,33 @@ do {									\
 		     : "=r" (err), ltype(x)				\
 		     : "m" (__m(addr)), "i" (errret), "0" (err))
 
+#define __get_user_size_ex(x, ptr, size)				\
+do {									\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	case 1:								\
+		__get_user_asm_ex(x, ptr, "b", "b", "=q");		\
+		break;							\
+	case 2:								\
+		__get_user_asm_ex(x, ptr, "w", "w", "=r");		\
+		break;							\
+	case 4:								\
+		__get_user_asm_ex(x, ptr, "l", "k", "=r");		\
+		break;							\
+	case 8:								\
+		__get_user_asm_ex_u64(x, ptr);				\
+		break;							\
+	default:							\
+		(x) = __get_user_bad();					\
+	}								\
+} while (0)
+
+#define __get_user_asm_ex(x, addr, itype, rtype, ltype)			\
+	asm volatile("1:	mov"itype" %1,%"rtype"0\n"		\
+		     "2:\n"						\
+		     _ASM_EXTABLE(1b, 2b - 1b)				\
+		     : ltype(x) : "m" (__m(addr)))
+
 #define __put_user_nocheck(x, ptr, size)			\
 ({								\
 	int __pu_err;						\
@@ -385,6 +446,23 @@ struct __large_struct { unsigned long buf[100]; };
 		     _ASM_EXTABLE(1b, 3b)				\
 		     : "=r"(err)					\
 		     : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
+
+#define __put_user_asm_ex(x, addr, itype, rtype, ltype)			\
+	asm volatile("1:	mov"itype" %"rtype"0,%1\n"		\
+		     "2:\n"						\
+		     _ASM_EXTABLE(1b, 2b - 1b)				\
+		     : : ltype(x), "m" (__m(addr)))
+
+#define __uaccess_ex_try()	do {					\
+	int __prev_err = current_thread_info()->uaccess_err;		\
+	current_thread_info()->uaccess_err = 0;				\
+	barrier()
+
+#define __uaccess_ex_catch(err)					\
+	(err) |= current_thread_info()->uaccess_err;			\
+	current_thread_info()->uaccess_err = __prev_err;		\
+} while (0)
+
 /**
  * __get_user: - Get a simple variable from user space, with less checking.
  * @x:   Variable to store result.
@@ -408,6 +486,19 @@ struct __large_struct { unsigned long buf[100]; };
 
 #define __get_user(x, ptr)						\
 	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
+#define __get_user_ex(x, ptr)	do {					\
+	unsigned long __gue_val;					\
+	__get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr))));	\
+	(x) = (__force __typeof__(*(ptr)))__gue_val;			\
+} while (0)
+
+#define __get_user_ex_try()	\
+	__uaccess_ex_try()
+
+#define __get_user_ex_catch(perr)	\
+	__uaccess_ex_catch(*(perr))
+
 /**
  * __put_user: - Write a simple value into user space, with less checking.
  * @x:   Value to copy to user space.
@@ -431,6 +522,15 @@ struct __large_struct { unsigned long buf[100]; };
 #define __put_user(x, ptr)						\
 	__put_user_nocheck((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
 
+#define __put_user_ex(x, ptr)						\
+	__put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+#define __put_user_ex_try() \
+	__uaccess_ex_try()
+
+#define __put_user_ex_catch(perr)	\
+	__uaccess_ex_catch(*(perr))
+
 #define __get_user_unaligned __get_user
 #define __put_user_unaligned __put_user
 
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 7e8db53..e185e03 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -23,6 +23,11 @@ int fixup_exception(struct pt_regs *regs)
 
 	fixup = search_exception_tables(regs->ip);
 	if (fixup) {
+		if (fixup->fixup < 16) {
+			current_thread_info()->uaccess_err = -EFAULT;
+			regs->ip += fixup->fixup;
+			return 1;
+		}
 		regs->ip = fixup->fixup;
 		return 1;
 	}
-- 
1.6.0.4


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

* [RFC -tip 3/4] x86: signal: use __{get|put}_user_ex exception handling framework
  2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
  2009-01-06  3:08 ` [RFC -tip 1/4] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64() Hiroshi Shimamoto
  2009-01-06  3:08 ` [RFC -tip 2/4] x86: uaccess: introduce new __{get|put}_user exception handling framework Hiroshi Shimamoto
@ 2009-01-06  3:09 ` Hiroshi Shimamoto
  2009-01-06  3:10 ` [RFC -tip 4/4] x86: ia32_signal: " Hiroshi Shimamoto
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-06  3:09 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: use new uaccess exception handling framework

Use __{get|put}_user_ex exception handling framework.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/kernel/signal.c |  214 +++++++++++++++++++++++++---------------------
 1 files changed, 118 insertions(+), 96 deletions(-)

diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 4fa5243..0927549 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -51,24 +51,24 @@
 #endif
 
 #define COPY(x)			{		\
-	err |= __get_user(regs->x, &sc->x);	\
+	__get_user_ex(regs->x, &sc->x);		\
 }
 
 #define COPY_SEG(seg)		{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		__get_user_ex(tmp, &sc->seg);		\
 		regs->seg = tmp;			\
 }
 
 #define COPY_SEG_CPL3(seg)	{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		__get_user_ex(tmp, &sc->seg);		\
 		regs->seg = tmp | 3;			\
 }
 
 #define GET_SEG(seg)		{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		__get_user_ex(tmp, &sc->seg);		\
 		loadsegment(seg, tmp);			\
 }
 
@@ -83,6 +83,8 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
+	__get_user_ex_try();
+
 #ifdef CONFIG_X86_32
 	GET_SEG(gs);
 	COPY_SEG(fs);
@@ -114,14 +116,16 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 	COPY_SEG_CPL3(cs);
 #endif /* CONFIG_X86_32 */
 
-	err |= __get_user(tmpflags, &sc->flags);
+	__get_user_ex(tmpflags, &sc->flags);
 	regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
 	regs->orig_ax = -1;		/* disable syscall checks */
 
-	err |= __get_user(buf, &sc->fpstate);
+	__get_user_ex(buf, &sc->fpstate);
 	err |= restore_i387_xstate(buf);
 
-	err |= __get_user(*pax, &sc->ax);
+	__get_user_ex(*pax, &sc->ax);
+
+	__get_user_ex_catch(&err);
 	return err;
 }
 
@@ -131,57 +135,61 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
 {
 	int err = 0;
 
+	__put_user_ex_try();
+
 #ifdef CONFIG_X86_32
 	{
 		unsigned int tmp;
 
 		savesegment(gs, tmp);
-		err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
+		__put_user_ex(tmp, (unsigned int __user *)&sc->gs);
 	}
-	err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs);
-	err |= __put_user(regs->es, (unsigned int __user *)&sc->es);
-	err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds);
+	__put_user_ex(regs->fs, (unsigned int __user *)&sc->fs);
+	__put_user_ex(regs->es, (unsigned int __user *)&sc->es);
+	__put_user_ex(regs->ds, (unsigned int __user *)&sc->ds);
 #endif /* CONFIG_X86_32 */
 
-	err |= __put_user(regs->di, &sc->di);
-	err |= __put_user(regs->si, &sc->si);
-	err |= __put_user(regs->bp, &sc->bp);
-	err |= __put_user(regs->sp, &sc->sp);
-	err |= __put_user(regs->bx, &sc->bx);
-	err |= __put_user(regs->dx, &sc->dx);
-	err |= __put_user(regs->cx, &sc->cx);
-	err |= __put_user(regs->ax, &sc->ax);
+	__put_user_ex(regs->di, &sc->di);
+	__put_user_ex(regs->si, &sc->si);
+	__put_user_ex(regs->bp, &sc->bp);
+	__put_user_ex(regs->sp, &sc->sp);
+	__put_user_ex(regs->bx, &sc->bx);
+	__put_user_ex(regs->dx, &sc->dx);
+	__put_user_ex(regs->cx, &sc->cx);
+	__put_user_ex(regs->ax, &sc->ax);
 #ifdef CONFIG_X86_64
-	err |= __put_user(regs->r8, &sc->r8);
-	err |= __put_user(regs->r9, &sc->r9);
-	err |= __put_user(regs->r10, &sc->r10);
-	err |= __put_user(regs->r11, &sc->r11);
-	err |= __put_user(regs->r12, &sc->r12);
-	err |= __put_user(regs->r13, &sc->r13);
-	err |= __put_user(regs->r14, &sc->r14);
-	err |= __put_user(regs->r15, &sc->r15);
+	__put_user_ex(regs->r8, &sc->r8);
+	__put_user_ex(regs->r9, &sc->r9);
+	__put_user_ex(regs->r10, &sc->r10);
+	__put_user_ex(regs->r11, &sc->r11);
+	__put_user_ex(regs->r12, &sc->r12);
+	__put_user_ex(regs->r13, &sc->r13);
+	__put_user_ex(regs->r14, &sc->r14);
+	__put_user_ex(regs->r15, &sc->r15);
 #endif /* CONFIG_X86_64 */
 
-	err |= __put_user(current->thread.trap_no, &sc->trapno);
-	err |= __put_user(current->thread.error_code, &sc->err);
-	err |= __put_user(regs->ip, &sc->ip);
+	__put_user_ex(current->thread.trap_no, &sc->trapno);
+	__put_user_ex(current->thread.error_code, &sc->err);
+	__put_user_ex(regs->ip, &sc->ip);
 #ifdef CONFIG_X86_32
-	err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
-	err |= __put_user(regs->flags, &sc->flags);
-	err |= __put_user(regs->sp, &sc->sp_at_signal);
-	err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
+	__put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
+	__put_user_ex(regs->flags, &sc->flags);
+	__put_user_ex(regs->sp, &sc->sp_at_signal);
+	__put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
 #else /* !CONFIG_X86_32 */
-	err |= __put_user(regs->flags, &sc->flags);
-	err |= __put_user(regs->cs, &sc->cs);
-	err |= __put_user(0, &sc->gs);
-	err |= __put_user(0, &sc->fs);
+	__put_user_ex(regs->flags, &sc->flags);
+	__put_user_ex(regs->cs, &sc->cs);
+	__put_user_ex(0, &sc->gs);
+	__put_user_ex(0, &sc->fs);
 #endif /* CONFIG_X86_32 */
 
-	err |= __put_user(fpstate, &sc->fpstate);
+	__put_user_ex(fpstate, &sc->fpstate);
 
 	/* non-iBCS2 extensions.. */
-	err |= __put_user(mask, &sc->oldmask);
-	err |= __put_user(current->thread.cr2, &sc->cr2);
+	__put_user_ex(mask, &sc->oldmask);
+	__put_user_ex(current->thread.cr2, &sc->cr2);
+
+	__put_user_ex_catch(&err);
 
 	return err;
 }
@@ -274,16 +282,19 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	if (__put_user(sig, &frame->sig))
-		return -EFAULT;
+	__put_user_ex_try();
 
-	if (setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
-		return -EFAULT;
+	__put_user_ex(sig, &frame->sig);
+
+	err |= setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]);
+	if (err)
+		goto out;
 
 	if (_NSIG_WORDS > 1) {
-		if (__copy_to_user(&frame->extramask, &set->sig[1],
-				   sizeof(frame->extramask)))
-			return -EFAULT;
+		err |= __copy_to_user(&frame->extramask, &set->sig[1],
+				      sizeof(frame->extramask));
+		if (err)
+			goto out;
 	}
 
 	if (current->mm->context.vdso)
@@ -294,7 +305,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 		restorer = ka->sa.sa_restorer;
 
 	/* Set up to return from userspace.  */
-	err |= __put_user(restorer, &frame->pretcode);
+	__put_user_ex(restorer, &frame->pretcode);
 
 	/*
 	 * This is popl %eax ; movl $__NR_sigreturn, %eax ; int $0x80
@@ -303,10 +314,7 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	 * reasons and because gdb uses it as a signature to notice
 	 * signal handler stack frames.
 	 */
-	err |= __put_user(*((u64 *)&retcode), (u64 *)frame->retcode);
-
-	if (err)
-		return -EFAULT;
+	__put_user_ex(*((u64 *)&retcode), (u64 *)frame->retcode);
 
 	/* Set up registers for signal handler */
 	regs->sp = (unsigned long)frame;
@@ -320,7 +328,10 @@ __setup_frame(int sig, struct k_sigaction *ka, sigset_t *set,
 	regs->ss = __USER_DS;
 	regs->cs = __USER_CS;
 
-	return 0;
+out:
+	__put_user_ex_catch(&err);
+
+	return err;
 }
 
 static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -336,34 +347,36 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	err |= __put_user(sig, &frame->sig);
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
+	__put_user_ex_try();
+
+	__put_user_ex(sig, &frame->sig);
+	__put_user_ex(&frame->info, &frame->pinfo);
+	__put_user_ex(&frame->uc, &frame->puc);
 	err |= copy_siginfo_to_user(&frame->info, info);
 	if (err)
-		return -EFAULT;
+		goto out;
 
 	/* Create the ucontext.  */
 	if (cpu_has_xsave)
-		err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
+		__put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
 	else
-		err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(regs->sp),
+		__put_user_ex(0, &frame->uc.uc_flags);
+	__put_user_ex(0, &frame->uc.uc_link);
+	__put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	__put_user_ex(sas_ss_flags(regs->sp),
 			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	__put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
 				regs, set->sig[0]);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		return -EFAULT;
+		goto out;
 
 	/* Set up to return from userspace.  */
 	restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
-	err |= __put_user(restorer, &frame->pretcode);
+	__put_user_ex(restorer, &frame->pretcode);
 
 	/*
 	 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
@@ -372,10 +385,7 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	 * reasons and because gdb uses it as a signature to notice
 	 * signal handler stack frames.
 	 */
-	err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
-
-	if (err)
-		return -EFAULT;
+	__put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
 
 	/* Set up registers for signal handler */
 	regs->sp = (unsigned long)frame;
@@ -389,7 +399,10 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	regs->ss = __USER_DS;
 	regs->cs = __USER_CS;
 
-	return 0;
+out:
+	__put_user_ex_catch(&err);
+
+	return err;
 }
 #else /* !CONFIG_X86_32 */
 /*
@@ -436,16 +449,18 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			return -EFAULT;
 	}
 
+	__put_user_ex_try();
+
 	/* Create the ucontext.  */
 	if (cpu_has_xsave)
-		err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
+		__put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
 	else
-		err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(regs->sp),
+		__put_user_ex(0, &frame->uc.uc_flags);
+	__put_user_ex(0, &frame->uc.uc_link);
+	__put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	__put_user_ex(sas_ss_flags(regs->sp),
 			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	__put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
 	err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 
@@ -453,15 +468,13 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	   already in userspace.  */
 	/* x86-64 should always use SA_RESTORER. */
 	if (ka->sa.sa_flags & SA_RESTORER) {
-		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
+		__put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
 	} else {
 		/* could use a vstub here */
-		return -EFAULT;
+		err = -EFAULT;
+		goto out;
 	}
 
-	if (err)
-		return -EFAULT;
-
 	/* Set up registers for signal handler */
 	regs->di = sig;
 	/* In case the signal handler was declared without prototypes */
@@ -479,7 +492,10 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	   even if the handler happens to be interrupting 32-bit code. */
 	regs->cs = __USER_CS;
 
-	return 0;
+out:
+	__put_user_ex_catch(&err);
+
+	return err;
 }
 #endif /* CONFIG_X86_32 */
 
@@ -509,31 +525,37 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 	      struct old_sigaction __user *oact)
 {
 	struct k_sigaction new_ka, old_ka;
-	int ret;
+	int ret = 0;
 
 	if (act) {
 		old_sigset_t mask;
 
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
+			return -EFAULT;
+		__get_user_ex_try();
+		__get_user_ex(new_ka.sa.sa_handler, &act->sa_handler);
+		__get_user_ex(new_ka.sa.sa_flags, &act->sa_flags);
+		__get_user_ex(mask, &act->sa_mask);
+		__get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer);
+		__get_user_ex_catch(&ret);
+		if (ret)
 			return -EFAULT;
-
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
 		siginitset(&new_ka.sa.sa_mask, mask);
 	}
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
+			return -EFAULT;
+		__put_user_ex_try();
+		__put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler);
+		__put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags);
+		__put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+		__put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer);
+		__put_user_ex_catch(&ret);
+		if (ret)
 			return -EFAULT;
-
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
 	}
 
 	return ret;
-- 
1.6.0.4


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

* [RFC -tip 4/4] x86: ia32_signal: use __{get|put}_user_ex exception handling framework
  2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
                   ` (2 preceding siblings ...)
  2009-01-06  3:09 ` [RFC -tip 3/4] x86: signal: use __{get|put}_user_ex " Hiroshi Shimamoto
@ 2009-01-06  3:10 ` Hiroshi Shimamoto
  2009-01-06 10:09 ` [RFC -tip 0/4] x86: reduce fixup of uaccess Ingo Molnar
  2009-01-07  9:33 ` H. Peter Anvin
  5 siblings, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-06  3:10 UTC (permalink / raw)
  To: Ingo Molnar, Thomas Gleixner, H. Peter Anvin; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: use new uaccess exception handling framework

Use __{get|put}_user_ex exception handling framework.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/ia32/ia32_signal.c |  220 +++++++++++++++++++++++++------------------
 1 files changed, 127 insertions(+), 93 deletions(-)

diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 9dabd00..9502a77 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -46,79 +46,88 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
-	int err;
+	int err = 0;
 
 	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
+	__put_user_ex_try();
+
 	/* If you change siginfo_t structure, please make sure that
 	   this code is fixed accordingly.
 	   It should never copy any pad contained in the structure
 	   to avoid security leaks, but must copy the generic
 	   3 ints plus the relevant union member.  */
-	err = __put_user(from->si_signo, &to->si_signo);
-	err |= __put_user(from->si_errno, &to->si_errno);
-	err |= __put_user((short)from->si_code, &to->si_code);
+	__put_user_ex(from->si_signo, &to->si_signo);
+	__put_user_ex(from->si_errno, &to->si_errno);
+	__put_user_ex((short)from->si_code, &to->si_code);
 
 	if (from->si_code < 0) {
-		err |= __put_user(from->si_pid, &to->si_pid);
-		err |= __put_user(from->si_uid, &to->si_uid);
-		err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
+		__put_user_ex(from->si_pid, &to->si_pid);
+		__put_user_ex(from->si_uid, &to->si_uid);
+		__put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
 	} else {
 		/*
 		 * First 32bits of unions are always present:
 		 * si_pid === si_band === si_tid === si_addr(LS half)
 		 */
-		err |= __put_user(from->_sifields._pad[0],
+		__put_user_ex(from->_sifields._pad[0],
 				  &to->_sifields._pad[0]);
 		switch (from->si_code >> 16) {
 		case __SI_FAULT >> 16:
 			break;
 		case __SI_CHLD >> 16:
-			err |= __put_user(from->si_utime, &to->si_utime);
-			err |= __put_user(from->si_stime, &to->si_stime);
-			err |= __put_user(from->si_status, &to->si_status);
+			__put_user_ex(from->si_utime, &to->si_utime);
+			__put_user_ex(from->si_stime, &to->si_stime);
+			__put_user_ex(from->si_status, &to->si_status);
 			/* FALL THROUGH */
 		default:
 		case __SI_KILL >> 16:
-			err |= __put_user(from->si_uid, &to->si_uid);
+			__put_user_ex(from->si_uid, &to->si_uid);
 			break;
 		case __SI_POLL >> 16:
-			err |= __put_user(from->si_fd, &to->si_fd);
+			__put_user_ex(from->si_fd, &to->si_fd);
 			break;
 		case __SI_TIMER >> 16:
-			err |= __put_user(from->si_overrun, &to->si_overrun);
-			err |= __put_user(ptr_to_compat(from->si_ptr),
+			__put_user_ex(from->si_overrun, &to->si_overrun);
+			__put_user_ex(ptr_to_compat(from->si_ptr),
 					  &to->si_ptr);
 			break;
 			 /* This is not generated by the kernel as of now.  */
 		case __SI_RT >> 16:
 		case __SI_MESGQ >> 16:
-			err |= __put_user(from->si_uid, &to->si_uid);
-			err |= __put_user(from->si_int, &to->si_int);
+			__put_user_ex(from->si_uid, &to->si_uid);
+			__put_user_ex(from->si_int, &to->si_int);
 			break;
 		}
 	}
+
+	__put_user_ex_catch(&err);
+
 	return err;
 }
 
 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 {
-	int err;
+	int err = 0;
 	u32 ptr32;
 
 	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
-	err = __get_user(to->si_signo, &from->si_signo);
-	err |= __get_user(to->si_errno, &from->si_errno);
-	err |= __get_user(to->si_code, &from->si_code);
+	__get_user_ex_try();
 
-	err |= __get_user(to->si_pid, &from->si_pid);
-	err |= __get_user(to->si_uid, &from->si_uid);
-	err |= __get_user(ptr32, &from->si_ptr);
+	__get_user_ex(to->si_signo, &from->si_signo);
+	__get_user_ex(to->si_errno, &from->si_errno);
+	__get_user_ex(to->si_code, &from->si_code);
+
+	__get_user_ex(to->si_pid, &from->si_pid);
+	__get_user_ex(to->si_uid, &from->si_uid);
+	__get_user_ex(ptr32, &from->si_ptr);
 	to->si_ptr = compat_ptr(ptr32);
 
+	__get_user_ex_catch(&err);
+
 	return err;
 }
 
@@ -142,31 +151,41 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 				  struct pt_regs *regs)
 {
 	stack_t uss, uoss;
-	int ret;
+	int ret, err = 0;
 	mm_segment_t seg;
 
+
 	if (uss_ptr) {
 		u32 ptr;
 
 		memset(&uss, 0, sizeof(stack_t));
-		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
-			    __get_user(ptr, &uss_ptr->ss_sp) ||
-			    __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
-			    __get_user(uss.ss_size, &uss_ptr->ss_size))
+		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
 			return -EFAULT;
+		__get_user_ex_try();
+		__get_user_ex(ptr, &uss_ptr->ss_sp);
+		__get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
+		__get_user_ex(uss.ss_size, &uss_ptr->ss_size);
 		uss.ss_sp = compat_ptr(ptr);
+		__get_user_ex_catch(&err);
+		if (err)
+			return -EFAULT;
 	}
 	seg = get_fs();
 	set_fs(KERNEL_DS);
 	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
 	set_fs(seg);
 	if (ret >= 0 && uoss_ptr)  {
-		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
-		    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
-		    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
-		    __put_user(uoss.ss_size, &uoss_ptr->ss_size))
-			ret = -EFAULT;
+		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
+			return -EFAULT;
+		__put_user_ex_try();
+		__put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
+		__put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
+		__put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
+		__put_user_ex_catch(&ret);
+		if (err)
+			return -EFAULT;
 	}
+
 	return ret;
 }
 
@@ -174,18 +193,18 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
  * Do a signal return; undo the signal stack.
  */
 #define COPY(x)			{		\
-	err |= __get_user(regs->x, &sc->x);	\
+	__get_user_ex(regs->x, &sc->x);		\
 }
 
 #define COPY_SEG_CPL3(seg)	{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		__get_user_ex(tmp, &sc->seg);		\
 		regs->seg = tmp | 3;			\
 }
 
 #define RELOAD_SEG(seg)		{		\
 	unsigned int cur, pre;			\
-	err |= __get_user(pre, &sc->seg);	\
+	__get_user_ex(pre, &sc->seg);		\
 	savesegment(seg, cur);			\
 	pre |= 3;				\
 	if (pre != cur)				\
@@ -203,6 +222,8 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
+	__get_user_ex_try();
+
 #if DEBUG_SIG
 	printk(KERN_DEBUG "SIG restore_sigcontext: "
 	       "sc=%p err(%x) eip(%x) cs(%x) flg(%x)\n",
@@ -215,7 +236,7 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
 	 * the handler, but does not clobber them at least in the
 	 * normal case.
 	 */
-	err |= __get_user(gs, &sc->gs);
+	__get_user_ex(gs, &sc->gs);
 	gs |= 3;
 	savesegment(gs, oldgs);
 	if (gs != oldgs)
@@ -232,16 +253,18 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
 	COPY_SEG_CPL3(cs);
 	COPY_SEG_CPL3(ss);
 
-	err |= __get_user(tmpflags, &sc->flags);
+	__get_user_ex(tmpflags, &sc->flags);
 	regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
 	/* disable syscall checks */
 	regs->orig_ax = -1;
 
-	err |= __get_user(tmp, &sc->fpstate);
+	__get_user_ex(tmp, &sc->fpstate);
 	buf = compat_ptr(tmp);
 	err |= restore_i387_xstate_ia32(buf);
 
-	err |= __get_user(*pax, &sc->ax);
+	__get_user_ex(*pax, &sc->ax);
+
+	__get_user_ex_catch(&err);
 	return err;
 }
 
@@ -319,36 +342,40 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
 {
 	int tmp, err = 0;
 
+	__put_user_ex_try();
+
 	savesegment(gs, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
+	__put_user_ex(tmp, (unsigned int __user *)&sc->gs);
 	savesegment(fs, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
+	__put_user_ex(tmp, (unsigned int __user *)&sc->fs);
 	savesegment(ds, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
+	__put_user_ex(tmp, (unsigned int __user *)&sc->ds);
 	savesegment(es, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->es);
-
-	err |= __put_user(regs->di, &sc->di);
-	err |= __put_user(regs->si, &sc->si);
-	err |= __put_user(regs->bp, &sc->bp);
-	err |= __put_user(regs->sp, &sc->sp);
-	err |= __put_user(regs->bx, &sc->bx);
-	err |= __put_user(regs->dx, &sc->dx);
-	err |= __put_user(regs->cx, &sc->cx);
-	err |= __put_user(regs->ax, &sc->ax);
-	err |= __put_user(current->thread.trap_no, &sc->trapno);
-	err |= __put_user(current->thread.error_code, &sc->err);
-	err |= __put_user(regs->ip, &sc->ip);
-	err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
-	err |= __put_user(regs->flags, &sc->flags);
-	err |= __put_user(regs->sp, &sc->sp_at_signal);
-	err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
-
-	err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate);
+	__put_user_ex(tmp, (unsigned int __user *)&sc->es);
+
+	__put_user_ex(regs->di, &sc->di);
+	__put_user_ex(regs->si, &sc->si);
+	__put_user_ex(regs->bp, &sc->bp);
+	__put_user_ex(regs->sp, &sc->sp);
+	__put_user_ex(regs->bx, &sc->bx);
+	__put_user_ex(regs->dx, &sc->dx);
+	__put_user_ex(regs->cx, &sc->cx);
+	__put_user_ex(regs->ax, &sc->ax);
+	__put_user_ex(current->thread.trap_no, &sc->trapno);
+	__put_user_ex(current->thread.error_code, &sc->err);
+	__put_user_ex(regs->ip, &sc->ip);
+	__put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
+	__put_user_ex(regs->flags, &sc->flags);
+	__put_user_ex(regs->sp, &sc->sp_at_signal);
+	__put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
+
+	__put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
 
 	/* non-iBCS2 extensions.. */
-	err |= __put_user(mask, &sc->oldmask);
-	err |= __put_user(current->thread.cr2, &sc->cr2);
+	__put_user_ex(mask, &sc->oldmask);
+	__put_user_ex(current->thread.cr2, &sc->cr2);
+
+	__put_user_ex_catch(&err);
 
 	return err;
 }
@@ -415,16 +442,19 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	if (__put_user(sig, &frame->sig))
-		return -EFAULT;
+	__put_user_ex_try();
 
-	if (ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]))
-		return -EFAULT;
+	__put_user_ex(sig, &frame->sig);
+
+	err |= ia32_setup_sigcontext(&frame->sc, fpstate, regs, set->sig[0]);
+	if (err)
+		goto out;
 
 	if (_COMPAT_NSIG_WORDS > 1) {
-		if (__copy_to_user(frame->extramask, &set->sig[1],
-				   sizeof(frame->extramask)))
-			return -EFAULT;
+		err |= __copy_to_user(frame->extramask, &set->sig[1],
+				      sizeof(frame->extramask));
+		if (err)
+			goto out;
 	}
 
 	if (ka->sa.sa_flags & SA_RESTORER) {
@@ -437,15 +467,13 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 		else
 			restorer = &frame->retcode;
 	}
-	err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
+	__put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
 
 	/*
 	 * These are actually not used anymore, but left because some
 	 * gdb versions depend on them as a marker.
 	 */
-	err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
-	if (err)
-		return -EFAULT;
+	__put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
 
 	/* Set up registers for signal handler */
 	regs->sp = (unsigned long) frame;
@@ -467,7 +495,10 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 	       current->comm, current->pid, frame, regs->ip, frame->pretcode);
 #endif
 
-	return 0;
+out:
+	__put_user_ex_catch(&err);
+
+	return err;
 }
 
 int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
@@ -496,43 +527,43 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	err |= __put_user(sig, &frame->sig);
-	err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
-	err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
+	__put_user_ex_try();
+
+	__put_user_ex(sig, &frame->sig);
+	__put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
+	__put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
 	err |= copy_siginfo_to_user32(&frame->info, info);
 	if (err)
-		return -EFAULT;
+		goto out;
 
 	/* Create the ucontext.  */
 	if (cpu_has_xsave)
-		err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
+		__put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
 	else
-		err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(regs->sp),
+		__put_user_ex(0, &frame->uc.uc_flags);
+	__put_user_ex(0, &frame->uc.uc_link);
+	__put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+	__put_user_ex(sas_ss_flags(regs->sp),
 			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	__put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
 	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
 				     regs, set->sig[0]);
 	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	if (err)
-		return -EFAULT;
+		goto out;
 
 	if (ka->sa.sa_flags & SA_RESTORER)
 		restorer = ka->sa.sa_restorer;
 	else
 		restorer = VDSO32_SYMBOL(current->mm->context.vdso,
 					 rt_sigreturn);
-	err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
+	__put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
 
 	/*
 	 * Not actually used anymore, but left because some gdb
 	 * versions need it.
 	 */
-	err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
-	if (err)
-		return -EFAULT;
+	__put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
 
 	/* Set up registers for signal handler */
 	regs->sp = (unsigned long) frame;
@@ -554,5 +585,8 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	       current->comm, current->pid, frame, regs->ip, frame->pretcode);
 #endif
 
-	return 0;
+out:
+	__put_user_ex_catch(&err);
+
+	return err;
 }
-- 
1.6.0.4


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

* Re: [RFC -tip 0/4] x86: reduce fixup of uaccess
  2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
                   ` (3 preceding siblings ...)
  2009-01-06  3:10 ` [RFC -tip 4/4] x86: ia32_signal: " Hiroshi Shimamoto
@ 2009-01-06 10:09 ` Ingo Molnar
  2009-01-07  9:33 ` H. Peter Anvin
  5 siblings, 0 replies; 17+ messages in thread
From: Ingo Molnar @ 2009-01-06 10:09 UTC (permalink / raw)
  To: Hiroshi Shimamoto; +Cc: Thomas Gleixner, H. Peter Anvin, linux-kernel


* Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com> wrote:

> This is my second try to reduce fixup code size for exceptions of uaccess.
> 
> This patch series reduces fixup code for exceptions of uaccess in signal.
> 
> I gave up to make direct jump to end of function when an exception occurs.
> However, I thought fixup code could be reduced. The concept is that to add
> uaccess_err in thread_info and set it to -EFAULT on exception, finally check
> this value on the last of function.
> 
> Is this good to reduce code size?
> 
> The code size reductions are below;
> $ size *signal*.o.*
>    text	   data	    bss	    dec	    hex	filename
>    4741	      0	      0	   4741	   1285	ia32_signal.o.new
>    6006	      0	      0	   6006	   1776	ia32_signal.o.old
>    3577	      0	      0	   3577	    df9	signal.o.new
>    4540	      0	      0	   4540	   11bc	signal.o.old
>    3855	      0	      0	   3855	    f0f	signal32.o.new
>    4876	      0	      0	   4876	   130c	signal32.o.old

looks very nice! Since kernel execution is i-cache-cold in the typical 
case, this will probably transform into a performance improvement as well.

	Ingo

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

* Re: [RFC -tip 0/4] x86: reduce fixup of uaccess
  2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
                   ` (4 preceding siblings ...)
  2009-01-06 10:09 ` [RFC -tip 0/4] x86: reduce fixup of uaccess Ingo Molnar
@ 2009-01-07  9:33 ` H. Peter Anvin
  2009-01-08  1:43   ` Hiroshi Shimamoto
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
  5 siblings, 2 replies; 17+ messages in thread
From: H. Peter Anvin @ 2009-01-07  9:33 UTC (permalink / raw)
  To: Hiroshi Shimamoto; +Cc: Ingo Molnar, Thomas Gleixner, linux-kernel

Hiroshi Shimamoto wrote:
> This is my second try to reduce fixup code size for exceptions of uaccess.
> 
> This patch series reduces fixup code for exceptions of uaccess in signal.
> 
> I gave up to make direct jump to end of function when an exception occurs.
> However, I thought fixup code could be reduced. The concept is that to add
> uaccess_err in thread_info and set it to -EFAULT on exception, finally check
> this value on the last of function.
> 
> Is this good to reduce code size?
> 

Hello Hiroshi,

The patches look technically really nice.  I have a couple of stylistic
comments, though, which I'd like yours and others' comments on.

This introduces a new blocking construct, and it's not immediately
obvious in the source code.  I think introducing a technically redundant
set of braces and dropping the parens from the try construct and the
redundant pointer might look better:

	get_user_try {
		/* do stuff */
	} get_user_catch(err);

This makes it, in my opinion, much clearer that it is a new bracing
construct, and it also eliminates the need to form a pointer to "err"
(even though the compiler doesn't actually do so, it looks like it does
to the programmer.)

Also, I don't think we need double underscores for the wrapping
construct, since the get_user/__get_user (check/nocheck) etc.
distinction doesn't directly apply there.

What do you think?

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


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

* Re: [RFC -tip 0/4] x86: reduce fixup of uaccess
  2009-01-07  9:33 ` H. Peter Anvin
@ 2009-01-08  1:43   ` Hiroshi Shimamoto
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
  1 sibling, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-08  1:43 UTC (permalink / raw)
  To: H. Peter Anvin; +Cc: Ingo Molnar, Thomas Gleixner, linux-kernel

H. Peter Anvin wrote:
> Hiroshi Shimamoto wrote:
>> This is my second try to reduce fixup code size for exceptions of uaccess.
>>
>> This patch series reduces fixup code for exceptions of uaccess in signal.
>>
>> I gave up to make direct jump to end of function when an exception occurs.
>> However, I thought fixup code could be reduced. The concept is that to add
>> uaccess_err in thread_info and set it to -EFAULT on exception, finally check
>> this value on the last of function.
>>
>> Is this good to reduce code size?
>>
> 
> Hello Hiroshi,

Hello Peter,

> 
> The patches look technically really nice.  I have a couple of stylistic
> comments, though, which I'd like yours and others' comments on.

Thanks for comments.

> 
> This introduces a new blocking construct, and it's not immediately
> obvious in the source code.  I think introducing a technically redundant

Yeah, I think it's not friendly about readability now.

> set of braces and dropping the parens from the try construct and the
> redundant pointer might look better:
> 
> 	get_user_try {
> 		/* do stuff */
> 	} get_user_catch(err);

OK, I'll update like that.

> 
> This makes it, in my opinion, much clearer that it is a new bracing
> construct, and it also eliminates the need to form a pointer to "err"

I'm not sure which is better plain "err" or pointer to "err".

> (even though the compiler doesn't actually do so, it looks like it does
> to the programmer.)
> 
> Also, I don't think we need double underscores for the wrapping
> construct, since the get_user/__get_user (check/nocheck) etc.
> distinction doesn't directly apply there.

OK. Will drop underscores.

I'll repost update patches.

Thanks,
Hiroshi


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

* [RFC v2 -tip 0/3] x86: reduce fixup of uaccess
  2009-01-07  9:33 ` H. Peter Anvin
  2009-01-08  1:43   ` Hiroshi Shimamoto
@ 2009-01-23 23:48   ` Hiroshi Shimamoto
  2009-01-23 23:49     ` [RFC v2 -tip 1/3] x86: uaccess: introduce try and catch framework Hiroshi Shimamoto
                       ` (4 more replies)
  1 sibling, 5 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-23 23:48 UTC (permalink / raw)
  To: H. Peter Anvin, Ingo Molnar, Thomas Gleixner; +Cc: linux-kernel

This patch series redues fixup code for exceptions of uaccess in signal.

There is a lot of fixup code which is generated by using __{get|put}_user.
I think that code can be reduced. The concept is that to add uaccess_err in
thread_info and set it to -EFAULT on exception, finally check this value on
the last of function.

The code size reductions are below;
$ size *signal*.o.*
   text	   data	    bss	    dec	    hex	filename
   4596	      0	      0	   4596	   11f4	ia32_signal.o.new
   6006	      0	      0	   6006	   1776	ia32_signal.o.old
   3583	      0	      0	   3583	    dff	signal.o.new
   4540	      0	      0	   4540	   11bc	signal.o.old
   3863	      0	      0	   3863	    f17	signal32.o.new
   4876	      0	      0	   4876	   130c	signal32.o.old
[ signal32.o means signal.o on 32-bit. ]

ChangeLog v1 -> v2
	- Change framework syntax. Previous version doesn't look easy to read.
	  Remove parens from try and add redundant braces as Peter suggested.
		get_user_try {
			get_user_ex(...);
			:
		} get_user_catch(err);
	- Remove double underscores.


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

* [RFC v2 -tip 1/3] x86: uaccess: introduce try and catch framework
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
@ 2009-01-23 23:49     ` Hiroshi Shimamoto
  2009-01-23 23:50     ` [RFC v2 -tip 2/3] x86: signal: use {get|put}_user_try and catch Hiroshi Shimamoto
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-23 23:49 UTC (permalink / raw)
  To: H. Peter Anvin, Ingo Molnar, Thomas Gleixner; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: introduce new uaccess exception handling framework

Introduce {get|put}_user_try and {get|put}_user_catch as new uaccess exception
handling framework.
{get|put}_user_try begins exception block and {get|put}_user_catch(err) ends
the block and gets err if an exception occured in {get|put}_user_ex() in the
block. The exception is stored thread_info->uaccess_err.

The example usage of this framework is below;
int func()
{
	int err = 0;

	get_user_try {
		get_user_ex(...);
		get_user_ex(...);
		:
	} get_user_catch(err);

	return err;
}

Note: get_user_ex() is not clear the value when an exception occurs, it's
different from the behavior of __get_user(), but I think it doesn't matter.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/include/asm/thread_info.h |    1 +
 arch/x86/include/asm/uaccess.h     |  103 ++++++++++++++++++++++++++++++++++++
 arch/x86/mm/extable.c              |    6 ++
 3 files changed, 110 insertions(+), 0 deletions(-)

diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index f384889..ca7310e 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -40,6 +40,7 @@ struct thread_info {
 						*/
 	__u8			supervisor_stack[0];
 #endif
+	int			uaccess_err;
 };
 
 #define INIT_THREAD_INFO(tsk)			\
diff --git a/arch/x86/include/asm/uaccess.h b/arch/x86/include/asm/uaccess.h
index 69d2757..0ec6de4 100644
--- a/arch/x86/include/asm/uaccess.h
+++ b/arch/x86/include/asm/uaccess.h
@@ -199,12 +199,22 @@ extern int __get_user_bad(void);
 		     : "=r" (err)					\
 		     : "A" (x), "r" (addr), "i" (-EFAULT), "0" (err))
 
+#define __put_user_asm_ex_u64(x, addr)					\
+	asm volatile("1:	movl %%eax,0(%1)\n"			\
+		     "2:	movl %%edx,4(%1)\n"			\
+		     "3:\n"						\
+		     _ASM_EXTABLE(1b, 2b - 1b)				\
+		     _ASM_EXTABLE(2b, 3b - 2b)				\
+		     : : "A" (x), "r" (addr))
+
 #define __put_user_x8(x, ptr, __ret_pu)				\
 	asm volatile("call __put_user_8" : "=a" (__ret_pu)	\
 		     : "A" ((typeof(*(ptr)))(x)), "c" (ptr) : "ebx")
 #else
 #define __put_user_asm_u64(x, ptr, retval) \
 	__put_user_asm(x, ptr, retval, "q", "", "Zr", -EFAULT)
+#define __put_user_asm_ex_u64(x, addr)	\
+	__put_user_asm_ex(x, addr, "q", "", "Zr")
 #define __put_user_x8(x, ptr, __ret_pu) __put_user_x(8, x, ptr, __ret_pu)
 #endif
 
@@ -286,6 +296,27 @@ do {									\
 	}								\
 } while (0)
 
+#define __put_user_size_ex(x, ptr, size)				\
+do {									\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	case 1:								\
+		__put_user_asm_ex(x, ptr, "b", "b", "iq");		\
+		break;							\
+	case 2:								\
+		__put_user_asm_ex(x, ptr, "w", "w", "ir");		\
+		break;							\
+	case 4:								\
+		__put_user_asm_ex(x, ptr, "l", "k", "ir");		\
+		break;							\
+	case 8:								\
+		__put_user_asm_ex_u64((__typeof__(*ptr))(x), ptr);	\
+		break;							\
+	default:							\
+		__put_user_bad();					\
+	}								\
+} while (0)
+
 #else
 
 #define __put_user_size(x, ptr, size, retval, errret)			\
@@ -311,9 +342,12 @@ do {									\
 
 #ifdef CONFIG_X86_32
 #define __get_user_asm_u64(x, ptr, retval, errret)	(x) = __get_user_bad()
+#define __get_user_asm_ex_u64(x, ptr)			(x) = __get_user_bad()
 #else
 #define __get_user_asm_u64(x, ptr, retval, errret) \
 	 __get_user_asm(x, ptr, retval, "q", "", "=r", errret)
+#define __get_user_asm_ex_u64(x, ptr) \
+	 __get_user_asm_ex(x, ptr, "q", "", "=r")
 #endif
 
 #define __get_user_size(x, ptr, size, retval, errret)			\
@@ -350,6 +384,33 @@ do {									\
 		     : "=r" (err), ltype(x)				\
 		     : "m" (__m(addr)), "i" (errret), "0" (err))
 
+#define __get_user_size_ex(x, ptr, size)				\
+do {									\
+	__chk_user_ptr(ptr);						\
+	switch (size) {							\
+	case 1:								\
+		__get_user_asm_ex(x, ptr, "b", "b", "=q");		\
+		break;							\
+	case 2:								\
+		__get_user_asm_ex(x, ptr, "w", "w", "=r");		\
+		break;							\
+	case 4:								\
+		__get_user_asm_ex(x, ptr, "l", "k", "=r");		\
+		break;							\
+	case 8:								\
+		__get_user_asm_ex_u64(x, ptr);				\
+		break;							\
+	default:							\
+		(x) = __get_user_bad();					\
+	}								\
+} while (0)
+
+#define __get_user_asm_ex(x, addr, itype, rtype, ltype)			\
+	asm volatile("1:	mov"itype" %1,%"rtype"0\n"		\
+		     "2:\n"						\
+		     _ASM_EXTABLE(1b, 2b - 1b)				\
+		     : ltype(x) : "m" (__m(addr)))
+
 #define __put_user_nocheck(x, ptr, size)			\
 ({								\
 	int __pu_err;						\
@@ -385,6 +446,26 @@ struct __large_struct { unsigned long buf[100]; };
 		     _ASM_EXTABLE(1b, 3b)				\
 		     : "=r"(err)					\
 		     : ltype(x), "m" (__m(addr)), "i" (errret), "0" (err))
+
+#define __put_user_asm_ex(x, addr, itype, rtype, ltype)			\
+	asm volatile("1:	mov"itype" %"rtype"0,%1\n"		\
+		     "2:\n"						\
+		     _ASM_EXTABLE(1b, 2b - 1b)				\
+		     : : ltype(x), "m" (__m(addr)))
+
+/*
+ * uaccess_try and catch
+ */
+#define uaccess_try	do {						\
+	int prev_err = current_thread_info()->uaccess_err;		\
+	current_thread_info()->uaccess_err = 0;				\
+	barrier();
+
+#define uaccess_catch(err)						\
+	(err) |= current_thread_info()->uaccess_err;			\
+	current_thread_info()->uaccess_err = prev_err;			\
+} while (0)
+
 /**
  * __get_user: - Get a simple variable from user space, with less checking.
  * @x:   Variable to store result.
@@ -408,6 +489,7 @@ struct __large_struct { unsigned long buf[100]; };
 
 #define __get_user(x, ptr)						\
 	__get_user_nocheck((x), (ptr), sizeof(*(ptr)))
+
 /**
  * __put_user: - Write a simple value into user space, with less checking.
  * @x:   Value to copy to user space.
@@ -435,6 +517,27 @@ struct __large_struct { unsigned long buf[100]; };
 #define __put_user_unaligned __put_user
 
 /*
+ * {get|put}_user_try and catch
+ *
+ * get_user_try {
+ *	get_user_ex(...);
+ * } get_user_catch(err)
+ */
+#define get_user_try		uaccess_try
+#define get_user_catch(err)	uaccess_catch(err)
+#define put_user_try		uaccess_try
+#define put_user_catch(err)	uaccess_catch(err)
+
+#define get_user_ex(x, ptr)	do {					\
+	unsigned long __gue_val;					\
+	__get_user_size_ex((__gue_val), (ptr), (sizeof(*(ptr))));	\
+	(x) = (__force __typeof__(*(ptr)))__gue_val;			\
+} while (0)
+
+#define put_user_ex(x, ptr)						\
+	__put_user_size_ex((__typeof__(*(ptr)))(x), (ptr), sizeof(*(ptr)))
+
+/*
  * movsl can be slow when source and dest are not both 8-byte aligned
  */
 #ifdef CONFIG_X86_INTEL_USERCOPY
diff --git a/arch/x86/mm/extable.c b/arch/x86/mm/extable.c
index 7e8db53..61b41ca 100644
--- a/arch/x86/mm/extable.c
+++ b/arch/x86/mm/extable.c
@@ -23,6 +23,12 @@ int fixup_exception(struct pt_regs *regs)
 
 	fixup = search_exception_tables(regs->ip);
 	if (fixup) {
+		/* If fixup is less than 16, it means uaccess error */
+		if (fixup->fixup < 16) {
+			current_thread_info()->uaccess_err = -EFAULT;
+			regs->ip += fixup->fixup;
+			return 1;
+		}
 		regs->ip = fixup->fixup;
 		return 1;
 	}
-- 
1.6.0.4


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

* [RFC v2 -tip 2/3] x86: signal: use {get|put}_user_try and catch
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
  2009-01-23 23:49     ` [RFC v2 -tip 1/3] x86: uaccess: introduce try and catch framework Hiroshi Shimamoto
@ 2009-01-23 23:50     ` Hiroshi Shimamoto
  2009-01-23 23:50     ` [RFC v2 -tip 3/3] x86: ia32_signal: " Hiroshi Shimamoto
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-23 23:50 UTC (permalink / raw)
  To: H. Peter Anvin, Ingo Molnar, Thomas Gleixner; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: use new framework

Use {get|put}_user_try, catch, and _ex in arch/x86/kernel/signal.c.

Note: this patch contains "WARNING: line over 80 characters", because when
introducing new block I insert an indent to avoid mistakes by edit.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/kernel/signal.c |  297 ++++++++++++++++++++++++----------------------
 1 files changed, 157 insertions(+), 140 deletions(-)

diff --git a/arch/x86/kernel/signal.c b/arch/x86/kernel/signal.c
index 0bc73d6..40e089b 100644
--- a/arch/x86/kernel/signal.c
+++ b/arch/x86/kernel/signal.c
@@ -51,24 +51,24 @@
 #endif
 
 #define COPY(x)			{		\
-	err |= __get_user(regs->x, &sc->x);	\
+	get_user_ex(regs->x, &sc->x);		\
 }
 
 #define COPY_SEG(seg)		{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		get_user_ex(tmp, &sc->seg);		\
 		regs->seg = tmp;			\
 }
 
 #define COPY_SEG_CPL3(seg)	{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		get_user_ex(tmp, &sc->seg);		\
 		regs->seg = tmp | 3;			\
 }
 
 #define GET_SEG(seg)		{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		get_user_ex(tmp, &sc->seg);		\
 		loadsegment(seg, tmp);			\
 }
 
@@ -83,45 +83,49 @@ restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *sc,
 	/* Always make any pending restarted system calls return -EINTR */
 	current_thread_info()->restart_block.fn = do_no_restart_syscall;
 
+	get_user_try {
+
 #ifdef CONFIG_X86_32
-	GET_SEG(gs);
-	COPY_SEG(fs);
-	COPY_SEG(es);
-	COPY_SEG(ds);
+		GET_SEG(gs);
+		COPY_SEG(fs);
+		COPY_SEG(es);
+		COPY_SEG(ds);
 #endif /* CONFIG_X86_32 */
 
-	COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
-	COPY(dx); COPY(cx); COPY(ip);
+		COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
+		COPY(dx); COPY(cx); COPY(ip);
 
 #ifdef CONFIG_X86_64
-	COPY(r8);
-	COPY(r9);
-	COPY(r10);
-	COPY(r11);
-	COPY(r12);
-	COPY(r13);
-	COPY(r14);
-	COPY(r15);
+		COPY(r8);
+		COPY(r9);
+		COPY(r10);
+		COPY(r11);
+		COPY(r12);
+		COPY(r13);
+		COPY(r14);
+		COPY(r15);
 #endif /* CONFIG_X86_64 */
 
 #ifdef CONFIG_X86_32
-	COPY_SEG_CPL3(cs);
-	COPY_SEG_CPL3(ss);
+		COPY_SEG_CPL3(cs);
+		COPY_SEG_CPL3(ss);
 #else /* !CONFIG_X86_32 */
-	/* Kernel saves and restores only the CS segment register on signals,
-	 * which is the bare minimum needed to allow mixed 32/64-bit code.
-	 * App's signal handler can save/restore other segments if needed. */
-	COPY_SEG_CPL3(cs);
+		/* Kernel saves and restores only the CS segment register on signals,
+		 * which is the bare minimum needed to allow mixed 32/64-bit code.
+		 * App's signal handler can save/restore other segments if needed. */
+		COPY_SEG_CPL3(cs);
 #endif /* CONFIG_X86_32 */
 
-	err |= __get_user(tmpflags, &sc->flags);
-	regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
-	regs->orig_ax = -1;		/* disable syscall checks */
+		get_user_ex(tmpflags, &sc->flags);
+		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+		regs->orig_ax = -1;		/* disable syscall checks */
+
+		get_user_ex(buf, &sc->fpstate);
+		err |= restore_i387_xstate(buf);
 
-	err |= __get_user(buf, &sc->fpstate);
-	err |= restore_i387_xstate(buf);
+		get_user_ex(*pax, &sc->ax);
+	} get_user_catch(err);
 
-	err |= __get_user(*pax, &sc->ax);
 	return err;
 }
 
@@ -131,57 +135,60 @@ setup_sigcontext(struct sigcontext __user *sc, void __user *fpstate,
 {
 	int err = 0;
 
+	put_user_try {
+
 #ifdef CONFIG_X86_32
-	{
-		unsigned int tmp;
+		{
+			unsigned int tmp;
 
-		savesegment(gs, tmp);
-		err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
-	}
-	err |= __put_user(regs->fs, (unsigned int __user *)&sc->fs);
-	err |= __put_user(regs->es, (unsigned int __user *)&sc->es);
-	err |= __put_user(regs->ds, (unsigned int __user *)&sc->ds);
+			savesegment(gs, tmp);
+			put_user_ex(tmp, (unsigned int __user *)&sc->gs);
+		}
+		put_user_ex(regs->fs, (unsigned int __user *)&sc->fs);
+		put_user_ex(regs->es, (unsigned int __user *)&sc->es);
+		put_user_ex(regs->ds, (unsigned int __user *)&sc->ds);
 #endif /* CONFIG_X86_32 */
 
-	err |= __put_user(regs->di, &sc->di);
-	err |= __put_user(regs->si, &sc->si);
-	err |= __put_user(regs->bp, &sc->bp);
-	err |= __put_user(regs->sp, &sc->sp);
-	err |= __put_user(regs->bx, &sc->bx);
-	err |= __put_user(regs->dx, &sc->dx);
-	err |= __put_user(regs->cx, &sc->cx);
-	err |= __put_user(regs->ax, &sc->ax);
+		put_user_ex(regs->di, &sc->di);
+		put_user_ex(regs->si, &sc->si);
+		put_user_ex(regs->bp, &sc->bp);
+		put_user_ex(regs->sp, &sc->sp);
+		put_user_ex(regs->bx, &sc->bx);
+		put_user_ex(regs->dx, &sc->dx);
+		put_user_ex(regs->cx, &sc->cx);
+		put_user_ex(regs->ax, &sc->ax);
 #ifdef CONFIG_X86_64
-	err |= __put_user(regs->r8, &sc->r8);
-	err |= __put_user(regs->r9, &sc->r9);
-	err |= __put_user(regs->r10, &sc->r10);
-	err |= __put_user(regs->r11, &sc->r11);
-	err |= __put_user(regs->r12, &sc->r12);
-	err |= __put_user(regs->r13, &sc->r13);
-	err |= __put_user(regs->r14, &sc->r14);
-	err |= __put_user(regs->r15, &sc->r15);
+		put_user_ex(regs->r8, &sc->r8);
+		put_user_ex(regs->r9, &sc->r9);
+		put_user_ex(regs->r10, &sc->r10);
+		put_user_ex(regs->r11, &sc->r11);
+		put_user_ex(regs->r12, &sc->r12);
+		put_user_ex(regs->r13, &sc->r13);
+		put_user_ex(regs->r14, &sc->r14);
+		put_user_ex(regs->r15, &sc->r15);
 #endif /* CONFIG_X86_64 */
 
-	err |= __put_user(current->thread.trap_no, &sc->trapno);
-	err |= __put_user(current->thread.error_code, &sc->err);
-	err |= __put_user(regs->ip, &sc->ip);
+		put_user_ex(current->thread.trap_no, &sc->trapno);
+		put_user_ex(current->thread.error_code, &sc->err);
+		put_user_ex(regs->ip, &sc->ip);
 #ifdef CONFIG_X86_32
-	err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
-	err |= __put_user(regs->flags, &sc->flags);
-	err |= __put_user(regs->sp, &sc->sp_at_signal);
-	err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
+		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
+		put_user_ex(regs->flags, &sc->flags);
+		put_user_ex(regs->sp, &sc->sp_at_signal);
+		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
 #else /* !CONFIG_X86_32 */
-	err |= __put_user(regs->flags, &sc->flags);
-	err |= __put_user(regs->cs, &sc->cs);
-	err |= __put_user(0, &sc->gs);
-	err |= __put_user(0, &sc->fs);
+		put_user_ex(regs->flags, &sc->flags);
+		put_user_ex(regs->cs, &sc->cs);
+		put_user_ex(0, &sc->gs);
+		put_user_ex(0, &sc->fs);
 #endif /* CONFIG_X86_32 */
 
-	err |= __put_user(fpstate, &sc->fpstate);
+		put_user_ex(fpstate, &sc->fpstate);
 
-	/* non-iBCS2 extensions.. */
-	err |= __put_user(mask, &sc->oldmask);
-	err |= __put_user(current->thread.cr2, &sc->cr2);
+		/* non-iBCS2 extensions.. */
+		put_user_ex(mask, &sc->oldmask);
+		put_user_ex(current->thread.cr2, &sc->cr2);
+	} put_user_catch(err);
 
 	return err;
 }
@@ -336,43 +343,41 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	err |= __put_user(sig, &frame->sig);
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
-	if (err)
-		return -EFAULT;
-
-	/* Create the ucontext.  */
-	if (cpu_has_xsave)
-		err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
-	else
-		err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(regs->sp),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
-				regs, set->sig[0]);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-	if (err)
-		return -EFAULT;
+	put_user_try {
+		put_user_ex(sig, &frame->sig);
+		put_user_ex(&frame->info, &frame->pinfo);
+		put_user_ex(&frame->uc, &frame->puc);
+		err |= copy_siginfo_to_user(&frame->info, info);
 
-	/* Set up to return from userspace.  */
-	restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-	err |= __put_user(restorer, &frame->pretcode);
+		/* Create the ucontext.  */
+		if (cpu_has_xsave)
+			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+		else
+			put_user_ex(0, &frame->uc.uc_flags);
+		put_user_ex(0, &frame->uc.uc_link);
+		put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+		put_user_ex(sas_ss_flags(regs->sp),
+			    &frame->uc.uc_stack.ss_flags);
+		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+		err |= setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+					regs, set->sig[0]);
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+		/* Set up to return from userspace.  */
+		restorer = VDSO32_SYMBOL(current->mm->context.vdso, rt_sigreturn);
+		if (ka->sa.sa_flags & SA_RESTORER)
+			restorer = ka->sa.sa_restorer;
+		put_user_ex(restorer, &frame->pretcode);
 
-	/*
-	 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
-	 *
-	 * WE DO NOT USE IT ANY MORE! It's only left here for historical
-	 * reasons and because gdb uses it as a signature to notice
-	 * signal handler stack frames.
-	 */
-	err |= __put_user(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
+		/*
+		 * This is movl $__NR_rt_sigreturn, %ax ; int $0x80
+		 *
+		 * WE DO NOT USE IT ANY MORE! It's only left here for historical
+		 * reasons and because gdb uses it as a signature to notice
+		 * signal handler stack frames.
+		 */
+		put_user_ex(*((u64 *)&rt_retcode), (u64 *)frame->retcode);
+	} put_user_catch(err);
 
 	if (err)
 		return -EFAULT;
@@ -436,28 +441,30 @@ static int __setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 			return -EFAULT;
 	}
 
-	/* Create the ucontext.  */
-	if (cpu_has_xsave)
-		err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
-	else
-		err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(regs->sp),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-
-	/* Set up to return from userspace.  If provided, use a stub
-	   already in userspace.  */
-	/* x86-64 should always use SA_RESTORER. */
-	if (ka->sa.sa_flags & SA_RESTORER) {
-		err |= __put_user(ka->sa.sa_restorer, &frame->pretcode);
-	} else {
-		/* could use a vstub here */
-		return -EFAULT;
-	}
+	put_user_try {
+		/* Create the ucontext.  */
+		if (cpu_has_xsave)
+			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+		else
+			put_user_ex(0, &frame->uc.uc_flags);
+		put_user_ex(0, &frame->uc.uc_link);
+		put_user_ex(me->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+		put_user_ex(sas_ss_flags(regs->sp),
+			    &frame->uc.uc_stack.ss_flags);
+		put_user_ex(me->sas_ss_size, &frame->uc.uc_stack.ss_size);
+		err |= setup_sigcontext(&frame->uc.uc_mcontext, fp, regs, set->sig[0]);
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+		/* Set up to return from userspace.  If provided, use a stub
+		   already in userspace.  */
+		/* x86-64 should always use SA_RESTORER. */
+		if (ka->sa.sa_flags & SA_RESTORER) {
+			put_user_ex(ka->sa.sa_restorer, &frame->pretcode);
+		} else {
+			/* could use a vstub here */
+			err |= -EFAULT;
+		}
+	} put_user_catch(err);
 
 	if (err)
 		return -EFAULT;
@@ -509,31 +516,41 @@ sys_sigaction(int sig, const struct old_sigaction __user *act,
 	      struct old_sigaction __user *oact)
 {
 	struct k_sigaction new_ka, old_ka;
-	int ret;
+	int ret = 0;
 
 	if (act) {
 		old_sigset_t mask;
 
-		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||
-		    __get_user(new_ka.sa.sa_handler, &act->sa_handler) ||
-		    __get_user(new_ka.sa.sa_restorer, &act->sa_restorer))
+		if (!access_ok(VERIFY_READ, act, sizeof(*act)))
 			return -EFAULT;
 
-		__get_user(new_ka.sa.sa_flags, &act->sa_flags);
-		__get_user(mask, &act->sa_mask);
+		get_user_try {
+			get_user_ex(new_ka.sa.sa_handler, &act->sa_handler);
+			get_user_ex(new_ka.sa.sa_flags, &act->sa_flags);
+			get_user_ex(mask, &act->sa_mask);
+			get_user_ex(new_ka.sa.sa_restorer, &act->sa_restorer);
+		} get_user_catch(ret);
+
+		if (ret)
+			return -EFAULT;
 		siginitset(&new_ka.sa.sa_mask, mask);
 	}
 
 	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);
 
 	if (!ret && oact) {
-		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||
-		    __put_user(old_ka.sa.sa_handler, &oact->sa_handler) ||
-		    __put_user(old_ka.sa.sa_restorer, &oact->sa_restorer))
+		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)))
 			return -EFAULT;
 
-		__put_user(old_ka.sa.sa_flags, &oact->sa_flags);
-		__put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+		put_user_try {
+			put_user_ex(old_ka.sa.sa_handler, &oact->sa_handler);
+			put_user_ex(old_ka.sa.sa_flags, &oact->sa_flags);
+			put_user_ex(old_ka.sa.sa_mask.sig[0], &oact->sa_mask);
+			put_user_ex(old_ka.sa.sa_restorer, &oact->sa_restorer);
+		} put_user_catch(ret);
+
+		if (ret)
+			return -EFAULT;
 	}
 
 	return ret;
-- 
1.6.0.4


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

* [RFC v2 -tip 3/3] x86: ia32_signal: use {get|put}_user_try and catch
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
  2009-01-23 23:49     ` [RFC v2 -tip 1/3] x86: uaccess: introduce try and catch framework Hiroshi Shimamoto
  2009-01-23 23:50     ` [RFC v2 -tip 2/3] x86: signal: use {get|put}_user_try and catch Hiroshi Shimamoto
@ 2009-01-23 23:50     ` Hiroshi Shimamoto
  2009-01-24  7:36       ` Cyrill Gorcunov
  2009-01-24  0:51     ` [RFC v2 -tip 0/3] x86: reduce fixup of uaccess H. Peter Anvin
  2009-01-24  4:39     ` H. Peter Anvin
  4 siblings, 1 reply; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-23 23:50 UTC (permalink / raw)
  To: H. Peter Anvin, Ingo Molnar, Thomas Gleixner; +Cc: linux-kernel

From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>

Impact: use new framework

Use {get|put}_user_try, catch, and _ex in arch/x86/ia32/ia32_signal.c.

Note: this patch contains "WARNING: line over 80 characters", because when
introducing new block I insert an indent to avoid mistakes by edit.

Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
---
 arch/x86/ia32/ia32_signal.c |  365 +++++++++++++++++++++++--------------------
 1 files changed, 195 insertions(+), 170 deletions(-)

diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
index 9dabd00..dd77ac0 100644
--- a/arch/x86/ia32/ia32_signal.c
+++ b/arch/x86/ia32/ia32_signal.c
@@ -46,78 +46,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
 
 int copy_siginfo_to_user32(compat_siginfo_t __user *to, siginfo_t *from)
 {
-	int err;
+	int err = 0;
 
 	if (!access_ok(VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
-	/* If you change siginfo_t structure, please make sure that
-	   this code is fixed accordingly.
-	   It should never copy any pad contained in the structure
-	   to avoid security leaks, but must copy the generic
-	   3 ints plus the relevant union member.  */
-	err = __put_user(from->si_signo, &to->si_signo);
-	err |= __put_user(from->si_errno, &to->si_errno);
-	err |= __put_user((short)from->si_code, &to->si_code);
-
-	if (from->si_code < 0) {
-		err |= __put_user(from->si_pid, &to->si_pid);
-		err |= __put_user(from->si_uid, &to->si_uid);
-		err |= __put_user(ptr_to_compat(from->si_ptr), &to->si_ptr);
-	} else {
-		/*
-		 * First 32bits of unions are always present:
-		 * si_pid === si_band === si_tid === si_addr(LS half)
-		 */
-		err |= __put_user(from->_sifields._pad[0],
-				  &to->_sifields._pad[0]);
-		switch (from->si_code >> 16) {
-		case __SI_FAULT >> 16:
-			break;
-		case __SI_CHLD >> 16:
-			err |= __put_user(from->si_utime, &to->si_utime);
-			err |= __put_user(from->si_stime, &to->si_stime);
-			err |= __put_user(from->si_status, &to->si_status);
-			/* FALL THROUGH */
-		default:
-		case __SI_KILL >> 16:
-			err |= __put_user(from->si_uid, &to->si_uid);
-			break;
-		case __SI_POLL >> 16:
-			err |= __put_user(from->si_fd, &to->si_fd);
-			break;
-		case __SI_TIMER >> 16:
-			err |= __put_user(from->si_overrun, &to->si_overrun);
-			err |= __put_user(ptr_to_compat(from->si_ptr),
-					  &to->si_ptr);
-			break;
-			 /* This is not generated by the kernel as of now.  */
-		case __SI_RT >> 16:
-		case __SI_MESGQ >> 16:
-			err |= __put_user(from->si_uid, &to->si_uid);
-			err |= __put_user(from->si_int, &to->si_int);
-			break;
+	put_user_try {
+		/* If you change siginfo_t structure, please make sure that
+		   this code is fixed accordingly.
+		   It should never copy any pad contained in the structure
+		   to avoid security leaks, but must copy the generic
+		   3 ints plus the relevant union member.  */
+		put_user_ex(from->si_signo, &to->si_signo);
+		put_user_ex(from->si_errno, &to->si_errno);
+		put_user_ex((short)from->si_code, &to->si_code);
+
+		if (from->si_code < 0) {
+			put_user_ex(from->si_pid, &to->si_pid);
+			put_user_ex(from->si_uid, &to->si_uid);
+			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
+		} else {
+			/*
+			 * First 32bits of unions are always present:
+			 * si_pid === si_band === si_tid === si_addr(LS half)
+			 */
+			put_user_ex(from->_sifields._pad[0],
+					  &to->_sifields._pad[0]);
+			switch (from->si_code >> 16) {
+			case __SI_FAULT >> 16:
+				break;
+			case __SI_CHLD >> 16:
+				put_user_ex(from->si_utime, &to->si_utime);
+				put_user_ex(from->si_stime, &to->si_stime);
+				put_user_ex(from->si_status, &to->si_status);
+				/* FALL THROUGH */
+			default:
+			case __SI_KILL >> 16:
+				put_user_ex(from->si_uid, &to->si_uid);
+				break;
+			case __SI_POLL >> 16:
+				put_user_ex(from->si_fd, &to->si_fd);
+				break;
+			case __SI_TIMER >> 16:
+				put_user_ex(from->si_overrun, &to->si_overrun);
+				put_user_ex(ptr_to_compat(from->si_ptr),
+					    &to->si_ptr);
+				break;
+				 /* This is not generated by the kernel as of now.  */
+			case __SI_RT >> 16:
+			case __SI_MESGQ >> 16:
+				put_user_ex(from->si_uid, &to->si_uid);
+				put_user_ex(from->si_int, &to->si_int);
+				break;
+			}
 		}
-	}
+	} put_user_catch(err);
+
 	return err;
 }
 
 int copy_siginfo_from_user32(siginfo_t *to, compat_siginfo_t __user *from)
 {
-	int err;
+	int err = 0;
 	u32 ptr32;
 
 	if (!access_ok(VERIFY_READ, from, sizeof(compat_siginfo_t)))
 		return -EFAULT;
 
-	err = __get_user(to->si_signo, &from->si_signo);
-	err |= __get_user(to->si_errno, &from->si_errno);
-	err |= __get_user(to->si_code, &from->si_code);
+	get_user_try {
+		get_user_ex(to->si_signo, &from->si_signo);
+		get_user_ex(to->si_errno, &from->si_errno);
+		get_user_ex(to->si_code, &from->si_code);
 
-	err |= __get_user(to->si_pid, &from->si_pid);
-	err |= __get_user(to->si_uid, &from->si_uid);
-	err |= __get_user(ptr32, &from->si_ptr);
-	to->si_ptr = compat_ptr(ptr32);
+		get_user_ex(to->si_pid, &from->si_pid);
+		get_user_ex(to->si_uid, &from->si_uid);
+		get_user_ex(ptr32, &from->si_ptr);
+		to->si_ptr = compat_ptr(ptr32);
+	} get_user_catch(err);
 
 	return err;
 }
@@ -142,17 +147,23 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 				  struct pt_regs *regs)
 {
 	stack_t uss, uoss;
-	int ret;
+	int ret, err = 0;
 	mm_segment_t seg;
 
 	if (uss_ptr) {
 		u32 ptr;
 
 		memset(&uss, 0, sizeof(stack_t));
-		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)) ||
-			    __get_user(ptr, &uss_ptr->ss_sp) ||
-			    __get_user(uss.ss_flags, &uss_ptr->ss_flags) ||
-			    __get_user(uss.ss_size, &uss_ptr->ss_size))
+		if (!access_ok(VERIFY_READ, uss_ptr, sizeof(stack_ia32_t)))
+			return -EFAULT;
+
+		get_user_try {
+			get_user_ex(ptr, &uss_ptr->ss_sp);
+			get_user_ex(uss.ss_flags, &uss_ptr->ss_flags);
+			get_user_ex(uss.ss_size, &uss_ptr->ss_size);
+		} get_user_catch(err);
+
+		if (err)
 			return -EFAULT;
 		uss.ss_sp = compat_ptr(ptr);
 	}
@@ -161,10 +172,16 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
 	ret = do_sigaltstack(uss_ptr ? &uss : NULL, &uoss, regs->sp);
 	set_fs(seg);
 	if (ret >= 0 && uoss_ptr)  {
-		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)) ||
-		    __put_user(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp) ||
-		    __put_user(uoss.ss_flags, &uoss_ptr->ss_flags) ||
-		    __put_user(uoss.ss_size, &uoss_ptr->ss_size))
+		if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(stack_ia32_t)))
+			return -EFAULT;
+
+		put_user_try {
+			put_user_ex(ptr_to_compat(uoss.ss_sp), &uoss_ptr->ss_sp);
+			put_user_ex(uoss.ss_flags, &uoss_ptr->ss_flags);
+			put_user_ex(uoss.ss_size, &uoss_ptr->ss_size);
+		} put_user_catch(err);
+
+		if (err)
 			ret = -EFAULT;
 	}
 	return ret;
@@ -174,18 +191,18 @@ asmlinkage long sys32_sigaltstack(const stack_ia32_t __user *uss_ptr,
  * Do a signal return; undo the signal stack.
  */
 #define COPY(x)			{		\
-	err |= __get_user(regs->x, &sc->x);	\
+	get_user_ex(regs->x, &sc->x);		\
 }
 
 #define COPY_SEG_CPL3(seg)	{			\
 		unsigned short tmp;			\
-		err |= __get_user(tmp, &sc->seg);	\
+		get_user_ex(tmp, &sc->seg);		\
 		regs->seg = tmp | 3;			\
 }
 
 #define RELOAD_SEG(seg)		{		\
 	unsigned int cur, pre;			\
-	err |= __get_user(pre, &sc->seg);	\
+	get_user_ex(pre, &sc->seg);		\
 	savesegment(seg, cur);			\
 	pre |= 3;				\
 	if (pre != cur)				\
@@ -209,39 +226,42 @@ static int ia32_restore_sigcontext(struct pt_regs *regs,
 	       sc, sc->err, sc->ip, sc->cs, sc->flags);
 #endif
 
-	/*
-	 * Reload fs and gs if they have changed in the signal
-	 * handler.  This does not handle long fs/gs base changes in
-	 * the handler, but does not clobber them at least in the
-	 * normal case.
-	 */
-	err |= __get_user(gs, &sc->gs);
-	gs |= 3;
-	savesegment(gs, oldgs);
-	if (gs != oldgs)
-		load_gs_index(gs);
-
-	RELOAD_SEG(fs);
-	RELOAD_SEG(ds);
-	RELOAD_SEG(es);
-
-	COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
-	COPY(dx); COPY(cx); COPY(ip);
-	/* Don't touch extended registers */
-
-	COPY_SEG_CPL3(cs);
-	COPY_SEG_CPL3(ss);
-
-	err |= __get_user(tmpflags, &sc->flags);
-	regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
-	/* disable syscall checks */
-	regs->orig_ax = -1;
-
-	err |= __get_user(tmp, &sc->fpstate);
-	buf = compat_ptr(tmp);
-	err |= restore_i387_xstate_ia32(buf);
-
-	err |= __get_user(*pax, &sc->ax);
+	get_user_try {
+		/*
+		 * Reload fs and gs if they have changed in the signal
+		 * handler.  This does not handle long fs/gs base changes in
+		 * the handler, but does not clobber them at least in the
+		 * normal case.
+		 */
+		get_user_ex(gs, &sc->gs);
+		gs |= 3;
+		savesegment(gs, oldgs);
+		if (gs != oldgs)
+			load_gs_index(gs);
+
+		RELOAD_SEG(fs);
+		RELOAD_SEG(ds);
+		RELOAD_SEG(es);
+
+		COPY(di); COPY(si); COPY(bp); COPY(sp); COPY(bx);
+		COPY(dx); COPY(cx); COPY(ip);
+		/* Don't touch extended registers */
+
+		COPY_SEG_CPL3(cs);
+		COPY_SEG_CPL3(ss);
+
+		get_user_ex(tmpflags, &sc->flags);
+		regs->flags = (regs->flags & ~FIX_EFLAGS) | (tmpflags & FIX_EFLAGS);
+		/* disable syscall checks */
+		regs->orig_ax = -1;
+
+		get_user_ex(tmp, &sc->fpstate);
+		buf = compat_ptr(tmp);
+		err |= restore_i387_xstate_ia32(buf);
+
+		get_user_ex(*pax, &sc->ax);
+	} get_user_catch(err);
+
 	return err;
 }
 
@@ -319,36 +339,38 @@ static int ia32_setup_sigcontext(struct sigcontext_ia32 __user *sc,
 {
 	int tmp, err = 0;
 
-	savesegment(gs, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->gs);
-	savesegment(fs, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->fs);
-	savesegment(ds, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->ds);
-	savesegment(es, tmp);
-	err |= __put_user(tmp, (unsigned int __user *)&sc->es);
-
-	err |= __put_user(regs->di, &sc->di);
-	err |= __put_user(regs->si, &sc->si);
-	err |= __put_user(regs->bp, &sc->bp);
-	err |= __put_user(regs->sp, &sc->sp);
-	err |= __put_user(regs->bx, &sc->bx);
-	err |= __put_user(regs->dx, &sc->dx);
-	err |= __put_user(regs->cx, &sc->cx);
-	err |= __put_user(regs->ax, &sc->ax);
-	err |= __put_user(current->thread.trap_no, &sc->trapno);
-	err |= __put_user(current->thread.error_code, &sc->err);
-	err |= __put_user(regs->ip, &sc->ip);
-	err |= __put_user(regs->cs, (unsigned int __user *)&sc->cs);
-	err |= __put_user(regs->flags, &sc->flags);
-	err |= __put_user(regs->sp, &sc->sp_at_signal);
-	err |= __put_user(regs->ss, (unsigned int __user *)&sc->ss);
-
-	err |= __put_user(ptr_to_compat(fpstate), &sc->fpstate);
-
-	/* non-iBCS2 extensions.. */
-	err |= __put_user(mask, &sc->oldmask);
-	err |= __put_user(current->thread.cr2, &sc->cr2);
+	put_user_try {
+		savesegment(gs, tmp);
+		put_user_ex(tmp, (unsigned int __user *)&sc->gs);
+		savesegment(fs, tmp);
+		put_user_ex(tmp, (unsigned int __user *)&sc->fs);
+		savesegment(ds, tmp);
+		put_user_ex(tmp, (unsigned int __user *)&sc->ds);
+		savesegment(es, tmp);
+		put_user_ex(tmp, (unsigned int __user *)&sc->es);
+
+		put_user_ex(regs->di, &sc->di);
+		put_user_ex(regs->si, &sc->si);
+		put_user_ex(regs->bp, &sc->bp);
+		put_user_ex(regs->sp, &sc->sp);
+		put_user_ex(regs->bx, &sc->bx);
+		put_user_ex(regs->dx, &sc->dx);
+		put_user_ex(regs->cx, &sc->cx);
+		put_user_ex(regs->ax, &sc->ax);
+		put_user_ex(current->thread.trap_no, &sc->trapno);
+		put_user_ex(current->thread.error_code, &sc->err);
+		put_user_ex(regs->ip, &sc->ip);
+		put_user_ex(regs->cs, (unsigned int __user *)&sc->cs);
+		put_user_ex(regs->flags, &sc->flags);
+		put_user_ex(regs->sp, &sc->sp_at_signal);
+		put_user_ex(regs->ss, (unsigned int __user *)&sc->ss);
+
+		put_user_ex(ptr_to_compat(fpstate), &sc->fpstate);
+
+		/* non-iBCS2 extensions.. */
+		put_user_ex(mask, &sc->oldmask);
+		put_user_ex(current->thread.cr2, &sc->cr2);
+	} put_user_catch(err);
 
 	return err;
 }
@@ -437,13 +459,17 @@ int ia32_setup_frame(int sig, struct k_sigaction *ka,
 		else
 			restorer = &frame->retcode;
 	}
-	err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
 
-	/*
-	 * These are actually not used anymore, but left because some
-	 * gdb versions depend on them as a marker.
-	 */
-	err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
+	put_user_try {
+		put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
+
+		/*
+		 * These are actually not used anymore, but left because some
+		 * gdb versions depend on them as a marker.
+		 */
+		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
+	} put_user_catch(err);
+
 	if (err)
 		return -EFAULT;
 
@@ -496,41 +522,40 @@ int ia32_setup_rt_frame(int sig, struct k_sigaction *ka, siginfo_t *info,
 	if (!access_ok(VERIFY_WRITE, frame, sizeof(*frame)))
 		return -EFAULT;
 
-	err |= __put_user(sig, &frame->sig);
-	err |= __put_user(ptr_to_compat(&frame->info), &frame->pinfo);
-	err |= __put_user(ptr_to_compat(&frame->uc), &frame->puc);
-	err |= copy_siginfo_to_user32(&frame->info, info);
-	if (err)
-		return -EFAULT;
+	put_user_try {
+		put_user_ex(sig, &frame->sig);
+		put_user_ex(ptr_to_compat(&frame->info), &frame->pinfo);
+		put_user_ex(ptr_to_compat(&frame->uc), &frame->puc);
+		err |= copy_siginfo_to_user32(&frame->info, info);
 
-	/* Create the ucontext.  */
-	if (cpu_has_xsave)
-		err |= __put_user(UC_FP_XSTATE, &frame->uc.uc_flags);
-	else
-		err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(regs->sp),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
-				     regs, set->sig[0]);
-	err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
-	if (err)
-		return -EFAULT;
+		/* Create the ucontext.  */
+		if (cpu_has_xsave)
+			put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
+		else
+			put_user_ex(0, &frame->uc.uc_flags);
+		put_user_ex(0, &frame->uc.uc_link);
+		put_user_ex(current->sas_ss_sp, &frame->uc.uc_stack.ss_sp);
+		put_user_ex(sas_ss_flags(regs->sp),
+			    &frame->uc.uc_stack.ss_flags);
+		put_user_ex(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+		err |= ia32_setup_sigcontext(&frame->uc.uc_mcontext, fpstate,
+					     regs, set->sig[0]);
+		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
+
+		if (ka->sa.sa_flags & SA_RESTORER)
+			restorer = ka->sa.sa_restorer;
+		else
+			restorer = VDSO32_SYMBOL(current->mm->context.vdso,
+						 rt_sigreturn);
+		put_user_ex(ptr_to_compat(restorer), &frame->pretcode);
+
+		/*
+		 * Not actually used anymore, but left because some gdb
+		 * versions need it.
+		 */
+		put_user_ex(*((u64 *)&code), (u64 *)frame->retcode);
+	} put_user_catch(err);
 
-	if (ka->sa.sa_flags & SA_RESTORER)
-		restorer = ka->sa.sa_restorer;
-	else
-		restorer = VDSO32_SYMBOL(current->mm->context.vdso,
-					 rt_sigreturn);
-	err |= __put_user(ptr_to_compat(restorer), &frame->pretcode);
-
-	/*
-	 * Not actually used anymore, but left because some gdb
-	 * versions need it.
-	 */
-	err |= __put_user(*((u64 *)&code), (u64 *)frame->retcode);
 	if (err)
 		return -EFAULT;
 
-- 
1.6.0.4


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

* Re: [RFC v2 -tip 0/3] x86: reduce fixup of uaccess
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
                       ` (2 preceding siblings ...)
  2009-01-23 23:50     ` [RFC v2 -tip 3/3] x86: ia32_signal: " Hiroshi Shimamoto
@ 2009-01-24  0:51     ` H. Peter Anvin
  2009-01-24  4:39     ` H. Peter Anvin
  4 siblings, 0 replies; 17+ messages in thread
From: H. Peter Anvin @ 2009-01-24  0:51 UTC (permalink / raw)
  To: Hiroshi Shimamoto; +Cc: Ingo Molnar, Thomas Gleixner, linux-kernel

Hiroshi Shimamoto wrote:
> ChangeLog v1 -> v2
> 	- Change framework syntax. Previous version doesn't look easy to read.
> 	  Remove parens from try and add redundant braces as Peter suggested.
> 		get_user_try {
> 			get_user_ex(...);
> 			:
> 		} get_user_catch(err);
> 	- Remove double underscores.

Cool, looks a lot nicer this way.

I will try to try it out today.

	-hpa


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

* Re: [RFC v2 -tip 0/3] x86: reduce fixup of uaccess
  2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
                       ` (3 preceding siblings ...)
  2009-01-24  0:51     ` [RFC v2 -tip 0/3] x86: reduce fixup of uaccess H. Peter Anvin
@ 2009-01-24  4:39     ` H. Peter Anvin
  4 siblings, 0 replies; 17+ messages in thread
From: H. Peter Anvin @ 2009-01-24  4:39 UTC (permalink / raw)
  To: Hiroshi Shimamoto; +Cc: Ingo Molnar, Thomas Gleixner, linux-kernel

Hiroshi Shimamoto wrote:
> This patch series redues fixup code for exceptions of uaccess in signal.
> 
> There is a lot of fixup code which is generated by using __{get|put}_user.
> I think that code can be reduced. The concept is that to add uaccess_err in
> thread_info and set it to -EFAULT on exception, finally check this value on
> the last of function.
> 
> The code size reductions are below;
> $ size *signal*.o.*
>    text	   data	    bss	    dec	    hex	filename
>    4596	      0	      0	   4596	   11f4	ia32_signal.o.new
>    6006	      0	      0	   6006	   1776	ia32_signal.o.old
>    3583	      0	      0	   3583	    dff	signal.o.new
>    4540	      0	      0	   4540	   11bc	signal.o.old
>    3863	      0	      0	   3863	    f17	signal32.o.new
>    4876	      0	      0	   4876	   130c	signal32.o.old
> [ signal32.o means signal.o on 32-bit. ]
> 

Applied to tip:x86/uaccess.  I haven't tested it much yet, but at least
a visual lookover looks good.

Thanks!

	-hpa

-- 
H. Peter Anvin, Intel Open Source Technology Center
I work for Intel.  I don't speak on their behalf.


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

* Re: [RFC v2 -tip 3/3] x86: ia32_signal: use {get|put}_user_try and catch
  2009-01-23 23:50     ` [RFC v2 -tip 3/3] x86: ia32_signal: " Hiroshi Shimamoto
@ 2009-01-24  7:36       ` Cyrill Gorcunov
  2009-01-26 18:31         ` Hiroshi Shimamoto
  0 siblings, 1 reply; 17+ messages in thread
From: Cyrill Gorcunov @ 2009-01-24  7:36 UTC (permalink / raw)
  To: Hiroshi Shimamoto
  Cc: H. Peter Anvin, Ingo Molnar, Thomas Gleixner, linux-kernel

[Hiroshi Shimamoto - Fri, Jan 23, 2009 at 03:50:38PM -0800]
| From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
| 
| Impact: use new framework
| 
| Use {get|put}_user_try, catch, and _ex in arch/x86/ia32/ia32_signal.c.
| 
| Note: this patch contains "WARNING: line over 80 characters", because when
| introducing new block I insert an indent to avoid mistakes by edit.
| 
| Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
| ---
|  arch/x86/ia32/ia32_signal.c |  365 +++++++++++++++++++++++--------------------
|  1 files changed, 195 insertions(+), 170 deletions(-)
| 
| diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
| index 9dabd00..dd77ac0 100644
| --- a/arch/x86/ia32/ia32_signal.c
| +++ b/arch/x86/ia32/ia32_signal.c
| @@ -46,78 +46,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
|
... 
| +	put_user_try {
| +		/* If you change siginfo_t structure, please make sure that
| +		   this code is fixed accordingly.
| +		   It should never copy any pad contained in the structure
| +		   to avoid security leaks, but must copy the generic
| +		   3 ints plus the relevant union member.  */
| +		put_user_ex(from->si_signo, &to->si_signo);
| +		put_user_ex(from->si_errno, &to->si_errno);
| +		put_user_ex((short)from->si_code, &to->si_code);
| +
| +		if (from->si_code < 0) {
| +			put_user_ex(from->si_pid, &to->si_pid);
| +			put_user_ex(from->si_uid, &to->si_uid);
| +			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
| +		} else {
| +			/*
| +			 * First 32bits of unions are always present:
| +			 * si_pid === si_band === si_tid === si_addr(LS half)
| +			 */
| +			put_user_ex(from->_sifields._pad[0],
| +					  &to->_sifields._pad[0]);
| +			switch (from->si_code >> 16) {
| +			case __SI_FAULT >> 16:
| +				break;
| +			case __SI_CHLD >> 16:
| +				put_user_ex(from->si_utime, &to->si_utime);
| +				put_user_ex(from->si_stime, &to->si_stime);
| +				put_user_ex(from->si_status, &to->si_status);
| +				/* FALL THROUGH */
| +			default:

Hi Hiroshi,

may I ask why we use default here?

| +			case __SI_KILL >> 16:
| +				put_user_ex(from->si_uid, &to->si_uid);
| +				break;
| +			case __SI_POLL >> 16:
| +				put_user_ex(from->si_fd, &to->si_fd);
| +				break;
| +			case __SI_TIMER >> 16:
| +				put_user_ex(from->si_overrun, &to->si_overrun);
| +				put_user_ex(ptr_to_compat(from->si_ptr),
| +					    &to->si_ptr);
| +				break;
| +				 /* This is not generated by the kernel as of now.  */
| +			case __SI_RT >> 16:
| +			case __SI_MESGQ >> 16:
| +				put_user_ex(from->si_uid, &to->si_uid);
| +				put_user_ex(from->si_int, &to->si_int);
| +				break;
| +			}
|  		}
| -	}
| +	} put_user_catch(err);
| +
|  	return err;
|  }
|  
...
 
		- Cyrill -

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

* Re: [RFC v2 -tip 3/3] x86: ia32_signal: use {get|put}_user_try and catch
  2009-01-24  7:36       ` Cyrill Gorcunov
@ 2009-01-26 18:31         ` Hiroshi Shimamoto
  2009-01-26 18:56           ` Cyrill Gorcunov
  0 siblings, 1 reply; 17+ messages in thread
From: Hiroshi Shimamoto @ 2009-01-26 18:31 UTC (permalink / raw)
  To: Cyrill Gorcunov
  Cc: H. Peter Anvin, Ingo Molnar, Thomas Gleixner, linux-kernel

Cyrill Gorcunov wrote:
> [Hiroshi Shimamoto - Fri, Jan 23, 2009 at 03:50:38PM -0800]
> | From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
> | 
> | Impact: use new framework
> | 
> | Use {get|put}_user_try, catch, and _ex in arch/x86/ia32/ia32_signal.c.
> | 
> | Note: this patch contains "WARNING: line over 80 characters", because when
> | introducing new block I insert an indent to avoid mistakes by edit.
> | 
> | Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
> | ---
> |  arch/x86/ia32/ia32_signal.c |  365 +++++++++++++++++++++++--------------------
> |  1 files changed, 195 insertions(+), 170 deletions(-)
> | 
> | diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
> | index 9dabd00..dd77ac0 100644
> | --- a/arch/x86/ia32/ia32_signal.c
> | +++ b/arch/x86/ia32/ia32_signal.c
> | @@ -46,78 +46,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
> |
> ... 
> | +	put_user_try {
> | +		/* If you change siginfo_t structure, please make sure that
> | +		   this code is fixed accordingly.
> | +		   It should never copy any pad contained in the structure
> | +		   to avoid security leaks, but must copy the generic
> | +		   3 ints plus the relevant union member.  */
> | +		put_user_ex(from->si_signo, &to->si_signo);
> | +		put_user_ex(from->si_errno, &to->si_errno);
> | +		put_user_ex((short)from->si_code, &to->si_code);
> | +
> | +		if (from->si_code < 0) {
> | +			put_user_ex(from->si_pid, &to->si_pid);
> | +			put_user_ex(from->si_uid, &to->si_uid);
> | +			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
> | +		} else {
> | +			/*
> | +			 * First 32bits of unions are always present:
> | +			 * si_pid === si_band === si_tid === si_addr(LS half)
> | +			 */
> | +			put_user_ex(from->_sifields._pad[0],
> | +					  &to->_sifields._pad[0]);
> | +			switch (from->si_code >> 16) {
> | +			case __SI_FAULT >> 16:
> | +				break;
> | +			case __SI_CHLD >> 16:
> | +				put_user_ex(from->si_utime, &to->si_utime);
> | +				put_user_ex(from->si_stime, &to->si_stime);
> | +				put_user_ex(from->si_status, &to->si_status);
> | +				/* FALL THROUGH */
> | +			default:
> 
> Hi Hiroshi,

Hi Cyrill,

> 
> may I ask why we use default here?

I don't know:) Hm, it looks old code.
arch/i386/kernel/signal.c in 2.4 has similar code.

I guess this code didn't change when copy_siginfo_to_user() was moved
from arch/i386/kernel/signal.c to kernel/signal.c.

Should we change this like copy_siginfo_tu_user() in kernel/signal.c?
Copying si_pid was added in kernel/signal.c.

BTW, it seems same __ST_KILL and default.

Thanks,
Hiroshi

> 
> | +			case __SI_KILL >> 16:
> | +				put_user_ex(from->si_uid, &to->si_uid);
> | +				break;
> | +			case __SI_POLL >> 16:
> | +				put_user_ex(from->si_fd, &to->si_fd);
> | +				break;
> | +			case __SI_TIMER >> 16:
> | +				put_user_ex(from->si_overrun, &to->si_overrun);
> | +				put_user_ex(ptr_to_compat(from->si_ptr),
> | +					    &to->si_ptr);
> | +				break;
> | +				 /* This is not generated by the kernel as of now.  */
> | +			case __SI_RT >> 16:
> | +			case __SI_MESGQ >> 16:
> | +				put_user_ex(from->si_uid, &to->si_uid);
> | +				put_user_ex(from->si_int, &to->si_int);
> | +				break;
> | +			}
> |  		}
> | -	}
> | +	} put_user_catch(err);
> | +
> |  	return err;
> |  }
> |  
> ...
>  
> 		- Cyrill -
> --
> 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] 17+ messages in thread

* Re: [RFC v2 -tip 3/3] x86: ia32_signal: use {get|put}_user_try and catch
  2009-01-26 18:31         ` Hiroshi Shimamoto
@ 2009-01-26 18:56           ` Cyrill Gorcunov
  0 siblings, 0 replies; 17+ messages in thread
From: Cyrill Gorcunov @ 2009-01-26 18:56 UTC (permalink / raw)
  To: Hiroshi Shimamoto
  Cc: H. Peter Anvin, Ingo Molnar, Thomas Gleixner, linux-kernel

[Hiroshi Shimamoto - Mon, Jan 26, 2009 at 10:31:03AM -0800]
| Cyrill Gorcunov wrote:
| > [Hiroshi Shimamoto - Fri, Jan 23, 2009 at 03:50:38PM -0800]
| > | From: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
| > | 
| > | Impact: use new framework
| > | 
| > | Use {get|put}_user_try, catch, and _ex in arch/x86/ia32/ia32_signal.c.
| > | 
| > | Note: this patch contains "WARNING: line over 80 characters", because when
| > | introducing new block I insert an indent to avoid mistakes by edit.
| > | 
| > | Signed-off-by: Hiroshi Shimamoto <h-shimamoto@ct.jp.nec.com>
| > | ---
| > |  arch/x86/ia32/ia32_signal.c |  365 +++++++++++++++++++++++--------------------
| > |  1 files changed, 195 insertions(+), 170 deletions(-)
| > | 
| > | diff --git a/arch/x86/ia32/ia32_signal.c b/arch/x86/ia32/ia32_signal.c
| > | index 9dabd00..dd77ac0 100644
| > | --- a/arch/x86/ia32/ia32_signal.c
| > | +++ b/arch/x86/ia32/ia32_signal.c
| > | @@ -46,78 +46,83 @@ void signal_fault(struct pt_regs *regs, void __user *frame, char *where);
| > |
| > ... 
| > | +	put_user_try {
| > | +		/* If you change siginfo_t structure, please make sure that
| > | +		   this code is fixed accordingly.
| > | +		   It should never copy any pad contained in the structure
| > | +		   to avoid security leaks, but must copy the generic
| > | +		   3 ints plus the relevant union member.  */
| > | +		put_user_ex(from->si_signo, &to->si_signo);
| > | +		put_user_ex(from->si_errno, &to->si_errno);
| > | +		put_user_ex((short)from->si_code, &to->si_code);
| > | +
| > | +		if (from->si_code < 0) {
| > | +			put_user_ex(from->si_pid, &to->si_pid);
| > | +			put_user_ex(from->si_uid, &to->si_uid);
| > | +			put_user_ex(ptr_to_compat(from->si_ptr), &to->si_ptr);
| > | +		} else {
| > | +			/*
| > | +			 * First 32bits of unions are always present:
| > | +			 * si_pid === si_band === si_tid === si_addr(LS half)
| > | +			 */
| > | +			put_user_ex(from->_sifields._pad[0],
| > | +					  &to->_sifields._pad[0]);
| > | +			switch (from->si_code >> 16) {
| > | +			case __SI_FAULT >> 16:
| > | +				break;
| > | +			case __SI_CHLD >> 16:
| > | +				put_user_ex(from->si_utime, &to->si_utime);
| > | +				put_user_ex(from->si_stime, &to->si_stime);
| > | +				put_user_ex(from->si_status, &to->si_status);
| > | +				/* FALL THROUGH */
| > | +			default:
| > 
| > Hi Hiroshi,
| 
| Hi Cyrill,
| 
| > 
| > may I ask why we use default here?
| 
| I don't know:) Hm, it looks old code.
| arch/i386/kernel/signal.c in 2.4 has similar code.
| 
| I guess this code didn't change when copy_siginfo_to_user() was moved
| from arch/i386/kernel/signal.c to kernel/signal.c.
| 
| Should we change this like copy_siginfo_tu_user() in kernel/signal.c?
| Copying si_pid was added in kernel/signal.c.
| 
| BTW, it seems same __ST_KILL and default.

Hiroshi, to be fair -- I just don't know what the
right solution would be ;-) I just noticed that
default: here a bit useless since we do 'testing'
the (from->si_code >> 16) after default: anyway.

So choose one /since I'm not really familiar with
process management in kernel/ :)

		-- Cyrill --

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

end of thread, other threads:[~2009-01-26 18:57 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2009-01-06  3:06 [RFC -tip 0/4] x86: reduce fixup of uaccess Hiroshi Shimamoto
2009-01-06  3:08 ` [RFC -tip 1/4] x86: uaccess: rename __put_user_u64() to __put_user_asm_u64() Hiroshi Shimamoto
2009-01-06  3:08 ` [RFC -tip 2/4] x86: uaccess: introduce new __{get|put}_user exception handling framework Hiroshi Shimamoto
2009-01-06  3:09 ` [RFC -tip 3/4] x86: signal: use __{get|put}_user_ex " Hiroshi Shimamoto
2009-01-06  3:10 ` [RFC -tip 4/4] x86: ia32_signal: " Hiroshi Shimamoto
2009-01-06 10:09 ` [RFC -tip 0/4] x86: reduce fixup of uaccess Ingo Molnar
2009-01-07  9:33 ` H. Peter Anvin
2009-01-08  1:43   ` Hiroshi Shimamoto
2009-01-23 23:48   ` [RFC v2 -tip 0/3] " Hiroshi Shimamoto
2009-01-23 23:49     ` [RFC v2 -tip 1/3] x86: uaccess: introduce try and catch framework Hiroshi Shimamoto
2009-01-23 23:50     ` [RFC v2 -tip 2/3] x86: signal: use {get|put}_user_try and catch Hiroshi Shimamoto
2009-01-23 23:50     ` [RFC v2 -tip 3/3] x86: ia32_signal: " Hiroshi Shimamoto
2009-01-24  7:36       ` Cyrill Gorcunov
2009-01-26 18:31         ` Hiroshi Shimamoto
2009-01-26 18:56           ` Cyrill Gorcunov
2009-01-24  0:51     ` [RFC v2 -tip 0/3] x86: reduce fixup of uaccess H. Peter Anvin
2009-01-24  4:39     ` H. Peter Anvin

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).