bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: determining the stack bounds


From: Bruno Haible
Subject: Re: determining the stack bounds
Date: Fri, 6 Jun 2008 13:29:55 +0200
User-agent: KMail/1.5.4

Eric Blake wrote:
> 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 type of the third argument, according to POSIX, is 'void *ucp'. Why does
it have to be cast? Why is it not directly 'ucontext_t *ucp' (since, as you
say, ucontext_t will be defined in <signal.h>)?

> 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.

I think you are misunderstanding things, and there is no Linux kernel bug here.
When a signal S has been specified to execute on the alternate stack (via
SA_ONSTACK), and SA_NODEFER is specified as well, when the signal S occurs a
second time while the first signal occurrence is still being processed,
the stack pointer cannot be set to the top of the alternating stack again -
this room is already in use. So the second time the signal handling must
behave as if there was no alternate stack. This is a semantic difference
between the "context" of the main thread (where alternate signal stacks will
be used when a signal occurs) and the "context" of signal handler (where
alternate signal stacks will be ignored). This is why ucontext_t has a
field 'uc_stack'.

Whether sigaltstack(), when called during the signal handler, reports the
existence of an alternate stack or not, is irrelevant. What matters, is the
actual behaviour when a nested signal occurs.

Some systems (OpenBSD, IRIX, Solaris) store the fact that the alternate stack
is temporarily deactivated as a bit in the kernel. Others (Linux, MacOS X)
determine it by looking whether the current stack pointer is in the range
of the alternate stack.

The description of 'uc_stack' in 
http://www.opengroup.org/susv3/basedefs/ucontext.h.html
is so vague that I would not base any program on it.

> >   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).

You're right. Yes, in Cygwin and mingw, you can best use the Win32 
VirtualQuery()
API.

> 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.

Yes. Distinguishing between random SIGSEGV and stack overflow is a feature that
IMO is unique to libsigsegv.

> 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

Indeed. This area contains the command-line, the environment and - on HP-UX -
also the shared libraries, and can therefore be quite large.

Also, on IA64 processors, the hardware has two stack pointers which grow
into opposite directions, from the start and the end of the assigned stack
area. A stack overflow occurs when the two pointers cross - and at that time
they are both far away from the point that you computed with getrlimit().

> 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?

Yes. Nowadays the stack grows down on all CPUs except HPPA.

> 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()).

I agree with you that c-stack's use of 'uc_stack' is bogus, and on Linux,
FreeBSD, OpenBSD, NetBSD, mincore() will give better results.

Bruno





reply via email to

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