tmp_suning_uos_patched/arch/x86
Roland McGrath 83bd01024b x86: protect against sigaltstack wraparound
cf http://lkml.org/lkml/2007/10/3/41

To summarize: on Linux, SA_ONSTACK decides whether you are already on the
signal stack based on the value of the SP at the time of a signal.  If
you are not already inside the range, you are not "on the signal stack"
and so the new signal handler frame starts over at the base of the signal
stack.

sigaltstack (and sigstack before it) was invented in BSD.  There, the
SA_ONSTACK behavior has always been different.  It uses a kernel state
flag to decide, rather than the SP value.  When you first take an
SA_ONSTACK signal and switch to the alternate signal stack, it sets the
SS_ONSTACK flag in the thread's sigaltstack state in the kernel.
Thereafter you are "on the signal stack" and don't switch SP before
pushing a handler frame no matter what the SP value is.  Only when you
sigreturn from the original handler context do you clear the SS_ONSTACK
flag so that a new handler frame will start over at the base of the
alternate signal stack.

The undesireable effect of the Linux behavior is that an overflow of the
alternate signal stack can not only go undetected, but lead to a ring
buffer effect of clobbering the original handler frame at the base of the
signal stack for each successive signal that comes just after the
overflow.  This is what Shi Weihua's test case demonstrates.  Normally
this does not come up because of the signal mask, but the test case uses
SA_NODEFER for its SIGSEGV handler.

The other subtle part of the existing Linux semantics is that a simple
longjmp out of a signal handler serves to take you off the signal stack
in a safe and reliable fashion without having used sigreturn (nor having
just returned from the handler normally, which means the same).  After
the longjmp (or even informal stack switching not via any proper libc or
kernel interface), the alternate signal stack stands ready to be used
again.

A paranoid program would allocate a PROT_NONE red zone around its
alternate signal stack.  Then a small overflow would trigger a SIGSEGV in
handler setup, and be fatal (core dump) whether or not SIGSEGV is
blocked.  As with thread stack red zones, that cannot catch all overflows
(or underflows).  e.g., a local array as large as page size allocated in
a function called from a handler, but not actually touched before more
calls push more stack, could cause an overflow that silently pushes into
some unrelated allocated pages.

The BSD behavior does not do anything in particular about overflow.  But
it does at least avoid the wraparound or "ring buffer effect", so you'll
just get a straightforward all-out overflow down your address space past
the low end of the alternate signal stack.  I don't know what the BSD
behavior is for longjmp out of an SA_ONSTACK handler.

The POSIX wording relating to sigaltstack is pretty minimal.  I don't
think it speaks to this issue one way or another.  (The program that
overflows its stack is clearly in undefined behavior territory of one
sort or another anyhow.)

Given the longjmp issue and the potential for highly subtle complications
in existing programs relying on this in arcane ways deep in their code, I
am very dubious about changing the behavior to the BSD style persistent
flag.  I think Shi Weihua's patches have a similar effect by tracking the
SP used in the last handler setup.

I think it would be sensible for the signal handler setup code to detect
when it would itself be causing a stack overflow.  Maybe something like
the following patch (untested).  This issue exists in the same way on all
machines, so ideally they would all do a similar check.

When it's the handler function itself or its callees that cause the
overflow, rather than the signal handler frame setup alone crossing the
boundary, this still won't help.  But I don't see any way to distinguish
that from the valid longjmp case.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
2008-01-30 13:30:06 +01:00
..
boot x86: provide a DMI based port 0x80 I/O delay override. 2008-01-30 13:30:05 +01:00
configs x86 gart: rename CONFIG_IOMMU to CONFIG_GART_IOMMU 2007-10-30 00:22:22 +01:00
crypto [CRYPTO] twofish: Merge common glue code 2008-01-14 17:07:57 +11:00
ia32 x86 - 32-bit ptrace emulation mishandles 6th arg 2007-11-10 04:30:36 +01:00
kernel x86: protect against sigaltstack wraparound 2008-01-30 13:30:06 +01:00
lguest lguest: prevent VISWS or VOYAGER randconfigs 2007-11-29 09:24:55 -08:00
lib x86: disable preemption in delay_tsc() 2007-11-14 18:45:44 -08:00
mach-default spelling fixes: arch/i386/ 2007-10-20 01:13:56 +02:00
mach-es7000 i386: es7000 minor cleanups 2007-10-17 20:16:15 +02:00
mach-generic spelling fixes: arch/i386/ 2007-10-20 01:13:56 +02:00
mach-visws [x86] remove uses of magic macros for boot_params access 2007-10-16 17:38:31 -07:00
mach-voyager x86: fix smp init sections 2007-11-17 16:27:00 +01:00
math-emu kbuild: fix up CFLAGS usage 2007-10-14 21:49:42 +02:00
mm x86: fix boot crash on HIGHMEM4G && SPARSEMEM 2008-01-15 16:44:37 +01:00
oprofile Driver core: change sysdev classes to use dynamic kobject names 2008-01-24 20:40:40 -08:00
pci Merge git://git.kernel.org/pub/scm/linux/kernel/git/x86/linux-2.6-x86 2007-11-26 19:41:28 -08:00
power i386: move power 2007-10-11 11:16:34 +02:00
vdso x86: ignore the sys_getcpu() tcache parameter 2007-11-17 16:27:00 +01:00
video i386: move video 2007-10-11 11:16:56 +02:00
xen xen: disable vcpu_info placement for now 2008-01-23 18:04:54 -08:00
Kconfig Tiny clean-up of OPROFILE/KPROBES configuration 2007-12-06 09:41:12 -08:00
Kconfig.cpu x86: arch/x86/Kconfig.cpu unification 2007-11-12 21:02:19 +01:00
Kconfig.debug x86: make io_delay=0xed the default 2008-01-30 13:30:05 +01:00
Makefile x86: correctly set UTS_MACHINE for "make ARCH=x86" 2007-11-26 17:38:53 -08:00
Makefile_32 x86: fix make mrproper 2008-01-30 13:30:04 +01:00
Makefile_32.cpu x86: move i386 and x86_64 Makefiles to arch/x86 2007-10-25 22:27:34 +02:00
Makefile_64 x86: fix make mrproper 2008-01-30 13:30:04 +01:00