bug-gnulib
[Top][All Lists]
Advanced

[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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]