]> sourceware.org Git - newlib-cygwin.git/commitdiff
Fix fork after recovered stack overflow
authorCorinna Vinschen <corinna@vinschen.de>
Wed, 1 Jul 2015 13:28:16 +0000 (15:28 +0200)
committerCorinna Vinschen <corinna@vinschen.de>
Wed, 1 Jul 2015 13:28:16 +0000 (15:28 +0200)
* 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>
winsup/cygwin/ChangeLog
winsup/cygwin/fork.cc

index 01bb3eb68fa03bffadf1cf982a03c778a49a1618..eaa62a086534f6a443fbfcdbb1ed73b93124ab0f 100644 (file)
@@ -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.
index faccb482ce567a23103d07f27acc07695cf46a4d..951c7fd5894ad9cd5387da6c84ddabfd9658c060 100644 (file)
@@ -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)
     {
This page took 0.0343 seconds and 5 git commands to generate.