diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2015-07-01 15:28:16 +0200 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2015-07-01 15:28:16 +0200 |
commit | e3d345c5c39c79db00c8601682ed6fe35d8953c8 (patch) | |
tree | c3e1a4e9320248a551ba3c51ed54449d210e1884 | |
parent | 0f3e6315712428fcbfc0b6ffeec7c850d9b7206a (diff) | |
download | cygnal-e3d345c5c39c79db00c8601682ed6fe35d8953c8.tar.gz cygnal-e3d345c5c39c79db00c8601682ed6fe35d8953c8.tar.bz2 cygnal-e3d345c5c39c79db00c8601682ed6fe35d8953c8.zip |
Fix fork after recovered stack overflow
* fork.cc (frok::parent): Set stacktop value based on requested stack
pointer value in child. Explain why.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
-rw-r--r-- | winsup/cygwin/ChangeLog | 5 | ||||
-rw-r--r-- | winsup/cygwin/fork.cc | 16 |
2 files changed, 19 insertions, 2 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 01bb3eb68..eaa62a086 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,8 @@ +2015-07-01 Corinna Vinschen <corinna@vinschen.de> + + * fork.cc (frok::parent): Set stacktop value based on requested stack + pointer value in child. Explain why. + 2015-06-30 Corinna Vinschen <corinna@vinschen.de> * signal.cc (sigaltstack): Add comment. diff --git a/winsup/cygwin/fork.cc b/winsup/cygwin/fork.cc index faccb482c..951c7fd58 100644 --- a/winsup/cygwin/fork.cc +++ b/winsup/cygwin/fork.cc @@ -308,9 +308,21 @@ frok::parent (volatile char * volatile stack_here) ch.forker_finished = forker_finished; PTEB teb = NtCurrentTeb (); - ch.stackbottom = _tlsbase; - ch.stacktop = (void *) _tlstop; ch.stackaddr = teb->DeallocationStack; + ch.stackbottom = _tlsbase; + /* If DeallocationStack is NULL, we're running on an application-provided + stack. If so, the entire stack is committed anyway and StackLimit points + to the allocation address of the stack. Otherwise we're running on a + system-allocated stack and using StackLimit is dangerous, in case the + application encountered a stack overflow and recovered from it via + a signal handler running on an alternate stack. Since stack_here is + the address of the stack pointer we start the child with anyway, we + can set ch.stacktop to this value rounded down to page size. The + child will not need the rest of the stack anyway. */ + if (!ch.stackaddr) + ch.stacktop = _tlstop; + else + ch.stacktop = (void *) ((uintptr_t) stack_here & ~wincap.page_size ()); ch.guardsize = 0; if (&_my_tls != _main_tls) { |