powerpc: fix double syscall restarts
Subsystems (2)
[grrr... mangled address in previous posting]
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 Al Viro <[email protected]>
--- arch/powerpc/kernel/signal.c | 2 ++ arch/powerpc/kernel/signal_32.c | 3 +-- arch/powerpc/kernel/signal_64.c | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-)
arch/powerpc/kernel/signal.c +2 -0
@@ -138,6 +138,7 @@ static int do_signal_pending(sigset_t *oldset, struct pt_regs *regs) ti->local_flags &= ~_TLF_RESTORE_SIGMASK;sigprocmask (SIG_SETMASK , ¤t->saved_sigmask,NULL ); } + regs->trap =0 ;return 0 ;/* no signals delivered */ }
@@ -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); } + regs->trap =0 ;if (ret) {spin_lock_irq (¤t->sighand->siglock); sigorsets(¤t->blocked, ¤t->blocked,
arch/powerpc/kernel/signal_32.c +1 -2
@@ -511,6 +511,7 @@ static long restore_user_regs(struct pt_regs *regs,if (!sig) save_r2 = (unsigned int )regs->gpr[2 ]; err =restore_general_regs (regs, sr); + regs->trap =0 ; err |=__get_user (msr, &sr->mc_gregs[PT_MSR ]);if (!sig) regs->gpr[2 ] = (unsigned long ) save_r2;
@@ -884,7 +885,6 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, regs->nip = (unsigned long ) ka->sa.sa_handler;/* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE ; - regs->trap =0 ;return 1 ; badframe:
@@ -1228,7 +1228,6 @@ int handle_signal32(unsigned long sig, struct k_sigaction *ka, regs->nip = (unsigned long ) ka->sa.sa_handler;/* enter the signal handler in big-endian mode */ regs->msr &= ~MSR_LE ; - regs->trap =0 ;return 1 ;
arch/powerpc/kernel/signal_64.c +1 -1
@@ -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->ccr, &sc->gp_regs[PT_CCR ]);/* 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->dsisr, &sc->gp_regs[PT_DSISR ]); err |=__get_user (regs->result, &sc->gp_regs[PT_RESULT ]);
Signature · 1 line
1.5.6.5