Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/lib/libpthread I've had this patch in my tree for a while an...



details:   https://anonhg.NetBSD.org/src/rev/97010c412d40
branches:  trunk
changeset: 759872:97010c412d40
user:      christos <christos%NetBSD.org@localhost>
date:      Sat Dec 18 15:54:27 2010 +0000

description:
I've had this patch in my tree for a while and since it only improves
the situation, I decided to commit it. There is an inherent problem
with ASLR and the way the pthread library is using the thread stack.

Our pthread library chooses that stack for each thread strategically
so that it can locate the location of the pthread struct for each
thread by masking the stack pointer and looking just below the red
zone it creates. Unfortunately with ASLR you get many random values
for the initial stack, and there are situations where the masked
stack base ends up below the base of the stack. (this happens on
x86 when the stack base happens to be 0x???02000 for example and
your mask is stackmask is 0xffe00000). To fix this, we detect the
pathological cases (this happens only in the main thread), allocate
more stack, and mprotect it appropriately. Then we stash the main
base and the main struct, so that when we look for the pthread
struct in pthread__id, we can special case the main thread.

Another way to work around the problem is unlimiting stacksize,
but the proper way is to use TLS to find the thread structure and
not to play games with the thread stacks.

diffstat:

 lib/libpthread/pthread.c     |  14 +++++++++++---
 lib/libpthread/pthread_int.h |  13 +++++++++----
 2 files changed, 20 insertions(+), 7 deletions(-)

diffs (81 lines):

diff -r 7adcfcf68225 -r 97010c412d40 lib/libpthread/pthread.c
--- a/lib/libpthread/pthread.c  Sat Dec 18 15:02:06 2010 +0000
+++ b/lib/libpthread/pthread.c  Sat Dec 18 15:54:27 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pthread.c,v 1.117 2010/11/14 22:25:23 tron Exp $       */
+/*     $NetBSD: pthread.c,v 1.118 2010/12/18 15:54:27 christos Exp $   */
 
 /*-
  * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__RCSID("$NetBSD: pthread.c,v 1.117 2010/11/14 22:25:23 tron Exp $");
+__RCSID("$NetBSD: pthread.c,v 1.118 2010/12/18 15:54:27 christos Exp $");
 
 #define        __EXPOSE_STACK  1
 
@@ -108,6 +108,8 @@
 size_t pthread__stacksize = 1 << _STACKSIZE_LG;
 vaddr_t        pthread__stackmask = (1 << _STACKSIZE_LG) - 1;
 vaddr_t pthread__threadmask = (vaddr_t)~((1 << _STACKSIZE_LG) - 1);
+vaddr_t        pthread__mainbase = 0;
+vaddr_t        pthread__mainstruct = 0;
 #undef _STACKSIZE_LG
 
 int _sys___sigprocmask14(int, const sigset_t *, sigset_t *);
@@ -1221,7 +1223,14 @@
        pthread__threadmask = ~pthread__stackmask;
 
        base = (void *)(pthread__sp() & pthread__threadmask);
+       if ((pthread__sp() - (uintptr_t)base) < 4 * pagesize) {
+               pthread__mainbase = (vaddr_t)base;
+               base = STACK_GROW(base, pthread__stacksize);
+               pthread__mainstruct = (vaddr_t)base;
+       }
        size = pthread__stacksize;
+       if (mprotect(base, size, PROT_READ|PROT_WRITE) == -1)
+               err(1, "mprotect stack");
 
        error = pthread__stackid_setup(base, size, &t);
        if (error) {
@@ -1258,7 +1267,6 @@
 #else
        t->pt_stack.ss_sp = (char *)(void *)base + 2 * pagesize;
 #endif
-
        /* Protect the next-to-bottom stack page as a red zone. */
        ret = mprotect(redaddr, pagesize, PROT_NONE);
        if (ret == -1) {
diff -r 7adcfcf68225 -r 97010c412d40 lib/libpthread/pthread_int.h
--- a/lib/libpthread/pthread_int.h      Sat Dec 18 15:02:06 2010 +0000
+++ b/lib/libpthread/pthread_int.h      Sat Dec 18 15:54:27 2010 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pthread_int.h,v 1.72 2009/05/17 14:49:00 ad Exp $      */
+/*     $NetBSD: pthread_int.h,v 1.73 2010/12/18 15:54:27 christos Exp $        */
 
 /*-
  * Copyright (c) 2001, 2002, 2003, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -249,13 +249,18 @@
        _INITCONTEXT_U_MD(ucp)                                          \
        } while (/*CONSTCOND*/0)
 
-/* Stack location of pointer to a particular thread */
-#define pthread__id(sp) \
-       ((pthread_t) (((vaddr_t)(sp)) & pthread__threadmask))
 
 #ifdef PTHREAD__HAVE_THREADREG
 #define        pthread__self()         pthread__threadreg_get()
 #else
+/* Stack location of pointer to a particular thread */
+extern vaddr_t pthread__mainbase;
+extern vaddr_t pthread__mainstruct;
+static inline pthread_t
+pthread__id(vaddr_t sp) {
+       vaddr_t va = sp & pthread__threadmask;
+       return (pthread_t)(va == pthread__mainbase ? pthread__mainstruct : va);
+}
 #define pthread__self()        (pthread__id(pthread__sp()))
 #endif
 



Home | Main Index | Thread Index | Old Index