summaryrefslogtreecommitdiff
path: root/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c')
-rw-r--r--nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
index 714ad49428..92a188a2f3 100644
--- a/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
+++ b/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2002, 2003, 2005, 2006 Free Software Foundation, Inc.
+/* Copyright (C) 2002, 2003, 2005, 2006, 2007 Free Software Foundation, Inc.
This file is part of the GNU C Library.
Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
@@ -25,6 +25,7 @@
#include <string.h>
#include <pthreadP.h>
#include <bits/libc-lock.h>
+#include <sysdep.h>
#ifdef TLS_MULTIPLE_THREADS_IN_TCB
@@ -46,11 +47,29 @@ __libc_pthread_init (ptr, reclaim, functions)
__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;
+ void *parr[1];
+ } const *src;
+ union ptrhack *dest;
+# define NPTRS (sizeof (struct pthread_functions) / sizeof (void *))
+
+ 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
@@ -61,7 +80,7 @@ __libc_pthread_init (ptr, reclaim, functions)
#ifdef SHARED
libc_freeres_fn (freeres_libptread)
{
- if (__libc_pthread_functions.ptr_freeres != NULL)
- __libc_pthread_functions.ptr_freeres ();
+ if (__libc_pthread_functions_init)
+ PTHFCT_CALL (ptr_freeres, ());
}
#endif