Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-07-01 16:28:16 +0300
committerCorinna Vinschen <corinna@vinschen.de>2015-07-01 16:28:16 +0300
commite3d345c5c39c79db00c8601682ed6fe35d8953c8 (patch)
treec3e1a4e9320248a551ba3c51ed54449d210e1884
parent0f3e6315712428fcbfc0b6ffeec7c850d9b7206a (diff)
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/ChangeLog5
-rw-r--r--winsup/cygwin/fork.cc16
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)
{