diff options
Diffstat (limited to 'libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c')
-rw-r--r-- | libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c | 44 |
1 files changed, 36 insertions, 8 deletions
diff --git a/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c index 4ad252800..016437768 100644 --- a/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c +++ b/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2002, 2003 Free Software Foundation, Inc. +/* Copyright (C) 2002,2003,2005,2006,2007,2009 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@redhat.com>, 2002. @@ -19,13 +19,15 @@ #include <unistd.h> #include <list.h> -#include "fork.h" +#include <fork.h> +#include <dl-sysdep.h> #include <tls.h> #include <string.h> #include <pthreadP.h> #include <bits/libc-lock.h> +#include <sysdep.h> +#include <ldsodefs.h> -libc_hidden_proto(memcpy) #ifdef TLS_MULTIPLE_THREADS_IN_TCB void @@ -46,14 +48,40 @@ __libc_pthread_init ( __register_atfork (NULL, NULL, reclaim, NULL); #ifdef SHARED - /* We copy the content of the variable pointed to by the FUNCTIONS - parameter to one in libc.so since this means access to the array - can be done with one memory access instead of two. */ - memcpy (&__libc_pthread_functions, functions, - sizeof (__libc_pthread_functions)); + /* Copy the function pointers into an array in libc. This enables + access with just one memory reference but moreso, it prevents + hijacking the function pointers with just one pointer change. We + "encrypt" the function pointers since we cannot write-protect the + array easily enough. */ + union ptrhack + { + struct pthread_functions pf; +# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *)) + void *parr[NPTRS]; + } __attribute__ ((may_alias)) const *src; + union ptrhack *dest; + + src = (const void *) functions; + dest = (void *) &__libc_pthread_functions; + + for (size_t cnt = 0; cnt < NPTRS; ++cnt) + { + void *p = src->parr[cnt]; + PTR_MANGLE (p); + dest->parr[cnt] = p; + } + __libc_pthread_functions_init = 1; #endif #ifndef TLS_MULTIPLE_THREADS_IN_TCB return &__libc_multiple_threads; #endif } + +#ifdef SHARED +libc_freeres_fn (freeres_libptread) +{ + if (__libc_pthread_functions_init) + PTHFCT_CALL (ptr_freeres, ()); +} +#endif |