From owner-svn-src-all@FreeBSD.ORG Sun Jan 9 12:38:40 2011 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id EBBBF1065672; Sun, 9 Jan 2011 12:38:40 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id DAB888FC18; Sun, 9 Jan 2011 12:38:40 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id p09Cce2t042908; Sun, 9 Jan 2011 12:38:40 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id p09CceMj042902; Sun, 9 Jan 2011 12:38:40 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <201101091238.p09CceMj042902@svn.freebsd.org> From: Konstantin Belousov Date: Sun, 9 Jan 2011 12:38:40 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r217191 - in head/lib/libthr: . thread X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 Jan 2011 12:38:41 -0000 Author: kib Date: Sun Jan 9 12:38:40 2011 New Revision: 217191 URL: http://svn.freebsd.org/changeset/base/217191 Log: 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 Modified: head/lib/libthr/pthread.map head/lib/libthr/thread/thr_create.c head/lib/libthr/thread/thr_private.h head/lib/libthr/thread/thr_rtld.c head/lib/libthr/thread/thr_stack.c Modified: head/lib/libthr/pthread.map ============================================================================== --- head/lib/libthr/pthread.map Sun Jan 9 11:52:23 2011 (r217190) +++ head/lib/libthr/pthread.map Sun Jan 9 12:38:40 2011 (r217191) @@ -382,6 +382,8 @@ FBSDprivate_1.0 { _thread_size_key; _thread_state_running; _thread_state_zoombie; + + __pthread_map_stacks_exec; }; FBSD_1.1 { Modified: head/lib/libthr/thread/thr_create.c ============================================================================== --- head/lib/libthr/thread/thr_create.c Sun Jan 9 11:52:23 2011 (r217190) +++ head/lib/libthr/thread/thr_create.c Sun Jan 9 12:38:40 2011 (r217191) @@ -32,6 +32,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,7 @@ _pthread_create(pthread_t * thread, cons 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, cons 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, cons /* 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) { Modified: head/lib/libthr/thread/thr_private.h ============================================================================== --- head/lib/libthr/thread/thr_private.h Sun Jan 9 11:52:23 2011 (r217190) +++ head/lib/libthr/thread/thr_private.h Sun Jan 9 12:38:40 2011 (r217191) @@ -898,6 +898,7 @@ struct dl_phdr_info; void __pthread_cxa_finalize(struct dl_phdr_info *phdr_info); void _thr_tsd_unload(struct dl_phdr_info *phdr_info) __hidden; void _thr_sigact_unload(struct dl_phdr_info *phdr_info) __hidden; +void _thr_stack_fix_protection(struct pthread *thrd); __END_DECLS Modified: head/lib/libthr/thread/thr_rtld.c ============================================================================== --- head/lib/libthr/thread/thr_rtld.c Sun Jan 9 11:52:23 2011 (r217190) +++ head/lib/libthr/thread/thr_rtld.c Sun Jan 9 12:38:40 2011 (r217191) @@ -31,6 +31,8 @@ * A lockless rwlock for rtld. */ #include +#include +#include #include #include @@ -194,6 +196,9 @@ _thr_rtld_init(void) /* force to resolve memcpy PLT */ memcpy(&dummy, &dummy, sizeof(dummy)); + mprotect(NULL, 0, 0); + _rtld_get_stack_prot(); + li.lock_create = _thr_rtld_lock_create; li.lock_destroy = _thr_rtld_lock_destroy; li.rlock_acquire = _thr_rtld_rlock_acquire; Modified: head/lib/libthr/thread/thr_stack.c ============================================================================== --- head/lib/libthr/thread/thr_stack.c Sun Jan 9 11:52:23 2011 (r217190) +++ head/lib/libthr/thread/thr_stack.c Sun Jan 9 12:38:40 2011 (r217191) @@ -32,6 +32,7 @@ #include #include #include +#include #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 *at /* 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)) {