Commit 9a81c16b527528ad307843be5571111aa8d35a80
Committed by
Linus Torvalds
1 parent
b68e9d4581
Exists in
master
and in
39 other branches
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: Al Viro <viro@zeniv.linux.org.uk> Acked-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 3 changed files with 4 additions and 3 deletions Side-by-side Diff
arch/powerpc/kernel/signal.c
... | ... | @@ -138,6 +138,7 @@ |
138 | 138 | ti->local_flags &= ~_TLF_RESTORE_SIGMASK; |
139 | 139 | sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); |
140 | 140 | } |
141 | + regs->trap = 0; | |
141 | 142 | return 0; /* no signals delivered */ |
142 | 143 | } |
143 | 144 | |
... | ... | @@ -164,6 +165,7 @@ |
164 | 165 | ret = handle_rt_signal64(signr, &ka, &info, oldset, regs); |
165 | 166 | } |
166 | 167 | |
168 | + regs->trap = 0; | |
167 | 169 | if (ret) { |
168 | 170 | spin_lock_irq(¤t->sighand->siglock); |
169 | 171 | sigorsets(¤t->blocked, ¤t->blocked, |
arch/powerpc/kernel/signal_32.c
... | ... | @@ -511,6 +511,7 @@ |
511 | 511 | if (!sig) |
512 | 512 | save_r2 = (unsigned int)regs->gpr[2]; |
513 | 513 | err = restore_general_regs(regs, sr); |
514 | + regs->trap = 0; | |
514 | 515 | err |= __get_user(msr, &sr->mc_gregs[PT_MSR]); |
515 | 516 | if (!sig) |
516 | 517 | regs->gpr[2] = (unsigned long) save_r2; |
... | ... | @@ -884,7 +885,6 @@ |
884 | 885 | regs->nip = (unsigned long) ka->sa.sa_handler; |
885 | 886 | /* enter the signal handler in big-endian mode */ |
886 | 887 | regs->msr &= ~MSR_LE; |
887 | - regs->trap = 0; | |
888 | 888 | return 1; |
889 | 889 | |
890 | 890 | badframe: |
... | ... | @@ -1228,7 +1228,6 @@ |
1228 | 1228 | regs->nip = (unsigned long) ka->sa.sa_handler; |
1229 | 1229 | /* enter the signal handler in big-endian mode */ |
1230 | 1230 | regs->msr &= ~MSR_LE; |
1231 | - regs->trap = 0; | |
1232 | 1231 | |
1233 | 1232 | return 1; |
1234 | 1233 |
arch/powerpc/kernel/signal_64.c
... | ... | @@ -178,7 +178,7 @@ |
178 | 178 | err |= __get_user(regs->xer, &sc->gp_regs[PT_XER]); |
179 | 179 | err |= __get_user(regs->ccr, &sc->gp_regs[PT_CCR]); |
180 | 180 | /* skip SOFTE */ |
181 | - err |= __get_user(regs->trap, &sc->gp_regs[PT_TRAP]); | |
181 | + regs->trap = 0; | |
182 | 182 | err |= __get_user(regs->dar, &sc->gp_regs[PT_DAR]); |
183 | 183 | err |= __get_user(regs->dsisr, &sc->gp_regs[PT_DSISR]); |
184 | 184 | err |= __get_user(regs->result, &sc->gp_regs[PT_RESULT]); |