linux-stable-rt/arch/arm/kernel
Al Viro 653d48b221 arm: fix really nasty sigreturn bug
If a signal hits us outside of a syscall and another gets delivered
when we are in sigreturn (e.g. because it had been in sa_mask for
the first one and got sent to us while we'd been in the first handler),
we have a chance of returning from the second handler to location one
insn prior to where we ought to return.  If r0 happens to contain -513
(-ERESTARTNOINTR), sigreturn will get confused into doing restart
syscall song and dance.

Incredible joy to debug, since it manifests as random, infrequent and
very hard to reproduce double execution of instructions in userland
code...

The fix is simple - mark it "don't bother with restarts" in wrapper,
i.e. set r8 to 0 in sys_sigreturn and sys_rt_sigreturn wrappers,
suppressing the syscall restart handling on return from these guys.
They can't legitimately return a restart-worthy error anyway.

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

	void f(int n)
	{
		__asm__ __volatile__(
			"ldr r0, [%0]\n"
			"b 1f\n"
			"b 2f\n"
			"1:b .\n"
			"2:\n" : : "r"(&n));
	}

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

	main()
	{
		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 */

		write(1, "buggered\n", 9);
		return 1;
	}

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Acked-by: Russell King <rmk+kernel@arm.linux.org.uk>
Cc: stable@kernel.org
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
2010-09-17 10:22:18 -07:00
..
.gitignore
Makefile Merge branch 'devel-stable' into devel 2010-07-31 14:20:16 +01:00
armksyms.c
arthur.c
asm-offsets.c
atags.c
atags.h
bios32.c
calls.S ARM: 6343/1: wire up fanotify and prlimit64 syscalls on ARM 2010-09-01 10:06:08 +01:00
compat.c
compat.h
crash_dump.c
crunch-bits.S
crunch.c
debug.S
dma-isa.c
dma.c
early_printk.c
ecard.c
ecard.h
elf.c
entry-armv.S Merge branch 'devel-stable' into devel 2010-07-31 14:20:16 +01:00
entry-common.S arm: fix really nasty sigreturn bug 2010-09-17 10:22:18 -07:00
entry-header.S
etm.c Input: sysrq - drop tty argument from sysrq ops handlers 2010-08-19 22:07:06 -07:00
fiq.c
ftrace.c
head-common.S
head-nommu.S
head.S
init_task.c
io.c
irq.c
isa.c
iwmmxt.S
kgdb.c ARM: 6326/1: kgdb: fix GDB_MAX_REGS no longer used 2010-08-14 09:28:35 +01:00
kprobes-decode.c
kprobes.c
leds.c
machine_kexec.c
module.c ARM: 6191/1: Do not compile the Thumb-2 module relocations on an ARM kernel 2010-08-05 10:35:48 +01:00
perf_event.c ARM: 6352/1: perf: fix event validation 2010-09-02 16:36:42 +01:00
pmu.c
process.c Merge branch 'devel-stable' into devel 2010-07-31 14:20:16 +01:00
ptrace.c
ptrace.h
relocate_kernel.S
return_address.c
setup.c Merge branch 'devel-stable' into devel 2010-07-31 14:20:16 +01:00
signal.c
signal.h
smp.c
smp_scu.c
smp_twd.c
stacktrace.c
sys_arm.c Make do_execve() take a const filename pointer 2010-08-17 18:07:43 -07:00
sys_oabi-compat.c Mark arguments to certain syscalls as being const 2010-08-13 16:53:13 -07:00
tcm.c
tcm.h
thumbee.c
time.c
traps.c
unwind.c
vmlinux.lds.S
xscale-cp0.c