Commit 9a81c16b authored by Al Viro's avatar Al Viro Committed by Linus Torvalds

powerpc: fix double syscall restarts

Make sigreturn zero regs->trap, make do_signal() do the same on all
paths.  As it is, signal interrupting e.g. read() from fd 512 (==
ERESTARTSYS) with another signal getting unblocked when the first
handler finishes will lead to restart one insn earlier than it ought
to.  Same for multiple signals with in-kernel handlers interrupting
that sucker at the same time.  Same for multiple signals of any kind
interrupting that sucker on 64bit...
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
Acked-by: default avatarPaul Mackerras <paulus@samba.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent b68e9d45
...@@ -138,6 +138,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ...@@ -138,6 +138,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
ti->local_flags &= ~_TLF_RESTORE_SIGMASK; ti->local_flags &= ~_TLF_RESTORE_SIGMASK;
sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL); sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
} }
regs->trap = 0;
return 0; /* no signals delivered */ return 0; /* no signals delivered */
} }
...@@ -164,6 +165,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ...@@ -164,6 +165,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs)
ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); ret = handle_rt_signal64(signr, &ka, &info, oldset, regs);
} }
regs->trap = 0;
if (ret) { if (ret) {
spin_lock_irq(&current->sighand->siglock); spin_lock_irq(&current->sighand->siglock);
sigorsets(&current->blocked, &current->blocked, sigorsets(&current->blocked, &current->blocked,
......
...@@ -511,6 +511,7 @@ static long restore_user_regs(struct pt_regs *regs, ...@@ -511,6 +511,7 @@ static long restore_user_regs(struct pt_regs *regs,
if (!sig) if (!sig)
save_r2 = (unsigned int)regs->gpr[2]; save_r2 = (unsigned int)regs->gpr[2];
err = restore_general_regs(regs, sr); err = restore_general_regs(regs, sr);
regs->trap = 0;
err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); err |= __get_user(msr, &sr->mc_gregs[PT_MSR]);
if (!sig) if (!sig)
regs->gpr[2] = (unsigned long) save_r2; regs->gpr[2] = (unsigned long) save_r2;
...@@ -884,7 +885,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -884,7 +885,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
regs->nip = (unsigned long) ka->sa.sa_handler; regs->nip = (unsigned long) ka->sa.sa_handler;
/* enter the signal handler in big-endian mode */ /* enter the signal handler in big-endian mode */
regs->msr &= ~MSR_LE; regs->msr &= ~MSR_LE;
regs->trap = 0;
return 1; return 1;
badframe: badframe:
...@@ -1228,7 +1228,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1228,7 +1228,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka,
regs->nip = (unsigned long) ka->sa.sa_handler; regs->nip = (unsigned long) ka->sa.sa_handler;
/* enter the signal handler in big-endian mode */ /* enter the signal handler in big-endian mode */
regs->msr &= ~MSR_LE; regs->msr &= ~MSR_LE;
regs->trap = 0;
return 1; return 1;
......
...@@ -178,7 +178,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig, ...@@ -178,7 +178,7 @@ static long restore_sigcontext(struct pt_regs *regs, sigset_t *set, int sig,
err |= __get_user(regs->xer, &sc->gp_regs[PT_XER]); err |= __get_user(regs->xer, &sc->gp_regs[PT_XER]);
err |= __get_user(regs->ccr, &sc->gp_regs[PT_CCR]); err |= __get_user(regs->ccr, &sc->gp_regs[PT_CCR]);
/* skip SOFTE */ /* skip SOFTE */
err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); regs->trap = 0;
err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]); err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]);
err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]); err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]);
err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment