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>
This commit is contained in:
parent
392c21802e
commit
c278525978
3 changed files with 7 additions and 1 deletions
|
@ -616,7 +616,7 @@ static int setup_frame32(struct k_sigaction *ka, struct pt_regs *regs,
|
||||||
|
|
||||||
flush_signal_insns(address);
|
flush_signal_insns(address);
|
||||||
}
|
}
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
sigill:
|
sigill:
|
||||||
do_exit(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->u_regs[UREG_I0] = orig_i0;
|
||||||
regs->tpc -= 4;
|
regs->tpc -= 4;
|
||||||
regs->tnpc -= 4;
|
regs->tnpc -= 4;
|
||||||
|
pt_regs_clear_syscall(regs);
|
||||||
}
|
}
|
||||||
if (restart_syscall &&
|
if (restart_syscall &&
|
||||||
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
||||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||||
regs->tpc -= 4;
|
regs->tpc -= 4;
|
||||||
regs->tnpc -= 4;
|
regs->tnpc -= 4;
|
||||||
|
pt_regs_clear_syscall(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no signal to deliver, we just put the saved sigmask
|
/* If there's no signal to deliver, we just put the saved sigmask
|
||||||
|
|
|
@ -580,12 +580,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||||
regs->u_regs[UREG_I0] = orig_i0;
|
regs->u_regs[UREG_I0] = orig_i0;
|
||||||
regs->pc -= 4;
|
regs->pc -= 4;
|
||||||
regs->npc -= 4;
|
regs->npc -= 4;
|
||||||
|
pt_regs_clear_syscall(regs);
|
||||||
}
|
}
|
||||||
if (restart_syscall &&
|
if (restart_syscall &&
|
||||||
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
||||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||||
regs->pc -= 4;
|
regs->pc -= 4;
|
||||||
regs->npc -= 4;
|
regs->npc -= 4;
|
||||||
|
pt_regs_clear_syscall(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* if there's no signal to deliver, we just put the saved sigmask
|
/* if there's no signal to deliver, we just put the saved sigmask
|
||||||
|
|
|
@ -600,12 +600,14 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
||||||
regs->u_regs[UREG_I0] = orig_i0;
|
regs->u_regs[UREG_I0] = orig_i0;
|
||||||
regs->tpc -= 4;
|
regs->tpc -= 4;
|
||||||
regs->tnpc -= 4;
|
regs->tnpc -= 4;
|
||||||
|
pt_regs_clear_syscall(regs);
|
||||||
}
|
}
|
||||||
if (restart_syscall &&
|
if (restart_syscall &&
|
||||||
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
regs->u_regs[UREG_I0] == ERESTART_RESTARTBLOCK) {
|
||||||
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
regs->u_regs[UREG_G1] = __NR_restart_syscall;
|
||||||
regs->tpc -= 4;
|
regs->tpc -= 4;
|
||||||
regs->tnpc -= 4;
|
regs->tnpc -= 4;
|
||||||
|
pt_regs_clear_syscall(regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If there's no signal to deliver, we just put the saved sigmask
|
/* If there's no signal to deliver, we just put the saved sigmask
|
||||||
|
|
Loading…
Add table
Reference in a new issue