From e480fc83b2887388d469eb3bf58c86c610f5b082 Mon Sep 17 00:00:00 2001 From: Jack Ren Date: Wed, 21 Sep 2011 12:44:11 +0200 Subject: [PATCH] bionic: fix pthread_{create, exit}/signal race condition (1) in pthread_create: If the one signal is received before esp is subtracted by 16 and __thread_entry( ) is called, the stack will be cleared by kernel when it tries to contruct the signal stack frame. That will cause that __thread_entry will get a wrong tls pointer from the stack which leads to the segment fault when trying to access tls content. (2) in pthread_exit After pthread_exit called system call unmap(), its stack will be freed. If one signal is received at that time, there is no stack available for it. Fixed by subtracting the child's esp by 16 before the clone system call and by blocking signal handling before pthread_exit is started. Author: Jack Ren Signed-off-by: Bruce Beare --- libc/arch-x86/bionic/clone.S | 2 +- libc/bionic/pthread.c | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libc/arch-x86/bionic/clone.S b/libc/arch-x86/bionic/clone.S index b9b0957f6..8abb7c84e 100644 --- a/libc/arch-x86/bionic/clone.S +++ b/libc/arch-x86/bionic/clone.S @@ -22,6 +22,7 @@ __pthread_clone: movl %eax, -8(%ecx) movl %ecx, -4(%ecx) + subl $16, %ecx movl $__NR_clone, %eax int $0x80 test %eax, %eax @@ -39,7 +40,6 @@ __pthread_clone: # we're in the child thread now, call __thread_entry # with the appropriate arguments on the child stack # we already placed most of them - subl $16, %esp jmp __thread_entry hlt diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c index 1da2ec9c5..e8f1052f2 100644 --- a/libc/bionic/pthread.c +++ b/libc/bionic/pthread.c @@ -571,6 +571,7 @@ void pthread_exit(void * retval) void* stack_base = thread->attr.stack_base; int stack_size = thread->attr.stack_size; int user_stack = (thread->attr.flags & PTHREAD_ATTR_FLAG_USER_STACK) != 0; + sigset_t mask; // call the cleanup handlers first while (thread->cleanup_stack) { @@ -613,6 +614,10 @@ void pthread_exit(void * retval) pthread_mutex_unlock(&gThreadListLock); } + sigfillset(&mask); + sigdelset(&mask, SIGSEGV); + (void)sigprocmask(SIG_SETMASK, &mask, (sigset_t *)NULL); + // destroy the thread stack if (user_stack) _exit_thread((int)retval); -- 2.11.0