| From 01776b84f8a241efa9de827f422f83c3f7c7007d Mon Sep 17 00:00:00 2001 |
| From: David S. Miller <davem@davemloft.net> |
| Date: Tue, 21 Sep 2010 22:30:13 -0700 |
| Subject: [PATCH] sparc: Prevent no-handler signal syscall restart recursion. |
| |
| commit c27852597829128a9c9d96d79ec454a83c6b0da5 upstream. |
| |
| Explicitly clear the "in-syscall" bit when we have no signal |
| handler and back up the program counters to back up the system |
| call. |
| |
| Reported-by: Al Viro <viro@ZenIV.linux.org.uk> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com> |
| |
| diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c |
| index 643a354..75fad42 100644 |
| --- a/arch/sparc/kernel/signal32.c |
| +++ b/arch/sparc/kernel/signal32.c |
| @@ -616,7 +616,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs, |
| |
| flush_signal_insns(address); |
| } |
| - return; |
| + return 0; |
| |
| sigill: |
| do_exit(SIGILL); |
| @@ -840,12 +840,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs, |
| regs->u_regs[UREG_I0] = orig_i0; |
| regs->tpc -= 4; |
| regs->tnpc -= 4; |
| + pt_regs_clear_syscall(regs); |
| } |
| if (restart_syscall && |
| regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { |
| regs->u_regs[UREG_G1] = __NR_restart_syscall; |
| regs->tpc -= 4; |
| regs->tnpc -= 4; |
| + pt_regs_clear_syscall(regs); |
| } |
| |
| /* If there's no signal to deliver, we just put the saved sigmask |
| diff --git a/arch/sparc/kernel/signal_32.c b/arch/sparc/kernel/signal_32.c |
| index 99c85e9..5e5c5fd 100644 |
| --- a/arch/sparc/kernel/signal_32.c |
| +++ b/arch/sparc/kernel/signal_32.c |
| @@ -580,12 +580,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) |
| regs->u_regs[UREG_I0] = orig_i0; |
| regs->pc -= 4; |
| regs->npc -= 4; |
| + pt_regs_clear_syscall(regs); |
| } |
| if (restart_syscall && |
| regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { |
| regs->u_regs[UREG_G1] = __NR_restart_syscall; |
| regs->pc -= 4; |
| regs->npc -= 4; |
| + pt_regs_clear_syscall(regs); |
| } |
| |
| /* if there's no signal to deliver, we just put the saved sigmask |
| diff --git a/arch/sparc/kernel/signal_64.c b/arch/sparc/kernel/signal_64.c |
| index 3f19e67..006fe45 100644 |
| --- a/arch/sparc/kernel/signal_64.c |
| +++ b/arch/sparc/kernel/signal_64.c |
| @@ -600,12 +600,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0) |
| regs->u_regs[UREG_I0] = orig_i0; |
| regs->tpc -= 4; |
| regs->tnpc -= 4; |
| + pt_regs_clear_syscall(regs); |
| } |
| if (restart_syscall && |
| regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { |
| regs->u_regs[UREG_G1] = __NR_restart_syscall; |
| regs->tpc -= 4; |
| regs->tnpc -= 4; |
| + pt_regs_clear_syscall(regs); |
| } |
| |
| /* If there's no signal to deliver, we just put the saved sigmask |
| -- |
| 1.7.4.4 |
| |