diff options
author | kib <kib@FreeBSD.org> | 2011-01-09 12:38:40 +0000 |
---|---|---|
committer | kib <kib@FreeBSD.org> | 2011-01-09 12:38:40 +0000 |
commit | b2e3ee7d07d38a011d50e0ce65fe146aafb5c939 (patch) | |
tree | 3e9a8bc61608f36b6d941a6fe4ca52880cc1c222 /lib/libthr/thread/thr_stack.c | |
parent | 13fb4c75946c522dc61a068915f8ebe021d256c7 (diff) | |
download | FreeBSD-src-b2e3ee7d07d38a011d50e0ce65fe146aafb5c939.zip FreeBSD-src-b2e3ee7d07d38a011d50e0ce65fe146aafb5c939.tar.gz |
Implement the __pthread_map_stacks_exec() for libthr.
Stack creation code is changed to call _rtld_get_stack_prot() to get
the stack protection right. There is a race where thread is created
during dlopen() of dso that requires executable stacks. Then,
_rtld_get_stack_prot() may return PROT_READ | PROT_WRITE, but thread
is still not linked into the thread list. In this case, the callback
misses the thread stack, and rechecks the required protection
afterward.
Reviewed by: davidxu
Diffstat (limited to 'lib/libthr/thread/thr_stack.c')
-rw-r--r-- | lib/libthr/thread/thr_stack.c | 35 |
1 files changed, 34 insertions, 1 deletions
diff --git a/lib/libthr/thread/thr_stack.c b/lib/libthr/thread/thr_stack.c index 7684953..cb390cc 100644 --- a/lib/libthr/thread/thr_stack.c +++ b/lib/libthr/thread/thr_stack.c @@ -32,6 +32,7 @@ #include <sys/queue.h> #include <stdlib.h> #include <pthread.h> +#include <link.h> #include "thr_private.h" @@ -128,6 +129,38 @@ round_up(size_t size) return size; } +void +_thr_stack_fix_protection(struct pthread *thrd) +{ + + mprotect((char *)thrd->attr.stackaddr_attr + + round_up(thrd->attr.guardsize_attr), + round_up(thrd->attr.stacksize_attr), + _rtld_get_stack_prot()); +} + +void __pthread_map_stacks_exec(void); +void +__pthread_map_stacks_exec(void) +{ + struct pthread *curthread, *thrd; + struct stack *st; + + curthread = _get_curthread(); + THREAD_LIST_RDLOCK(curthread); + LIST_FOREACH(st, &mstackq, qe) + mprotect((char *)st->stackaddr + st->guardsize, st->stacksize, + _rtld_get_stack_prot()); + LIST_FOREACH(st, &dstackq, qe) + mprotect((char *)st->stackaddr + st->guardsize, st->stacksize, + _rtld_get_stack_prot()); + TAILQ_FOREACH(thrd, &_thread_gc_list, gcle) + _thr_stack_fix_protection(thrd); + TAILQ_FOREACH(thrd, &_thread_list, tle) + _thr_stack_fix_protection(thrd); + THREAD_LIST_UNLOCK(curthread); +} + int _thr_stack_alloc(struct pthread_attr *attr) { @@ -210,7 +243,7 @@ _thr_stack_alloc(struct pthread_attr *attr) /* Map the stack and guard page together, and split guard page from allocated space: */ if ((stackaddr = mmap(stackaddr, stacksize+guardsize, - PROT_READ | PROT_WRITE, MAP_STACK, + _rtld_get_stack_prot(), MAP_STACK, -1, 0)) != MAP_FAILED && (guardsize == 0 || mprotect(stackaddr, guardsize, PROT_NONE) == 0)) { |