about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2005-12-18 06:58:22 +0000
committerUlrich Drepper <drepper@redhat.com>2005-12-18 06:58:22 +0000
commit827b70873b41363c864fb65e99829204595d0f85 (patch)
tree5d2e3811b6b0da44f18a7c8920dffdc524e3cd66
parent8292f6fc71a60e92a23be053c500f504c6802c54 (diff)
downloadglibc-827b70873b41363c864fb65e99829204595d0f85.tar.gz
glibc-827b70873b41363c864fb65e99829204595d0f85.tar.xz
glibc-827b70873b41363c864fb65e99829204595d0f85.zip
* elf/Versions [GLIBC_PRIVATE]: Export __pointer_chk_guard if defined.
	* elf/rtld.c: Define __pointer_chk_guard_local and if necessary
	__pointer_chk_guard.
	(_rtld_global_ro): Initialize _dl_pointer_guard.
	(dl_main): Initialize __pointer_chk_guard_local and either
	__pointer_chk_guard or TLS value if necessary.
	(process_envvars): Recognize and handle LD_POINTER_GUARD.
	* sysdeps/generic/ldsodefs.h (rtld_global_ro): Add _dl_pointer_guard.
	* sysdeps/i386/__longjmp.S: Use PTR_DEMANGLE for PC if defined.
	* sysdeps/x86_64/__longjmp.S: Likewise.
	* sysdeps/i386/bsd-_setjmp.S: Use PTR_MANGLE for PC if defined.
	* sysdeps/i386/bsd-_setjmp.S: Likewise.
	* sysdeps/i386/setjmp.S: Likewise.
	[IS_IN_rtld]: Avoid call to __sigjmp_save.
	* sysdeps/i386/setjmp.S: Likewise.
	* sysdeps/unix/sysv/linux/i386/sysdep.h: Define PTR_MANGLE and
	PTR_DEMANGLE.
	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.

	* sysdeps/i386/elf/setjmp.S: Removed.
	* sysdeps/i386/elf/bsd-setjmp.S: Removed.
-rw-r--r--ChangeLog22
-rw-r--r--elf/Versions2
-rw-r--r--elf/rtld.c32
-rw-r--r--nptl/ChangeLog10
-rw-r--r--nptl/pthread_create.c5
-rw-r--r--nptl/sysdeps/i386/tcb-offsets.sym1
-rw-r--r--nptl/sysdeps/i386/tls.h9
-rw-r--r--nptl/sysdeps/x86_64/tcb-offsets.sym1
-rw-r--r--nptl/sysdeps/x86_64/tls.h10
-rw-r--r--sysdeps/generic/ldsodefs.h3
-rw-r--r--sysdeps/i386/__longjmp.S5
-rw-r--r--sysdeps/i386/bsd-_setjmp.S5
-rw-r--r--sysdeps/i386/bsd-setjmp.S7
-rw-r--r--sysdeps/i386/elf/bsd-setjmp.S82
-rw-r--r--sysdeps/i386/elf/setjmp.S70
-rw-r--r--sysdeps/i386/setjmp.S13
-rw-r--r--sysdeps/unix/sysv/linux/i386/sysdep.h11
-rw-r--r--sysdeps/unix/sysv/linux/x86_64/sysdep.h12
-rw-r--r--sysdeps/x86_64/__longjmp.S5
-rw-r--r--sysdeps/x86_64/setjmp.S15
20 files changed, 159 insertions, 161 deletions
diff --git a/ChangeLog b/ChangeLog
index b2af78c42b..e992f38357 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,27 @@
 2005-12-17  Ulrich Drepper  <drepper@redhat.com>
 
+	* elf/Versions [GLIBC_PRIVATE]: Export __pointer_chk_guard if defined.
+	* elf/rtld.c: Define __pointer_chk_guard_local and if necessary
+	__pointer_chk_guard.
+	(_rtld_global_ro): Initialize _dl_pointer_guard.
+	(dl_main): Initialize __pointer_chk_guard_local and either
+	__pointer_chk_guard or TLS value if necessary.
+	(process_envvars): Recognize and handle LD_POINTER_GUARD.
+	* sysdeps/generic/ldsodefs.h (rtld_global_ro): Add _dl_pointer_guard.
+	* sysdeps/i386/__longjmp.S: Use PTR_DEMANGLE for PC if defined.
+	* sysdeps/x86_64/__longjmp.S: Likewise.
+	* sysdeps/i386/bsd-_setjmp.S: Use PTR_MANGLE for PC if defined.
+	* sysdeps/i386/bsd-_setjmp.S: Likewise.
+	* sysdeps/i386/setjmp.S: Likewise.
+	[IS_IN_rtld]: Avoid call to __sigjmp_save.
+	* sysdeps/i386/setjmp.S: Likewise.
+	* sysdeps/unix/sysv/linux/i386/sysdep.h: Define PTR_MANGLE and
+	PTR_DEMANGLE.
+	* sysdeps/unix/sysv/linux/x86_64/sysdep.h: Likewise.
+
+	* sysdeps/i386/elf/setjmp.S: Removed.
+	* sysdeps/i386/elf/bsd-setjmp.S: Removed.
+
 	* elf/dl-error.c (_dl_catch_error): Use __sigsetgjmp instead of
 	setjmp.
 	* elf/dl-error.c (_dl_signal_error): Use __longjmp instead of longjmp.
diff --git a/elf/Versions b/elf/Versions
index 9c53f1615e..87e27c5a7a 100644
--- a/elf/Versions
+++ b/elf/Versions
@@ -60,5 +60,7 @@ ld {
     _dl_make_stack_executable;
     # Only here for gdb while a better method is developed.
     _dl_debug_state;
+    # Pointer protection.
+    __pointer_chk_guard;
   }
 }
diff --git a/elf/rtld.c b/elf/rtld.c
index a89f89b3a5..9ef58bb328 100644
--- a/elf/rtld.c
+++ b/elf/rtld.c
@@ -90,6 +90,15 @@ INTDEF(_dl_argv)
 uintptr_t __stack_chk_guard attribute_relro;
 #endif
 
+/* Only exported for architectures that don't store the pointer guard
+   value in thread local area.  */
+uintptr_t __pointer_chk_guard_local
+     attribute_relro attribute_hidden __attribute__ ((nocommon));
+#ifndef THREAD_SET_POINTER_GUARD
+strong_alias (__pointer_chk_guard_local, __pointer_chk_guard)
+#endif
+
+
 /* List of auditing DSOs.  */
 static struct audit_list
 {
@@ -142,6 +151,7 @@ struct rtld_global_ro _rtld_global_ro attribute_relro =
     ._dl_hwcap_mask = HWCAP_IMPORTANT,
     ._dl_lazy = 1,
     ._dl_fpu_control = _FPU_DEFAULT,
+    ._dl_pointer_guard = 1,
 
     /* Function pointers.  */
     ._dl_debug_printf = _dl_debug_printf,
@@ -1823,6 +1833,20 @@ ERROR: ld.so: object '%s' cannot be loaded as audit interface: %s; ignored.\n",
   __stack_chk_guard = stack_chk_guard;
 #endif
 
+  /* Set up the pointer guard as well, if necessary.  */
+  if (GLRO(dl_pointer_guard))
+    {
+      // XXX If it is cheap, we should use a separate value.
+      uintptr_t pointer_chk_guard;
+      hp_timing_t now;
+      HP_TIMING_NOW (now);
+      pointer_chk_guard = stack_chk_guard ^ now;
+#ifdef THREAD_SET_POINTER_GUARD
+      THREAD_SET_POINTER_GUARD (pointer_chk_guard);
+#endif
+      __pointer_chk_guard_local = pointer_chk_guard;
+    }
+
   if (__builtin_expect (mode, normal) != normal)
     {
       /* We were run just to list the shared libraries.  It is
@@ -2575,7 +2599,13 @@ process_envvars (enum mode *modep)
 #endif
 	  if (!INTUSE(__libc_enable_secure)
 	      && memcmp (envline, "USE_LOAD_BIAS", 13) == 0)
-	    GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
+	    {
+	      GLRO(dl_use_load_bias) = envline[14] == '1' ? -1 : 0;
+	      break;
+	    }
+
+	  if (memcmp (envline, "POINTER_GUARD", 13) == 0)
+	    GLRO(dl_pointer_guard) = envline[14] == '0';
 	  break;
 
 	case 14:
diff --git a/nptl/ChangeLog b/nptl/ChangeLog
index 9db2e498c5..7a35696b38 100644
--- a/nptl/ChangeLog
+++ b/nptl/ChangeLog
@@ -1,3 +1,13 @@
+2005-12-17  Ulrich Drepper  <drepper@redhat.com>
+
+	* pthread_create.c (__pthread_create_2_1): Use
+	THREAD_COPY_POINTER_GUARD if available.
+	* sysdeps/i386/tcb-offsets.sym: Add POINTER_GUARD.
+	* sysdeps/x86_64/tcb-offsets.sym: Likewise.
+	* sysdeps/i386/tls.h (tcbhead_t): Add pointer_guard.
+	Define THREAD_SET_POINTER_GUARD and THREAD_COPY_POINTER_GUARD.
+	* sysdeps/x86_64/tls.h: Likewise.
+
 2005-12-15  Roland McGrath  <roland@redhat.com>
 
 	* sysdeps/unix/sysv/linux/mq_notify.c: Don't use sysdeps/generic.
diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
index f2f206be5a..c11d972572 100644
--- a/nptl/pthread_create.c
+++ b/nptl/pthread_create.c
@@ -415,6 +415,11 @@ __pthread_create_2_1 (newthread, attr, start_routine, arg)
   THREAD_COPY_STACK_GUARD (pd);
 #endif
 
+  /* Copy the pointer guard value.  */
+#ifdef THREAD_COPY_POINTER_GUARD
+  THREAD_COPY_POINTER_GUARD (pd);
+#endif
+
   /* Determine scheduling parameters for the thread.  */
   if (attr != NULL
       && __builtin_expect ((iattr->flags & ATTR_FLAG_NOTINHERITSCHED) != 0, 0)
diff --git a/nptl/sysdeps/i386/tcb-offsets.sym b/nptl/sysdeps/i386/tcb-offsets.sym
index 4e0444ba38..7c8d9a5ca5 100644
--- a/nptl/sysdeps/i386/tcb-offsets.sym
+++ b/nptl/sysdeps/i386/tcb-offsets.sym
@@ -11,3 +11,4 @@ SYSINFO_OFFSET		offsetof (tcbhead_t, sysinfo)
 CLEANUP			offsetof (struct pthread, cleanup)
 CLEANUP_PREV		offsetof (struct _pthread_cleanup_buffer, __prev)
 MUTEX_FUTEX		offsetof (pthread_mutex_t, __data.__lock)
+POINTER_GUARD		offsetof (tcbhead_t, pointer_guard)
diff --git a/nptl/sysdeps/i386/tls.h b/nptl/sysdeps/i386/tls.h
index 65566ff7a7..a870a848cf 100644
--- a/nptl/sysdeps/i386/tls.h
+++ b/nptl/sysdeps/i386/tls.h
@@ -50,6 +50,7 @@ typedef struct
   int multiple_threads;
   uintptr_t sysinfo;
   uintptr_t stack_guard;
+  uintptr_t pointer_guard;
 } tcbhead_t;
 
 # define TLS_MULTIPLE_THREADS_IN_TCB 1
@@ -425,6 +426,14 @@ union user_desc_init
    = THREAD_GETMEM (THREAD_SELF, header.stack_guard))
 
 
+/* Set the pointer guard field in the TCB head.  */
+#define THREAD_SET_POINTER_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value)
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  ((descr)->header.pointer_guard					      \
+   = THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
+
+
 #endif /* __ASSEMBLER__ */
 
 #endif	/* tls.h */
diff --git a/nptl/sysdeps/x86_64/tcb-offsets.sym b/nptl/sysdeps/x86_64/tcb-offsets.sym
index 8118d2df8b..a9ede75c96 100644
--- a/nptl/sysdeps/x86_64/tcb-offsets.sym
+++ b/nptl/sysdeps/x86_64/tcb-offsets.sym
@@ -10,3 +10,4 @@ CLEANUP			offsetof (struct pthread, cleanup)
 CLEANUP_PREV		offsetof (struct _pthread_cleanup_buffer, __prev)
 MUTEX_FUTEX		offsetof (pthread_mutex_t, __data.__lock)
 MULTIPLE_THREADS_OFFSET	offsetof (tcbhead_t, multiple_threads)
+POINTER_GUARD		offsetof (tcbhead_t, pointer_guard)
diff --git a/nptl/sysdeps/x86_64/tls.h b/nptl/sysdeps/x86_64/tls.h
index 516827b8e1..13cf6fb3f5 100644
--- a/nptl/sysdeps/x86_64/tls.h
+++ b/nptl/sysdeps/x86_64/tls.h
@@ -49,6 +49,7 @@ typedef struct
   int multiple_threads;
   uintptr_t sysinfo;
   uintptr_t stack_guard;
+  uintptr_t pointer_guard;
 } tcbhead_t;
 
 #else /* __ASSEMBLER__ */
@@ -329,6 +330,15 @@ typedef struct
     ((descr)->header.stack_guard					      \
      = THREAD_GETMEM (THREAD_SELF, header.stack_guard))
 
+
+/* Set the pointer guard field in the TCB head.  */
+#define THREAD_SET_POINTER_GUARD(value) \
+  THREAD_SETMEM (THREAD_SELF, header.pointer_guard, value)
+#define THREAD_COPY_POINTER_GUARD(descr) \
+  ((descr)->header.pointer_guard					      \
+   = THREAD_GETMEM (THREAD_SELF, header.pointer_guard))
+
+
 #endif /* __ASSEMBLER__ */
 
 #endif	/* tls.h */
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
index 67a20cea70..b5f7c3cae5 100644
--- a/sysdeps/generic/ldsodefs.h
+++ b/sysdeps/generic/ldsodefs.h
@@ -623,6 +623,9 @@ struct rtld_global_ro
   /* Expected cache ID.  */
   EXTERN int _dl_correct_cache_id;
 
+  /* 0 if internal pointer values should not be guarded, 1 if they should.  */
+  EXTERN int _dl_pointer_guard;
+
   /* Mask for hardware capabilities that are available.  */
   EXTERN uint64_t _dl_hwcap;
 
diff --git a/sysdeps/i386/__longjmp.S b/sysdeps/i386/__longjmp.S
index 6b590f7f04..aced5f42c9 100644
--- a/sysdeps/i386/__longjmp.S
+++ b/sysdeps/i386/__longjmp.S
@@ -1,5 +1,5 @@
 /* longjmp for i386.
-   Copyright (C) 1995,1996,1997,1998,2000,2002 Free Software Foundation, Inc.
+   Copyright (C) 1995-1998,2000,2002,2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -44,6 +44,9 @@ ENTRY (BP_SYM (__longjmp))
 	movl (JB_DI*4)(%ecx), %edi
 	movl (JB_BP*4)(%ecx), %ebp
 	movl (JB_SP*4)(%ecx), %esp
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (%edx)
+#endif
 	/* Jump to saved PC.  */
      	jmp *%edx
 END (BP_SYM (__longjmp))
diff --git a/sysdeps/i386/bsd-_setjmp.S b/sysdeps/i386/bsd-_setjmp.S
index aa8df167d0..f80d239323 100644
--- a/sysdeps/i386/bsd-_setjmp.S
+++ b/sysdeps/i386/bsd-_setjmp.S
@@ -1,5 +1,5 @@
 /* BSD `_setjmp' entry point to `sigsetjmp (..., 0)'.  i386 version.
-   Copyright (C) 1994-1997,2000,2001,2002 Free Software Foundation, Inc.
+   Copyright (C) 1994-1997,2000-2002,2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -46,6 +46,9 @@ ENTRY (BP_SYM (_setjmp))
 	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
      	movl %ecx, (JB_SP*4)(%edx)
 	movl PCOFF(%esp), %ecx	/* Save PC we are returning to now.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
      	movl %ecx, (JB_PC*4)(%edx)
 	LEAVE
 	movl %ebp, (JB_BP*4)(%edx) /* Save caller's frame pointer.  */
diff --git a/sysdeps/i386/bsd-setjmp.S b/sysdeps/i386/bsd-setjmp.S
index b6934dc548..f4257a0dc5 100644
--- a/sysdeps/i386/bsd-setjmp.S
+++ b/sysdeps/i386/bsd-setjmp.S
@@ -28,6 +28,10 @@
 #include "bp-sym.h"
 #include "bp-asm.h"
 
+#define PARMS  LINKAGE		/* no space for saved regs */
+#define JMPBUF PARMS
+#define SIGMSK JMPBUF+PTR_SIZE
+
 ENTRY (BP_SYM (setjmp))
 	/* Note that we have to use a non-exported symbol in the next
 	   jump since otherwise gas will emit it as a jump through the
@@ -44,6 +48,9 @@ ENTRY (BP_SYM (setjmp))
 	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
      	movl %ecx, (JB_SP*4)(%eax)
 	movl PCOFF(%esp), %ecx	/* Save PC we are returning to now.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
      	movl %ecx, (JB_PC*4)(%eax)
 	LEAVE /* pop frame pointer to prepare for tail-call.  */
 	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
diff --git a/sysdeps/i386/elf/bsd-setjmp.S b/sysdeps/i386/elf/bsd-setjmp.S
deleted file mode 100644
index c421791fe0..0000000000
--- a/sysdeps/i386/elf/bsd-setjmp.S
+++ /dev/null
@@ -1,82 +0,0 @@
-/* BSD `setjmp' entry point to `sigsetjmp (..., 1)'.  i386 version.
-   Copyright (C) 1995-1997,2000-2003,2005 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <sysdep.h>
-#define _ASM
-#define _SETJMP_H
-#include <bits/setjmp.h>
-#include "bp-sym.h"
-#include "bp-asm.h"
-
-#define PARMS	LINKAGE		/* no space for saved regs */
-#define JMPBUF	PARMS
-#define SIGMSK	JMPBUF+PTR_SIZE
-
-ENTRY (BP_SYM (setjmp))
-	/* Note that we have to use a non-exported symbol in the next
-	   jump since otherwise gas will emit it as a jump through the
-	   PLT which is what we cannot use here.  */
-	ENTER
-
-	movl JMPBUF(%esp), %eax
-	CHECK_BOUNDS_BOTH_WIDE (%eax, JMPBUF(%esp), $JB_SIZE)
-
-     	/* Save registers.  */
-	movl %ebx, (JB_BX*4)(%eax)
-	movl %esi, (JB_SI*4)(%eax)
-	movl %edi, (JB_DI*4)(%eax)
-	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
-     	movl %ecx, (JB_SP*4)(%eax)
-	movl PCOFF(%esp), %ecx	/* Save PC we are returning to now.  */
-     	movl %ecx, (JB_PC*4)(%eax)
-	LEAVE /* pop frame pointer to prepare for tail-call.  */
-	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
-
-	/* Call __sigjmp_save.  */
-	pushl $1
-	cfi_adjust_cfa_offset (4)
-	pushl 8(%esp)
-	cfi_adjust_cfa_offset (4)
-#ifdef	PIC
-	/* We cannot use the PLT, because it requires that %ebx be set, but
-           we can't save and restore our caller's value.  Instead, we do an
-           indirect jump through the GOT, using for the temporary register
-           %ecx, which is call-clobbered.  */
-	call __i686.get_pc_thunk.cx
-	addl $_GLOBAL_OFFSET_TABLE_, %ecx
-	leal C_SYMBOL_NAME (BP_SYM (__sigjmp_save)@GOTOFF)(%ecx), %ecx
-	call *%ecx
-#else
-	call BP_SYM (__sigjmp_save)
-#endif
-	popl %ecx
-	cfi_adjust_cfa_offset (-4)
-	popl %edx
-	cfi_adjust_cfa_offset (-4)
-	ret
-END (BP_SYM (setjmp))
-
-	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
-	.globl __i686.get_pc_thunk.cx
-	.hidden __i686.get_pc_thunk.cx
-	.type __i686.get_pc_thunk.cx,@function
-__i686.get_pc_thunk.cx:
-	movl (%esp), %ecx
-	ret
-	.size __i686.get_pc_thunk.cx, . - __i686.get_pc_thunk.cx
diff --git a/sysdeps/i386/elf/setjmp.S b/sysdeps/i386/elf/setjmp.S
deleted file mode 100644
index d6ae98b8b4..0000000000
--- a/sysdeps/i386/elf/setjmp.S
+++ /dev/null
@@ -1,70 +0,0 @@
-/* setjmp for i386, ELF version.
-   Copyright (C) 1995-1997,2000,2001,2002,2003 Free Software Foundation, Inc.
-   This file is part of the GNU C Library.
-
-   The GNU C Library is free software; you can redistribute it and/or
-   modify it under the terms of the GNU Lesser General Public
-   License as published by the Free Software Foundation; either
-   version 2.1 of the License, or (at your option) any later version.
-
-   The GNU C Library is distributed in the hope that it will be useful,
-   but WITHOUT ANY WARRANTY; without even the implied warranty of
-   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-   Lesser General Public License for more details.
-
-   You should have received a copy of the GNU Lesser General Public
-   License along with the GNU C Library; if not, write to the Free
-   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
-   02111-1307 USA.  */
-
-#include <sysdep.h>
-#define _ASM
-#define _SETJMP_H
-#include <bits/setjmp.h>
-#include "bp-sym.h"
-#include "bp-asm.h"
-
-#define PARMS	LINKAGE		/* no space for saved regs */
-#define JMPBUF	PARMS
-#define SIGMSK	JMPBUF+PTR_SIZE
-
-ENTRY (BP_SYM (__sigsetjmp))
-	ENTER
-
-	movl JMPBUF(%esp), %eax
-	CHECK_BOUNDS_BOTH_WIDE (%eax, JMPBUF(%esp), $JB_SIZE)
-
-     	/* Save registers.  */
-	movl %ebx, (JB_BX*4)(%eax)
-	movl %esi, (JB_SI*4)(%eax)
-	movl %edi, (JB_DI*4)(%eax)
-	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
-     	movl %ecx, (JB_SP*4)(%eax)
-	movl PCOFF(%esp), %ecx	/* Save PC we are returning to now.  */
-     	movl %ecx, (JB_PC*4)(%eax)
-	LEAVE /* pop frame pointer to prepare for tail-call.  */
-	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
-
-	/* Make a tail call to __sigjmp_save; it takes the same args.  */
-#ifdef	PIC
-	/* We cannot use the PLT, because it requires that %ebx be set, but
-           we can't save and restore our caller's value.  Instead, we do an
-           indirect jump through the GOT, using for the temporary register
-           %ecx, which is call-clobbered.  */
-	call __i686.get_pc_thunk.cx
-	addl $_GLOBAL_OFFSET_TABLE_, %ecx
-	leal C_SYMBOL_NAME (BP_SYM (__sigjmp_save)@GOTOFF)(%ecx), %ecx
-	jmp *%ecx
-#else
-	jmp BP_SYM (__sigjmp_save)
-#endif
-END (BP_SYM (__sigsetjmp))
-
-	.section .gnu.linkonce.t.__i686.get_pc_thunk.cx,"ax",@progbits
-	.globl __i686.get_pc_thunk.cx
-	.hidden __i686.get_pc_thunk.cx
-	.type __i686.get_pc_thunk.cx,@function
-__i686.get_pc_thunk.cx:
-	movl (%esp), %ecx
-	ret
-	.size __i686.get_pc_thunk.cx, . - __i686.get_pc_thunk.cx
diff --git a/sysdeps/i386/setjmp.S b/sysdeps/i386/setjmp.S
index e01d32b66c..747499adc2 100644
--- a/sysdeps/i386/setjmp.S
+++ b/sysdeps/i386/setjmp.S
@@ -1,5 +1,5 @@
 /* setjmp for i386.
-   Copyright (C) 1995, 1996, 1997, 2000, 2001 Free Software Foundation, Inc.
+   Copyright (C) 1995,1996,1997,2000,2001,2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -42,10 +42,19 @@ ENTRY (BP_SYM (__sigsetjmp))
 	leal JMPBUF(%esp), %ecx	/* Save SP as it will be after we return.  */
      	movl %ecx, (JB_SP*4)(%eax)
 	movl PCOFF(%esp), %ecx	/* Save PC we are returning to now.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%ecx)
+#endif
      	movl %ecx, (JB_PC*4)(%eax)
 	LEAVE /* pop frame pointer to prepare for tail-call.  */
 	movl %ebp, (JB_BP*4)(%eax) /* Save caller's frame pointer.  */
 
+#if defined NOT_IN_libc && defined IS_IN_rtld
+	/* In ld.so we never save the signal mask.  */
+	xorl %eax, %eax
+	ret
+#else
 	/* Make a tail call to __sigjmp_save; it takes the same args.  */
-	jmp BP_SYM (__sigjmp_save)
+	jmp __sigjmp_save
+#endif
 END (BP_SYM (__sigsetjmp))
diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
index 99f9bf1edf..929c6e5191 100644
--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
+++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
@@ -558,4 +558,15 @@ asm (".L__X'%ebx = 1\n\t"
 
 #endif	/* __ASSEMBLER__ */
 
+
+/* Pointer mangling support.  */
+#if defined NOT_IN_libc && defined IS_IN_rtld
+/* We cannot use the thread descriptor because in ld.so we use setjmp
+   earlier than the descriptor is initialized.  Using a global variable
+   is too complicated here since we have no PC-relative addressing mode.  */
+#else
+# define PTR_MANGLE(reg)	xorl %gs:POINTER_GUARD, reg
+# define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
+#endif
+
 #endif /* linux/i386/sysdep.h */
diff --git a/sysdeps/unix/sysv/linux/x86_64/sysdep.h b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
index 0dc2f2750e..2ea69c3bfd 100644
--- a/sysdeps/unix/sysv/linux/x86_64/sysdep.h
+++ b/sysdeps/unix/sysv/linux/x86_64/sysdep.h
@@ -311,4 +311,16 @@
 
 #endif	/* __ASSEMBLER__ */
 
+
+/* Pointer mangling support.  */
+#if defined NOT_IN_libc && defined IS_IN_rtld
+/* We cannot use the thread descriptor because in ld.so we use setjmp
+   earlier than the descriptor is initialized.  */
+# define PTR_MANGLE(reg)	xorq __pointer_chk_guard_local(%rip), reg
+# define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
+#else
+# define PTR_MANGLE(reg)	xorq %fs:POINTER_GUARD, reg
+# define PTR_DEMANGLE(reg)	PTR_MANGLE (reg)
+#endif
+
 #endif /* linux/x86_64/sysdep.h */
diff --git a/sysdeps/x86_64/__longjmp.S b/sysdeps/x86_64/__longjmp.S
index 9ed480c540..becfb4f79d 100644
--- a/sysdeps/x86_64/__longjmp.S
+++ b/sysdeps/x86_64/__longjmp.S
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001, 2004 Free Software Foundation, Inc.
+/* Copyright (C) 2001, 2004, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -50,5 +50,8 @@ ENTRY(__longjmp)
 	mov %esi, %eax
 	movq (JB_PC*8)(%rdi),%rdx
 	movq (JB_RSP*8)(%rdi),%rsp
+#ifdef PTR_DEMANGLE
+	PTR_DEMANGLE (%rdx)
+#endif
 	jmpq *%rdx
 END (BP_SYM (__longjmp))
diff --git a/sysdeps/x86_64/setjmp.S b/sysdeps/x86_64/setjmp.S
index 811ab1d913..8af5502042 100644
--- a/sysdeps/x86_64/setjmp.S
+++ b/sysdeps/x86_64/setjmp.S
@@ -1,5 +1,5 @@
 /* setjmp for x86-64.
-   Copyright (C) 2001, 2003 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
    The GNU C Library is free software; you can redistribute it and/or
@@ -34,13 +34,22 @@ ENTRY (__sigsetjmp)
 	leaq 8(%rsp), %rdx	/* Save SP as it will be after we return.  */
 	movq %rdx, (JB_RSP*8)(%rdi)
 	movq (%rsp), %rax	/* Save PC we are returning to now.  */
+#ifdef PTR_MANGLE
+	PTR_MANGLE (%rax)
+#endif
 	movq %rax, (JB_PC*8)(%rdi)
 
+#if defined NOT_IN_libc && defined IS_IN_rtld
+	/* In ld.so we never save the signal mask.  */
+	xorl %eax, %eax
+	retq
+#else
 	/* Make a tail call to __sigjmp_save; it takes the same args.  */
-#ifdef	PIC
+# ifdef	PIC
 	jmp C_SYMBOL_NAME (BP_SYM (__sigjmp_save))@PLT
-#else
+# else
 	jmp BP_SYM (__sigjmp_save)
+# endif
 #endif
 END (BP_SYM (__sigsetjmp))
 hidden_def (__sigsetjmp)