From: David Woodhouse 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 Signed-off-by: Andrew Morton --- 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<