[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: determining the stack bounds
From: |
Eric Blake |
Subject: |
Re: determining the stack bounds |
Date: |
Fri, 6 Jun 2008 03:49:18 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Bruno Haible <bruno <at> clisp.org> writes:
>
> Eric Blake wrote:
> > user_context->uc_stack.ss_sp contains the location
> > of the currently running (alternate) stack, not the stack where the fault
> > occurred. ... find out where the _original_ stack ended
I'm not sure if it is a bug or intentional that Linux sets ucontext_t.uc_link
to NULL in the alternate stack. But in POSIX 2001, getcontext() states that
when uc_link is NULL, the thread must exit when the context returns; and in the
case of a sigsegv stack-overflow handler, returning from the signal (rather
than longjmp'ing) is undefined behavior (besides, if you COULD return normally,
you would just reprovoke the stack overflow). What's worse, POSIX 200x is
withdrawing <ucontext.h> (its types should now reside in <signal.h>), as well
as removing requirements for getcontext() and friends, so trying to rely on
getcontext is a losing battle.
On the other hand, POSIX states for sigaction() that the handler's "third
argument can be cast to a pointer to an object of type ucontext_t to refer to
the receiving thread’s context that was interrupted when the signal was
delivered." The receiving thread may currently be in the alternate stack, but
the signal was delivered when the thread was still in the primary stack. So
maybe we should file this as a bug with the kernel folks, and hope that a
future version of Linux change uc_stack to supply the information we want.
After all, we don't need uc_stack to learn about the current (alternate) stack;
we can use sigaltstack() for that.
> File platforms uses
>
> stackvma-linux.c Linux /proc/self/maps, mincore()
> stackvma-freebsd.c FreeBSD /proc/curproc/map, mincore()
> stackvma-mincore.c OpenBSD, NetBSD mincore()
> stackvma-mach.c MacOS X vm_region()
> stackvma-procfs.c IRIX, OSF/1, Solaris ioctl(PIOCMAP)
> stackvma-beos.c BeOS get_next_area_info()
Cygwin provides /proc/self/maps (but not yet mincore()). Plus, you can
probably exploit the Windows API for both mingw and cygwin (perhaps in the same
way that cygwin implements /proc/self/maps).
>
> Would help to move this code to gnulib? Are there other uses of the stack VMA?
Perhaps so. At any rate, the current implementation of c-stack precludes any
detection of non-stack overflow segv's on Linux (at least for the kernel
versions I was testing), because it claims ALL segvs are stack overflow,
whether or not that is true. I don't know if any of the other OS's that
support sigaltstack and ucontext_t and which do better at providing info about
the main stack. M4 has a slightly better approach - when registering the
overflow handler, probe the current stack location and getrlimit for the
maximum stack size, then on fault, see if the fault lies near the pre-computed
stack limit. It gets tricky on architectures with limited memory where stack
and heap can collide, but these days, 16-bit memory spaces are not gnulib's
primary porting target, and most OSs enforce large gaps between the virtual
address ranges assigned to stack vs. heap.
But m4's approach isn't quite right, either - on Linux, the current stack
location + getrlimit information when the overflow handler is registered fails
to account for stack previously occupied prior to calling the handler, and
fails to account for the fact that the size of the memory mapped to the stack
at the time of registration is different than the size of the map at the time
of the fault. Thus, the handler often thinks that the faulting address falls
outside the window it computed as the potential end of stack at registration
time.
> (Conservative garbage-collectors and Scheme interpreters only need to know
> the current stack pointer and the stack top, AFAIK, not the stack bottom.)
Just so I'm clear: By stack top, you mean the area reserved by main(), and by
stack bottom, you mean the area near where the fault points on a stack overflow?
When sigaction works, c-stack already has access to the faulting address and
the stack direction. If we assume the fault was due to stack overflow, then we
should also be able to assume that an address from the next page over, going
the opposite direction from stack growth, is mapped, along with all other
addresses in the primary stack. So c-stack could use a mincore()-like
capability to quickly determine whether all memory from the page near the fault
over to the stack location saved at the time the handler was registered is
currently mapped (whether or not all of those pages are in core) (and
using /proc/self/maps when that is faster than mincore()).
--
Eric Blake
- c-stack vs. older platforms, Eric Blake, 2008/06/05
- Re: c-stack vs. older platforms, Paul Eggert, 2008/06/05
- Re: c-stack vs. older platforms, Bruno Haible, 2008/06/05
- Re: c-stack vs. older platforms, Eric Blake, 2008/06/05
- Re: c-stack vs. older platforms, Eric Blake, 2008/06/05
- Re: determining the stack bounds, Bruno Haible, 2008/06/05
- Re: determining the stack bounds,
Eric Blake <=
- Re: determining the stack bounds, Bruno Haible, 2008/06/06
- Re: determining the stack bounds, Eric Blake, 2008/06/06
- Re: determining the stack bounds, Eric Blake, 2008/06/06
- Re: determining the stack bounds, Eric Blake, 2008/06/06
- Re: determining the stack bounds, Bruno Haible, 2008/06/06
- Re: c-stack vs. older platforms, Eric Blake, 2008/06/06