aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-09-22 01:30:13 -0400
committerDavid S. Miller <davem@davemloft.net>2010-09-22 01:30:13 -0400
commitc27852597829128a9c9d96d79ec454a83c6b0da5 (patch)
tree3fe8d2b5cd9d59a47c64491ba2398bc2039d339c
parent392c21802ee3aa85cee0e703105f797a8a7b9416 (diff)
sparc: Prevent no-handler signal syscall restart recursion.
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>
-rw-r--r--arch/sparc/kernel/signal32.c4
-rw-r--r--arch/sparc/kernel/signal_32.c2
-rw-r--r--arch/sparc/kernel/signal_64.c2
3 files changed, 7 insertions, 1 deletions
diff --git a/arch/sparc/kernel/signal32.c b/arch/sparc/kernel/signal32.c
index 643a354795cc..75fad425e249 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,
616 616
617 flush_signal_insns(address); 617 flush_signal_insns(address);
618 } 618 }
619 return; 619 return 0;
620 620
621sigill: 621sigill:
622 do_exit(SIGILL); 622 do_exit(SIGILL);
@@ -840,12 +840,14 @@ void do_signal32(sigset_t *oldset, struct pt_regs * regs,
840 regs->u_regs[UREG_I0] = orig_i0; 840 regs->u_regs[UREG_I0] = orig_i0;
841 regs->tpc -= 4; 841 regs->tpc -= 4;
842 regs->tnpc -= 4; 842 regs->tnpc -= 4;
843 pt_regs_clear_syscall(regs);
843 } 844 }
844 if (restart_syscall && 845 if (restart_syscall &&
845 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { 846 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
846 regs->u_regs[UREG_G1] = __NR_restart_syscall; 847 regs->u_regs[UREG_G1] = __NR_restart_syscall;
847 regs->tpc -= 4; 848 regs->tpc -= 4;
848 regs->tnpc -= 4; 849 regs->tnpc -= 4;
850 pt_regs_clear_syscall(regs);
849 } 851 }
850 852
851 /* If there's no signal to deliver, we just put the saved sigmask 853 /* 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 99c85e99bbcf..5e5c5fd03783 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)
580 regs->u_regs[UREG_I0] = orig_i0; 580 regs->u_regs[UREG_I0] = orig_i0;
581 regs->pc -= 4; 581 regs->pc -= 4;
582 regs->npc -= 4; 582 regs->npc -= 4;
583 pt_regs_clear_syscall(regs);
583 } 584 }
584 if (restart_syscall && 585 if (restart_syscall &&
585 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { 586 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
586 regs->u_regs[UREG_G1] = __NR_restart_syscall; 587 regs->u_regs[UREG_G1] = __NR_restart_syscall;
587 regs->pc -= 4; 588 regs->pc -= 4;
588 regs->npc -= 4; 589 regs->npc -= 4;
590 pt_regs_clear_syscall(regs);
589 } 591 }
590 592
591 /* if there's no signal to deliver, we just put the saved sigmask 593 /* 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 3f19e673e2cd..006fe4515886 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)
600 regs->u_regs[UREG_I0] = orig_i0; 600 regs->u_regs[UREG_I0] = orig_i0;
601 regs->tpc -= 4; 601 regs->tpc -= 4;
602 regs->tnpc -= 4; 602 regs->tnpc -= 4;
603 pt_regs_clear_syscall(regs);
603 } 604 }
604 if (restart_syscall && 605 if (restart_syscall &&
605 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) { 606 regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
606 regs->u_regs[UREG_G1] = __NR_restart_syscall; 607 regs->u_regs[UREG_G1] = __NR_restart_syscall;
607 regs->tpc -= 4; 608 regs->tpc -= 4;
608 regs->tnpc -= 4; 609 regs->tnpc -= 4;
610 pt_regs_clear_syscall(regs);
609 } 611 }
610 612
611 /* If there's no signal to deliver, we just put the saved sigmask 613 /* If there's no signal to deliver, we just put the saved sigmask