diff options
author | Rabin Vincent <rabin@rab.in> | 2015-02-08 17:53:22 +0100 |
---|---|---|
committer | Jesper Nilsson <jespern@axis.com> | 2015-03-25 10:51:53 +0100 |
commit | 0f72e5c0df732658d5e9e3c556c9c6928034e291 (patch) | |
tree | 01664612c9e7ba6c318196295522e187f3b41d56 /arch/cris/arch-v32/kernel/entry.S | |
parent | db4a35c651a10eddc6b48b69e1db1f46bea303fa (diff) | |
download | op-kernel-dev-0f72e5c0df732658d5e9e3c556c9c6928034e291.zip op-kernel-dev-0f72e5c0df732658d5e9e3c556c9c6928034e291.tar.gz |
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>
Diffstat (limited to 'arch/cris/arch-v32/kernel/entry.S')
-rw-r--r-- | arch/cris/arch-v32/kernel/entry.S | 5 |
1 files changed, 3 insertions, 2 deletions
diff --git a/arch/cris/arch-v32/kernel/entry.S b/arch/cris/arch-v32/kernel/entry.S index d4c088b..1ea29b7 100644 --- a/arch/cris/arch-v32/kernel/entry.S +++ b/arch/cris/arch-v32/kernel/entry.S @@ -147,7 +147,7 @@ system_call: ;; Stack-frame similar to the irq heads, which is reversed in ;; ret_from_sys_call. - sub.d 92, $sp ; Skip EXS and EDA. + sub.d 92, $sp ; Skip EDA. movem $r13, [$sp] move.d $sp, $r8 addq 14*4, $r8 @@ -158,8 +158,9 @@ system_call: move $ccs, $r4 move $srp, $r5 move $erp, $r6 + move.d $r9, $r7 ; Store syscall number in EXS subq 4, $sp - movem $r6, [$r8] + movem $r7, [$r8] ei ; Enable interrupts while processing syscalls. move.d $r10, [$sp] |