mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-04 09:59:32 +00:00
sparc64: Fix syscall restart, for real...
The change I put into copy_thread() just papered over the real problem. When we are looking to see if we should do a syscall restart, when deliverying a signal, we should only interpret the syscall return value as an error if the carry condition code(s) are set. Otherwise it's a success return. Also, sigreturn paths should do a pt_regs_clear_trap_type(). It turns out that doing a syscall restart when returning from a fork() does and should happen, from time to time. Even if copy_thread() returns success, copy_process() can still unwind and signal -ERESTARTNOINTR in the parent. Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
32039f4954
commit
2678fefedb
3 changed files with 11 additions and 7 deletions
|
@ -591,12 +591,6 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
|
|||
if (clone_flags & CLONE_SETTLS)
|
||||
t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3];
|
||||
|
||||
/* We do not want to accidently trigger system call restart
|
||||
* handling in the new thread. Therefore, clear out the trap
|
||||
* type, which will make pt_regs_regs_is_syscall() return false.
|
||||
*/
|
||||
pt_regs_clear_trap_type(t->kregs);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -332,6 +332,9 @@ void do_rt_sigreturn(struct pt_regs *regs)
|
|||
regs->tpc = tpc;
|
||||
regs->tnpc = tnpc;
|
||||
|
||||
/* Prevent syscall restart. */
|
||||
pt_regs_clear_trap_type(regs);
|
||||
|
||||
sigdelsetmask(&set, ~_BLOCKABLE);
|
||||
spin_lock_irq(¤t->sighand->siglock);
|
||||
current->blocked = set;
|
||||
|
@ -515,7 +518,8 @@ static void do_signal(struct pt_regs *regs, unsigned long orig_i0)
|
|||
siginfo_t info;
|
||||
int signr;
|
||||
|
||||
if (pt_regs_is_syscall(regs)) {
|
||||
if (pt_regs_is_syscall(regs) &&
|
||||
(regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) {
|
||||
pt_regs_clear_trap_type(regs);
|
||||
cookie.restart_syscall = 1;
|
||||
} else
|
||||
|
|
|
@ -268,6 +268,9 @@ void do_sigreturn32(struct pt_regs *regs)
|
|||
regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
|
||||
regs->tstate |= psr_to_tstate_icc(psr);
|
||||
|
||||
/* Prevent syscall restart. */
|
||||
pt_regs_clear_trap_type(regs);
|
||||
|
||||
err |= __get_user(fpu_save, &sf->fpu_save);
|
||||
if (fpu_save)
|
||||
err |= restore_fpu_state32(regs, &sf->fpu_state);
|
||||
|
@ -351,6 +354,9 @@ asmlinkage void do_rt_sigreturn32(struct pt_regs *regs)
|
|||
regs->tstate &= ~(TSTATE_ICC|TSTATE_XCC);
|
||||
regs->tstate |= psr_to_tstate_icc(psr);
|
||||
|
||||
/* Prevent syscall restart. */
|
||||
pt_regs_clear_trap_type(regs);
|
||||
|
||||
err |= __get_user(fpu_save, &sf->fpu_save);
|
||||
if (fpu_save)
|
||||
err |= restore_fpu_state32(regs, &sf->fpu_state);
|
||||
|
|
Loading…
Reference in a new issue