CRISv32: prevent bogus restarts on sigreturn
authorRabin Vincent <rabin@rab.in>
Sun, 8 Feb 2015 16:53:22 +0000 (17:53 +0100)
committerJesper Nilsson <jespern@axis.com>
Wed, 25 Mar 2015 09:51:53 +0000 (10:51 +0100)
commit0f72e5c0df732658d5e9e3c556c9c6928034e291
tree01664612c9e7ba6c318196295522e187f3b41d56
parentdb4a35c651a10eddc6b48b69e1db1f46bea303fa
CRISv32: prevent bogus restarts on sigreturn

Al Viro noted that CRIS is vulnerable to bogus restarts on sigreturn.

The fixes CRISv32 by using regs->exs as an additional indicator to
whether we should attempt to restart the syscall or not.  EXS is only
used in the sigtrap handling, and in that path we already have r9 (the
other indicator, which indicates if we're in a syscall or not) cleared.

Test case, a port of Al's ARM version from 653d48b22166db2d8 ("arm: fix
really nasty sigreturn bug"):

  #include <unistd.h>
  #include <signal.h>
  #include <stdlib.h>
  #include <sys/time.h>
  #include <errno.h>

  void f(int n)
  {
   register int r10 asm ("r10") = n;

          __asm__ __volatile__(
   "ba 1f \n"
   "nop \n"
   "break 8 \n"
   "1: ba . \n"
   "nop \n"
   :
   : "r" (r10)
   : "memory");
  }

  void handler1(int sig) { }
  void handler2(int sig) { raise(1); }
  void handler3(int sig) { exit(0); }

  int main(int argc, char *argv[])
  {
          struct sigaction s = {.sa_handler = handler2};
          struct itimerval t1 = { .it_value = {1} };
          struct itimerval t2 = { .it_value = {2} };

          signal(1, handler1);

          sigemptyset(&s.sa_mask);
          sigaddset(&s.sa_mask, 1);
          sigaction(SIGALRM, &s, NULL);

          signal(SIGVTALRM, handler3);

          setitimer(ITIMER_REAL, &t1, NULL);
          setitimer(ITIMER_VIRTUAL, &t2, NULL);

          f(-513); /* -ERESTARTNOINTR */

          return 0;
  }

Reported-by: Al Viro <viro@ZenIV.linux.org.uk>
Link: http://lkml.kernel.org/r/20121208074429.GC4939@ZenIV.linux.org.uk
Signed-off-by: Rabin Vincent <rabin@rab.in>
Signed-off-by: Jesper Nilsson <jespern@axis.com>
arch/cris/arch-v32/kernel/entry.S
arch/cris/arch-v32/kernel/signal.c