aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libc/bionic/pthread_create.cpp17
-rw-r--r--libc/bionic/pthread_exit.cpp2
-rw-r--r--libc/bionic/pthread_internal.h3
3 files changed, 16 insertions, 6 deletions
diff --git a/libc/bionic/pthread_create.cpp b/libc/bionic/pthread_create.cpp
index 66632c494..dbdb18058 100644
--- a/libc/bionic/pthread_create.cpp
+++ b/libc/bionic/pthread_create.cpp
@@ -69,13 +69,20 @@ void __init_tls(pthread_internal_t* thread) {
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 1de85f510..ceda93166 100644
--- a/libc/bionic/pthread_exit.cpp
+++ b/libc/bionic/pthread_exit.cpp
@@ -87,7 +87,7 @@ void pthread_exit(void* return_value) {
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 2151e03ed..3b91e6a19 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -130,6 +130,9 @@ __LIBC_HIDDEN__ void pthread_key_clean_all(void);
*/
#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();