
From: David Woodhouse <dwmw2@infradead.org>

This is a port to ppc64 of the recent "uml: fix signal mask on delivery error"
fix.

If the user stack limit is reached or the signal stack assigned with
sigaltstack() is invalid when a user signal handler with SA_ONSTACK has to be
started, the signal mask of the interrupted user program is modified.  This
happens because the mask, that should be used with the handler only, is
written to "current->blocked" even if the handler could not be started.  But
without a handler, no rewrite of the original mask at sys_sigreturn will be
done.

A slightly different case is sys_sigsuspend(), where the mask is already
modified when kern_do_signal() is started.  "*oldset" and "current->blocked"
are not equal here and thus current->blocked has to be set to *oldset, if an
error occurs in handle_signal().

This ought to fix it for 2.6, along with single-stepping over syscalls and
single-stepping over sigreturn (which is a special case).

Acked-by: Paul Mackerras <paulus@samba.org>
Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/arch/ppc64/kernel/entry.S         |    4 ++--
 25-akpm/arch/ppc64/kernel/ptrace.c        |    3 ++-
 25-akpm/include/asm-ppc64/ptrace-common.h |    2 ++
 25-akpm/include/asm-ppc64/thread_info.h   |    2 ++
 4 files changed, 8 insertions(+), 3 deletions(-)

diff -puN arch/ppc64/kernel/entry.S~ppc64-fix-signal-mask-on-delivery-error arch/ppc64/kernel/entry.S
--- 25/arch/ppc64/kernel/entry.S~ppc64-fix-signal-mask-on-delivery-error	Mon Nov 22 14:27:43 2004
+++ 25-akpm/arch/ppc64/kernel/entry.S	Mon Nov 22 14:27:43 2004
@@ -162,7 +162,7 @@ syscall_error_cont:
 
 	/* check for syscall tracing or audit */
 	ld	r9,TI_FLAGS(r12)
-	andi.	r0,r9,_TIF_SYSCALL_T_OR_A
+	andi.	r0,r9,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
 	bne-	syscall_exit_trace
 syscall_exit_trace_cont:
 
@@ -317,7 +317,7 @@ _GLOBAL(ppc64_rt_sigreturn)
 	blt	syscall_exit
 	clrrdi	r4,r1,THREAD_SHIFT
 	ld	r4,TI_FLAGS(r4)
-	andi.	r4,r4,_TIF_SYSCALL_T_OR_A
+	andi.	r4,r4,(_TIF_SYSCALL_T_OR_A|_TIF_SINGLESTEP)
 	beq+	81f
 	bl	.do_syscall_trace_leave
 81:	b	.ret_from_except
diff -puN arch/ppc64/kernel/ptrace.c~ppc64-fix-signal-mask-on-delivery-error arch/ppc64/kernel/ptrace.c
--- 25/arch/ppc64/kernel/ptrace.c~ppc64-fix-signal-mask-on-delivery-error	Mon Nov 22 14:27:43 2004
+++ 25-akpm/arch/ppc64/kernel/ptrace.c	Mon Nov 22 14:27:43 2004
@@ -318,7 +318,8 @@ void do_syscall_trace_leave(void)
 	if (unlikely(current->audit_context))
 		audit_syscall_exit(current, 0);	/* FIXME: pass pt_regs */
 
-	if (test_thread_flag(TIF_SYSCALL_TRACE)
+	if ((test_thread_flag(TIF_SYSCALL_TRACE)
+	     || test_thread_flag(TIF_SINGLESTEP))
 	    && (current->ptrace & PT_PTRACED))
 		do_syscall_trace();
 }
diff -puN include/asm-ppc64/ptrace-common.h~ppc64-fix-signal-mask-on-delivery-error include/asm-ppc64/ptrace-common.h
--- 25/include/asm-ppc64/ptrace-common.h~ppc64-fix-signal-mask-on-delivery-error	Mon Nov 22 14:27:43 2004
+++ 25-akpm/include/asm-ppc64/ptrace-common.h	Mon Nov 22 14:27:43 2004
@@ -58,6 +58,7 @@ static inline void set_single_step(struc
 	struct pt_regs *regs = task->thread.regs;
 	if (regs != NULL)
 		regs->msr |= MSR_SE;
+	set_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
 }
 
 static inline void clear_single_step(struct task_struct *task)
@@ -65,6 +66,7 @@ static inline void clear_single_step(str
 	struct pt_regs *regs = task->thread.regs;
 	if (regs != NULL)
 		regs->msr &= ~MSR_SE;
+	clear_ti_thread_flag(task->thread_info, TIF_SINGLESTEP);
 }
 
 #endif /* _PPC64_PTRACE_COMMON_H */
diff -puN include/asm-ppc64/thread_info.h~ppc64-fix-signal-mask-on-delivery-error include/asm-ppc64/thread_info.h
--- 25/include/asm-ppc64/thread_info.h~ppc64-fix-signal-mask-on-delivery-error	Mon Nov 22 14:27:43 2004
+++ 25-akpm/include/asm-ppc64/thread_info.h	Mon Nov 22 14:27:43 2004
@@ -97,6 +97,7 @@ static inline struct thread_info *curren
 #define TIF_RUN_LIGHT		6	/* iSeries run light */
 #define TIF_ABI_PENDING		7	/* 32/64 bit switch needed */
 #define TIF_SYSCALL_AUDIT	8	/* syscall auditing active */
+#define TIF_SINGLESTEP		9	/* singlestepping active */
 
 /* as above, but as bit values */
 #define _TIF_SYSCALL_TRACE	(1<<TIF_SYSCALL_TRACE)
@@ -108,6 +109,7 @@ static inline struct thread_info *curren
 #define _TIF_RUN_LIGHT		(1<<TIF_RUN_LIGHT)
 #define _TIF_ABI_PENDING	(1<<TIF_ABI_PENDING)
 #define _TIF_SYSCALL_AUDIT	(1<<TIF_SYSCALL_AUDIT)
+#define _TIF_SINGLESTEP		(1<<TIF_SINGLESTEP)
 #define _TIF_SYSCALL_T_OR_A	(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT)
 
 #define _TIF_USER_WORK_MASK	(_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | \
_
