about summary refs log tree commit diff
path: root/nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2007-01-17 08:37:26 +0000
committerUlrich Drepper <drepper@redhat.com>2007-01-17 08:37:26 +0000
commitea1533e08df4c63e680438ac1dc243cdc37d205a (patch)
treed7954d886b979b8bea1d7e1f6db05b440a693097 /nptl/sysdeps/unix/sysv/linux/libc_pthread_init.c
parentd78bce1c01fe67d02d833e026e5acbb88d1d9836 (diff)
downloadglibc-ea1533e08df4c63e680438ac1dc243cdc37d205a.tar.gz
glibc-ea1533e08df4c63e680438ac1dc243cdc37d205a.tar.xz
glibc-ea1533e08df4c63e680438ac1dc243cdc37d205a.zip
* sysdeps/unix/sysv/linux/libc_pthread_init.c: Don't just copy the
	function table, mangle the pointers.
	* sysdeps/pthread/pthread-functions.h: Define PTHFCT_CALL.
	* forward.c: Use PTHFCT_CALL and __libc_pthread_functions_init.
	* sysdeps/pthread/bits/libc-lock.h: When using __libc_pthread_functions
	demangle pointers before use.
	* sysdeps/unix/sysv/linux/s390/jmp-unwind.c: Use PTHFCT_CALL to
	demangle pointer.
	* sysdeps/unix/sysv/linux/jmp-unwind.c: Likewise.
	* sysdeps/pthread/setxid.h: Likewise.
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