Commit 55bb9480f9159b229ac3c3454c97b62d1e0a7e80

Authored by Vineet Gupta
1 parent 5c39c0ab5e

ARC: [Review] Prevent incorrect syscall restarts

Per Al Viro's "signals for dummies" https://lkml.org/lkml/2012/12/6/366
there are 3 golden rules for (not) restarting syscalls:

"	What we need to guarantee is
* restarts do not happen on signals caught in interrupts or exceptions
* restarts do not happen on signals caught in sigreturn()
* restart should happen only once, even if we get through do_signal()
  many times."

ARC Port already handled #1, this patch fixes #2 and #3.

We use the additional state in pt_regs->orig_r8 to ckh if restarting
has already been done once.

Thanks to Al Viro for spotting this.

Signed-off-by: Vineet Gupta <vgupta@synopsys.com>
Cc: Al Viro <viro@ZenIV.linux.org.uk>

Showing 2 changed files with 11 additions and 4 deletions Side-by-side Diff

arch/arc/include/asm/ptrace.h
... ... @@ -100,6 +100,9 @@
100 100 #define in_syscall(regs) (regs->event & orig_r8_IS_SCALL)
101 101 #define in_brkpt_trap(regs) (regs->event & orig_r8_IS_BRKPT)
102 102  
  103 +#define syscall_wont_restart(regs) (regs->event |= orig_r8_IS_SCALL_RESTARTED)
  104 +#define syscall_restartable(regs) !(regs->event & orig_r8_IS_SCALL_RESTARTED)
  105 +
103 106 #define current_pt_regs() \
104 107 ({ \
105 108 /* open-coded current_thread_info() */ \
arch/arc/kernel/signal.c
... ... @@ -128,6 +128,9 @@
128 128 if (restore_altstack(&sf->uc.uc_stack))
129 129 goto badframe;
130 130  
  131 + /* Don't restart from sigreturn */
  132 + syscall_wont_restart(regs);
  133 +
131 134 return regs->r0;
132 135  
133 136 badframe:
134 137  
135 138  
... ... @@ -318,13 +321,13 @@
318 321  
319 322 signr = get_signal_to_deliver(&info, &ka, regs, NULL);
320 323  
321   - /* Are we from a system call? */
322   - restart_scall = in_syscall(regs);
  324 + restart_scall = in_syscall(regs) && syscall_restartable(regs);
323 325  
324 326 if (signr > 0) {
325   - if (restart_scall)
  327 + if (restart_scall) {
326 328 arc_restart_syscall(&ka, regs);
327   -
  329 + syscall_wont_restart(regs); /* No more restarts */
  330 + }
328 331 handle_signal(signr, &ka, &info, regs);
329 332 return;
330 333 }
... ... @@ -339,6 +342,7 @@
339 342 regs->r8 = __NR_restart_syscall;
340 343 regs->ret -= 4;
341 344 }
  345 + syscall_wont_restart(regs); /* No more restarts */
342 346 }
343 347  
344 348 /* If there's no signal to deliver, restore the saved sigmask back */