Revert "Revert "add guard pages to the internal signal stacks""

This reverts commit a3125fd1396a09a7fc4872dc4653f342150a3deb.
And Fix the prctl() problem that cause system crash.

Change-Id: Icc8d12d848cfba881a7984ca2827fd81be41f9fd
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 66632c4..dbdb180 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -69,13 +69,20 @@
 
 void __init_alternate_signal_stack(pthread_internal_t* thread) {
   // Create and set an alternate signal stack.
-  stack_t ss;
-  ss.ss_sp = mmap(NULL, SIGSTKSZ, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
-  if (ss.ss_sp != MAP_FAILED) {
-    ss.ss_size = SIGSTKSZ;
+  void* stack_base = mmap(NULL, SIGNAL_STACK_SIZE, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0);
+  if (stack_base != MAP_FAILED) {
+
+    // Create a guard page to catch stack overflows in signal handlers.
+    if (mprotect(stack_base, PAGE_SIZE, PROT_NONE) == -1) {
+      munmap(stack_base, SIGNAL_STACK_SIZE);
+      return;
+    }
+    stack_t ss;
+    ss.ss_sp = reinterpret_cast<uint8_t*>(stack_base) + PAGE_SIZE;
+    ss.ss_size = SIGNAL_STACK_SIZE - PAGE_SIZE;
     ss.ss_flags = 0;
     sigaltstack(&ss, NULL);
-    thread->alternate_signal_stack = ss.ss_sp;
+    thread->alternate_signal_stack = stack_base;
 
     // We can only use const static allocated string for mapped region name, as Android kernel
     // uses the string pointer directly when dumping /proc/pid/maps.
diff --git a/libc/bionic/pthread_exit.cpp b/libc/bionic/pthread_exit.cpp
index 1de85f5..ceda931 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -87,7 +87,7 @@
     sigaltstack(&ss, NULL);
 
     // Free it.
-    munmap(thread->alternate_signal_stack, SIGSTKSZ);
+    munmap(thread->alternate_signal_stack, SIGNAL_STACK_SIZE);
     thread->alternate_signal_stack = NULL;
   }
 
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index 2151e03..3b91e6a 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -130,6 +130,9 @@
  */
 #define PTHREAD_STACK_SIZE_DEFAULT ((1 * 1024 * 1024) - SIGSTKSZ)
 
+/* Leave room for a guard page in the internally created signal stacks. */
+#define SIGNAL_STACK_SIZE (SIGSTKSZ + PAGE_SIZE)
+
 /* Needed by fork. */
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_prepare();
 __LIBC_HIDDEN__ extern void __bionic_atfork_run_child();