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 trigge...
On Mon, 26 Nov 2007 19:02:22 -0800 (PST)
we probably should also make sure userspace has at least a little bit
of stack space for itself, say 2Kb or 4Kb, not just "the kernel puts
you right at the edge"....--
If you want to reach me at my work email, use arjan@linux.intel.com
For development, discussion and tips for power savings,
visit http://www.lesswatts.org
-
* Roland McGrath <roland@redhat.com> wrote:
thanks Roland for the detailed analysis. I've queued up the patch below
in the x86 tree. I suspect we can wait with this for v2.6.25, due to
this being long-standing behavior of Linux? Thus we could observe the
effects of this patch for a longer time.I'm wondering how widespread sigaltstack use is in general. Googling
around gives:http://google.com/codesearch?q=sigaltstack
~400 matches. A more common signal API in comparison:
http://google.com/codesearch?q=sigaction
gives ~139,000 matches. So i guess the right approach would be to also
extend LTP's sigaltstack tests to cover whatever new desired behavior -
so that we at least have a minimal chance of catching obvious breakages
here.Ingo
--------------->
Subject: x86: protect against sigaltstack wraparound
From: Roland McGrath <roland@redhat.com>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...
It's certainly nothing new. The failure mode of concern is only for a
buggy program to fail to crash as quickly and gracefully as it might.Thanks,
Roland
-
| Andy Whitcroft | clam |
| Tarkan Erimer | Re: Dual-Licensing Linux Kernel with GPL V2 and GPL V3 |
| Greg Kroah-Hartman | [PATCH 001/196] Chinese: Add the known_regression URI to the HOWTO |
| David Miller | Re: Slow DOWN, please!!! |
git: | |
| Arjan van de Ven | Re: [GIT]: Networking |
| Lennert Buytenhek | [PATCH 08/39] mv643xx_eth: nuke port status register bit defines |
| Jarek Poplawski | Re: HTB accuracy for high speed |
| Jarek Poplawski | [PATCH] pkt_sched: Destroy gen estimators under rtnl_lock(). |
