summaryrefslogtreecommitdiff
path: root/libpthread/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
diff options
context:
space:
mode:
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.c44
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