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_create.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_create.c')
-rw-r--r-- | lib/libthr/thread/thr_create.c | 11 |
1 files changed, 11 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_create.c b/lib/libthr/thread/thr_create.c index f0af20b..a41b33f 100644 --- a/lib/libthr/thread/thr_create.c +++ b/lib/libthr/thread/thr_create.c @@ -32,6 +32,7 @@ #include <sys/rtprio.h> #include <sys/signalvar.h> #include <errno.h> +#include <link.h> #include <stdlib.h> #include <string.h> #include <stddef.h> @@ -58,6 +59,7 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, sigset_t set, oset; cpuset_t *cpusetp = NULL; int cpusetsize = 0; + int old_stack_prot; _thr_check_init(); @@ -96,6 +98,7 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, new_thread->tid = TID_TERMINATED; + old_stack_prot = _rtld_get_stack_prot(); if (create_stack(&new_thread->attr) != 0) { /* Insufficient memory to create a stack: */ _thr_free(curthread, new_thread); @@ -130,6 +133,14 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr, /* Add the new thread. */ new_thread->refcount = 1; _thr_link(curthread, new_thread); + + /* + * Handle the race between __pthread_map_stacks_exec and + * thread linkage. + */ + if (old_stack_prot != _rtld_get_stack_prot()) + _thr_stack_fix_protection(new_thread); + /* Return thread pointer eariler so that new thread can use it. */ (*thread) = new_thread; if (SHOULD_REPORT_EVENT(curthread, TD_CREATE) || cpusetp != NULL) { |