[3/8] Enable the pointer guard in the dynamic loader

Message ID 20260603000656.3287796-4-adhemerval.zanella@linaro.org (mailing list archive)
State Superseded
Delegated to: DJ Delorie
Headers
Series Pointer guard hardening and consolidation |

Checks

Context Check Description
redhat-pt-bot/TryBot-apply_patch success Patch applied to master at the time it was sent
linaro-tcwg-bot/tcwg_glibc_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_glibc_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-arm success Test passed

Commit Message

Adhemerval Zanella Netto June 3, 2026, 12:04 a.m. UTC
  i386, powerpc, s390, sh and sparc fell back to the generic no-op
pointer_guard.h in ld.so, so the loader's own setjmp/longjmp and mangled
function pointers were left unprotected (the other targets already
mangle in rtld).  ld.so is position-independent and sets up
__pointer_chk_guard_local early in dl_main, so the loader can reach it
the same way a statically linked program does:

  - powerpc, s390, sh, sparc: select __pointer_chk_guard_local for
    IS_IN (rtld) and reuse the existing PIC guard load.
  - i386: load it via @GOTOFF off a GOT pointer set up with LOAD_PIC_REG
    (ld.so does not keep the GOT in %ebx at the setjmp/longjmp entry).
  - s390: drop the IS_IN (rtld) "#undef PTR_DEMANGLE" in __longjmp.c so
    the loader's longjmp demangles to match its setjmp.

Checked on x86_64-linux-gnu, aarch64-linux-gnu, i686-linux-gnu, and
armv7a-linux-gnueabihf.  I also run elf and setjmp checks on qemu
loongarch64, powerpc64, powerpc64le, and s390x systems.
---
 sysdeps/s390/__longjmp.c                      |  5 --
 sysdeps/unix/sysv/linux/i386/pointer_guard.h  | 57 ++++++--------
 .../unix/sysv/linux/powerpc/pointer_guard.h   | 78 ++++++++++---------
 sysdeps/unix/sysv/linux/s390/pointer_guard.h  | 52 ++++++-------
 sysdeps/unix/sysv/linux/sh/pointer_guard.h    | 65 ++++++++--------
 .../sysv/linux/sparc/sparc32/pointer_guard.h  | 59 +++++++-------
 .../sysv/linux/sparc/sparc64/pointer_guard.h  | 59 +++++++-------
 7 files changed, 183 insertions(+), 192 deletions(-)
  

Comments

DJ Delorie June 10, 2026, 7:37 p.m. UTC | #1
Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:
> i386, powerpc, s390, sh and sparc fell back to the generic no-op
> pointer_guard.h in ld.so, so the loader's own setjmp/longjmp and mangled
> function pointers were left unprotected (the other targets already
> mangle in rtld).  ld.so is position-independent and sets up
> __pointer_chk_guard_local early in dl_main, so the loader can reach it
> the same way a statically linked program does:

LGTM
Reviewed-by: DJ Delorie <dj@redhat.com>
  

Patch

diff --git a/sysdeps/s390/__longjmp.c b/sysdeps/s390/__longjmp.c
index 78aa70a943c..50d67bf42cc 100644
--- a/sysdeps/s390/__longjmp.c
+++ b/sysdeps/s390/__longjmp.c
@@ -24,11 +24,6 @@ 
 #include <unistd.h>
 #include <stap-probe.h>
 
-/* See sysdeps/unix/sysv/linux/s390/pointer_guard.h.  */
-#if IS_IN (rtld)
-# undef PTR_DEMANGLE
-#endif
-
 /* Jump to the position specified by ENV, causing the
    setjmp call there to return VAL, or 1 if VAL is 0.  */
 void
diff --git a/sysdeps/unix/sysv/linux/i386/pointer_guard.h b/sysdeps/unix/sysv/linux/i386/pointer_guard.h
index d91b2342055..63308d84e76 100644
--- a/sysdeps/unix/sysv/linux/i386/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/i386/pointer_guard.h
@@ -19,27 +19,10 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-#if IS_IN (rtld)
-/* We cannot use the thread descriptor because in ld.so we use setjmp
-   earlier than the descriptor is initialized.  */
-# include <sysdeps/generic/pointer_guard.h>
-#else
-# ifdef __ASSEMBLER__
-#  include <sysdep.h>
-#  ifdef SHARED
-/* The global guard is reached through the GOT.  setjmp/__longjmp save and
-   restore %ebx and %esi around the mangling, so they can be used here as
-   the GOT pointer and a scratch register.  */
-#   define PTR_MANGLE(reg)	LOAD_PIC_REG (bx);			      \
-				movl __pointer_chk_guard@GOT(%ebx), %esi;     \
-				xorl (%esi), reg;			      \
-				roll $9, reg
-#   define PTR_DEMANGLE(reg)	rorl $9, reg;				      \
-				LOAD_PIC_REG (bx);			      \
-				movl __pointer_chk_guard@GOT(%ebx), %esi;     \
-				xorl (%esi), reg
-#  elif defined PIC
-/* Static PIE: the module-local guard is reached via @GOTOFF.  */
+#ifdef __ASSEMBLER__
+# include <sysdep.h>
+# if IS_IN (rtld) || !defined SHARED
+#  ifdef PIC
 #   define PTR_MANGLE(reg)	LOAD_PIC_REG (bx);			      \
 				xorl __pointer_chk_guard_local@GOTOFF(%ebx), reg; \
 				roll $9, reg
@@ -47,35 +30,43 @@ 
 				LOAD_PIC_REG (bx);			      \
 				xorl __pointer_chk_guard_local@GOTOFF(%ebx), reg
 #  else
-/* Position-dependent code addresses the guard directly.  */
 #   define PTR_MANGLE(reg)	xorl __pointer_chk_guard_local, reg;	      \
 				roll $9, reg
 #   define PTR_DEMANGLE(reg)	rorl $9, reg;				      \
 				xorl __pointer_chk_guard_local, reg
 #  endif
 # else
-#  include <stdbit.h>
-#  include <stdint.h>
-#  ifdef SHARED
-extern uintptr_t __pointer_chk_guard attribute_relro;
-#   define PTR_GUARD_VALUE	__pointer_chk_guard
-#  else
+#  define PTR_MANGLE(reg)	LOAD_PIC_REG (bx);			      \
+				movl __pointer_chk_guard@GOT(%ebx), %esi;     \
+				xorl (%esi), reg;			      \
+				roll $9, reg
+#  define PTR_DEMANGLE(reg)	rorl $9, reg;				      \
+				LOAD_PIC_REG (bx);			      \
+				movl __pointer_chk_guard@GOT(%ebx), %esi;     \
+				xorl (%esi), reg
+# endif
+#else
+# include <stdbit.h>
+# include <stdint.h>
+# if IS_IN (rtld) || !defined SHARED
 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
-#   define PTR_GUARD_VALUE	__pointer_chk_guard_local
-#  endif
-#  define PTR_MANGLE(var)						      \
+#  define PTR_GUARD_VALUE	__pointer_chk_guard_local
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#  define PTR_GUARD_VALUE	__pointer_chk_guard
+# endif
+# define PTR_MANGLE(var)						      \
     do {								      \
       (var) = (__typeof (var)) ((uintptr_t) (var) ^ PTR_GUARD_VALUE);	      \
       (var) = (__typeof (var)) stdc_rotate_left ((uintptr_t) (var),	      \
 						 2 * sizeof (uintptr_t) + 1); \
     } while (0)
-#  define PTR_DEMANGLE(var)						      \
+# define PTR_DEMANGLE(var)						      \
     do {								      \
       (var) = (__typeof (var)) stdc_rotate_right ((uintptr_t) (var),	      \
 						  2 * sizeof (uintptr_t) + 1); \
       (var) = (__typeof (var)) ((uintptr_t) (var) ^ PTR_GUARD_VALUE);	      \
     } while (0)
-# endif
 #endif
 
 #endif /* POINTER_GUARD_H */
diff --git a/sysdeps/unix/sysv/linux/powerpc/pointer_guard.h b/sysdeps/unix/sysv/linux/powerpc/pointer_guard.h
index 864a78ea531..271cf93c2f4 100644
--- a/sysdeps/unix/sysv/linux/powerpc/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/powerpc/pointer_guard.h
@@ -1,4 +1,4 @@ 
-/* Pointer obfuscation implenentation.  PowerpC version.
+/* Pointer obfuscation implenentation.  PowerPC version.
    Copyright (C) 2005-2026 Free Software Foundation, Inc.
    This file is part of the GNU C Library.
 
@@ -19,24 +19,32 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-#if IS_IN (rtld)
-# include <sysdeps/generic/pointer_guard.h>
-#else
-# ifdef __ASSEMBLER__
-#  include <sysdep.h>
-#  ifdef SHARED
-#   define PTR_GUARD_SYM	__pointer_chk_guard
-#  else
-#   define PTR_GUARD_SYM	__pointer_chk_guard_local
-#  endif
+/* In ld.so and in statically linked programs the guard is the module-local
+   relro variable __pointer_chk_guard_local; in other shared objects it is
+   the global __pointer_chk_guard provided by the dynamic loader.  */
+#ifdef __ASSEMBLER__
+# include <sysdep.h>
+# if IS_IN (rtld) || !defined SHARED
+#  define PTR_GUARD_SYM	__pointer_chk_guard_local
+# else
+#  define PTR_GUARD_SYM	__pointer_chk_guard
+# endif
 
-#  if defined(__PPC64__) || defined(__powerpc64__)
-#   define PTR_GUARD_LOAD(tmpreg)					\
+# if defined(__PPC64__) || defined(__powerpc64__)
+/* r2 (the TOC pointer) is always available, so load the guard's address
+   from the TOC/GOT and dereference it.  */
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	addis	tmpreg,r2,PTR_GUARD_SYM@got@ha;				\
 	ld	tmpreg,PTR_GUARD_SYM@got@l(tmpreg);			\
 	ld	tmpreg,0(tmpreg)
-#  elif defined PIC
-#   define PTR_GUARD_LOAD(tmpreg)					\
+# elif defined PIC
+/* Position-independent 32-bit code has no dedicated GOT register here, so
+   establish one with the usual bcl/mflr sequence.  GAS numeric local labels
+   are used so the sequence can be expanded more than once per file.  LR is
+   clobbered by the bcl, so it is saved in r12 (a volatile register that is
+   not otherwise live at the mangling points) and restored; r0 must not be
+   used here as it holds the saved link register in __longjmp.  */
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	mflr	r12;							\
 	bcl	20,31,0f;						\
 0:	mflr	tmpreg;							\
@@ -45,36 +53,36 @@ 
 	mtlr	r12;							\
 	lwz	tmpreg,PTR_GUARD_SYM@got(tmpreg);			\
 	lwz	tmpreg,0(tmpreg)
-#  else
-#   define PTR_GUARD_LOAD(tmpreg)					\
-	lis	tmpreg,PTR_GUARD_SYM@ha;				\
+# else
+/* Position-dependent 32-bit code can address the variable directly.  */
+#  define PTR_GUARD_LOAD(tmpreg)					\
+	lis	tmpreg,PTR_GUARD_SYM@ha;					\
 	lwz	tmpreg,PTR_GUARD_SYM@l(tmpreg)
-#  endif
+# endif
 
-#  define PTR_MANGLE(reg, tmpreg) \
+# define PTR_MANGLE(reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg); \
 	xor	reg,tmpreg,reg
-#  define PTR_MANGLE2(reg, tmpreg) \
+# define PTR_MANGLE2(reg, tmpreg) \
 	xor	reg,tmpreg,reg
-#  define PTR_MANGLE3(destreg, reg, tmpreg) \
+# define PTR_MANGLE3(destreg, reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg); \
 	xor	destreg,tmpreg,reg
-#  define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
-#  define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
-#  define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg)
-# else
-#  include <stdint.h>
-#  ifdef SHARED
-extern uintptr_t __pointer_chk_guard attribute_relro;
-#   define PTR_MANGLE(var) \
-  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
-#  else
+# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
+# define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
+# define PTR_DEMANGLE3(destreg, reg, tmpreg) PTR_MANGLE3 (destreg, reg, tmpreg)
+#else
+# include <stdint.h>
+# if IS_IN (rtld) || !defined SHARED
 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
-#   define PTR_MANGLE(var) \
+#  define PTR_MANGLE(var) \
   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
-#  endif
-#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#  define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
 # endif
+# define PTR_DEMANGLE(var)     PTR_MANGLE (var)
 #endif
 
 #endif /* POINTER_GUARD_H */
diff --git a/sysdeps/unix/sysv/linux/s390/pointer_guard.h b/sysdeps/unix/sysv/linux/s390/pointer_guard.h
index aa75b8c42e5..a4ec92f6655 100644
--- a/sysdeps/unix/sysv/linux/s390/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/s390/pointer_guard.h
@@ -19,40 +19,40 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-#if IS_IN (rtld)
-# include <sysdeps/generic/pointer_guard.h>
-#else
-# ifdef __ASSEMBLER__
-#  ifdef SHARED
-#   define PTR_GUARD_LOAD(tmpreg)					\
+/* In ld.so and in statically linked programs the guard is the module-local
+   relro variable __pointer_chk_guard_local, reached PC-relatively with larl;
+   in other shared objects it is the global __pointer_chk_guard provided by
+   the dynamic loader, reached through the GOT.  */
+#ifdef __ASSEMBLER__
+# if IS_IN (rtld) || !defined SHARED
+#  define PTR_GUARD_LOAD(tmpreg)					\
+	larl	tmpreg,__pointer_chk_guard_local;			\
+	lg	tmpreg,0(tmpreg)
+# else
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	larl	tmpreg,__pointer_chk_guard@GOTENT;			\
 	lg	tmpreg,0(tmpreg);					\
 	lg	tmpreg,0(tmpreg)
-#  else
-#   define PTR_GUARD_LOAD(tmpreg)					\
-	larl	tmpreg,__pointer_chk_guard_local;			\
-	lg	tmpreg,0(tmpreg)
-#  endif
-#  define PTR_MANGLE(reg, tmpreg) \
+# endif
+# define PTR_MANGLE(reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg);					\
 	xgr	reg,tmpreg
-#  define PTR_MANGLE2(reg, tmpreg) \
+# define PTR_MANGLE2(reg, tmpreg) \
 	xgr	reg,tmpreg
-#  define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
-#  define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
-# else
-#  include <stdint.h>
-#  ifdef SHARED
-extern uintptr_t __pointer_chk_guard attribute_relro;
-#   define PTR_GUARD_VALUE	__pointer_chk_guard
-#  else
+# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
+# define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
+#else
+# include <stdint.h>
+# if IS_IN (rtld) || !defined SHARED
 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
-#   define PTR_GUARD_VALUE	__pointer_chk_guard_local
-#  endif
-#  define PTR_MANGLE(var) \
-  (var) = (void *) ((uintptr_t) (var) ^ PTR_GUARD_VALUE)
-#  define PTR_DEMANGLE(var)	PTR_MANGLE (var)
+#  define PTR_GUARD_VALUE	__pointer_chk_guard_local
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#  define PTR_GUARD_VALUE	__pointer_chk_guard
 # endif
+# define PTR_MANGLE(var) \
+  (var) = (void *) ((uintptr_t) (var) ^ PTR_GUARD_VALUE)
+# define PTR_DEMANGLE(var)	PTR_MANGLE (var)
 #endif
 
 #endif /* POINTER_GUARD_H */
diff --git a/sysdeps/unix/sysv/linux/sh/pointer_guard.h b/sysdeps/unix/sysv/linux/sh/pointer_guard.h
index fa989573c9e..9a1e01a452c 100644
--- a/sysdeps/unix/sysv/linux/sh/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/sh/pointer_guard.h
@@ -19,17 +19,21 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-#if IS_IN (rtld)
-# include <sysdeps/generic/pointer_guard.h>
-#else
-# ifdef __ASSEMBLER__
-#  ifdef SHARED
-#   define PTR_GUARD_SYM	__pointer_chk_guard
-#  else
-#   define PTR_GUARD_SYM	__pointer_chk_guard_local
-#  endif
-#  ifdef PIC
-#   define PTR_GUARD_LOAD(tmp)						\
+/* In ld.so and in statically linked programs the guard is the module-local
+   relro variable __pointer_chk_guard_local; in other shared objects it is
+   the global __pointer_chk_guard provided by the dynamic loader.  */
+#ifdef __ASSEMBLER__
+# if IS_IN (rtld) || !defined SHARED
+#  define PTR_GUARD_SYM	__pointer_chk_guard_local
+# else
+#  define PTR_GUARD_SYM	__pointer_chk_guard
+# endif
+# ifdef PIC
+/* Load the guard through the GOT.  The GOT pointer is computed with the
+   usual mova/mov.l sequence which clobbers r0; in __longjmp r0 holds the
+   return value, so it is saved in r3 (dead at every mangling site) and
+   restored.  A literal pool is emitted inline and branched over.  */
+#  define PTR_GUARD_LOAD(tmp)						\
 	mov	r0, r3;							\
 	mova	.Lptrg_got, r0;						\
 	mov.l	.Lptrg_got, tmp;					\
@@ -46,8 +50,8 @@ 
 .Lptrg_sym:								\
 	.long	PTR_GUARD_SYM@GOT;					\
 .Lptrg_end:
-#  else
-#   define PTR_GUARD_LOAD(tmp)						\
+# else
+#  define PTR_GUARD_LOAD(tmp)						\
 	mov.l	.Lptrg_sym, tmp;					\
 	mov.l	@tmp, tmp;						\
 	bra	.Lptrg_end;						\
@@ -56,25 +60,24 @@ 
 .Lptrg_sym:								\
 	.long	PTR_GUARD_SYM;						\
 .Lptrg_end:
-#  endif
-#  define PTR_MANGLE(reg, tmp) \
-     PTR_GUARD_LOAD (tmp); xor tmp,reg
-#  define PTR_MANGLE2(reg, tmp) xor tmp,reg
-#  define PTR_DEMANGLE(reg, tmp)        PTR_MANGLE (reg, tmp)
-#  define PTR_DEMANGLE2(reg, tmp)       PTR_MANGLE2 (reg, tmp)
-# else
-#  include <stdint.h>
-#  ifdef SHARED
-extern uintptr_t __pointer_chk_guard attribute_relro;
-#   define PTR_MANGLE(var) \
-     (var) = (void *) ((uintptr_t) (var) ^ __pointer_chk_guard)
-#  else
-extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
-#   define PTR_MANGLE(var) \
-     (var) = (void *) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
-#  endif
-#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
 # endif
+# define PTR_MANGLE(reg, tmp) \
+     PTR_GUARD_LOAD (tmp); xor tmp,reg
+# define PTR_MANGLE2(reg, tmp) xor tmp,reg
+# define PTR_DEMANGLE(reg, tmp)        PTR_MANGLE (reg, tmp)
+# define PTR_DEMANGLE2(reg, tmp)       PTR_MANGLE2 (reg, tmp)
+#else
+# include <stdint.h>
+# if IS_IN (rtld) || !defined SHARED
+extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
+#  define PTR_MANGLE(var) \
+     (var) = (void *) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#  define PTR_MANGLE(var) \
+     (var) = (void *) ((uintptr_t) (var) ^ __pointer_chk_guard)
+# endif
+# define PTR_DEMANGLE(var)     PTR_MANGLE (var)
 #endif
 
 #endif /* POINTER_GUARD_H */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard.h b/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard.h
index 43531defe99..2242981f6bd 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard.h
@@ -19,54 +19,51 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-#if IS_IN (rtld)
-/* We cannot use the thread descriptor because in ld.so we use setjmp
-   earlier than the descriptor is initialized.  */
-# include <sysdeps/generic/pointer_guard.h>
-#else
-# ifdef __ASSEMBLER__
-#  include <sysdep.h>
-#  ifdef SHARED
-#   define PTR_GUARD_SYM	__pointer_chk_guard
-#  else
-#   define PTR_GUARD_SYM	__pointer_chk_guard_local
-#  endif
-#  ifdef PIC
+/* In ld.so and in statically linked programs the guard is the module-local
+   relro variable __pointer_chk_guard_local; in other shared objects it is
+   the global __pointer_chk_guard provided by the dynamic loader.  */
+#ifdef __ASSEMBLER__
+# include <sysdep.h>
+# if IS_IN (rtld) || !defined SHARED
+#  define PTR_GUARD_SYM	__pointer_chk_guard_local
+# else
+#  define PTR_GUARD_SYM	__pointer_chk_guard
+# endif
+# ifdef PIC
 /* Load the guard through the GOT.  SETUP_PIC_REG_LEAF computes the GOT
    pointer in %o2 while preserving %o7 (the return address, which setjmp
    mangles), using %o3 as a scratch register; both are dead at every
    mangling site.  */
-#   define PTR_GUARD_LOAD(tmpreg)					\
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	SETUP_PIC_REG_LEAF(o2, o3);					\
 	sethi	%gdop_hix22(PTR_GUARD_SYM), tmpreg;			\
 	xor	tmpreg, %gdop_lox10(PTR_GUARD_SYM), tmpreg;		\
 	ld	[%o2 + tmpreg], tmpreg, %gdop(PTR_GUARD_SYM);		\
 	ld	[tmpreg], tmpreg
-#  else
-#   define PTR_GUARD_LOAD(tmpreg)					\
+# else
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	sethi	%hi(PTR_GUARD_SYM), tmpreg;				\
 	ld	[tmpreg + %lo(PTR_GUARD_SYM)], tmpreg
-#  endif
-#  define PTR_MANGLE(dreg, reg, tmpreg) \
+# endif
+# define PTR_MANGLE(dreg, reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg);					\
 	xor	reg, tmpreg, dreg
-#  define PTR_DEMANGLE(dreg, reg, tmpreg) PTR_MANGLE (dreg, reg, tmpreg)
-#  define PTR_MANGLE2(dreg, reg, tmpreg) \
+# define PTR_DEMANGLE(dreg, reg, tmpreg) PTR_MANGLE (dreg, reg, tmpreg)
+# define PTR_MANGLE2(dreg, reg, tmpreg) \
 	xor	reg, tmpreg, dreg
-#  define PTR_DEMANGLE2(dreg, reg, tmpreg) PTR_MANGLE2 (dreg, reg, tmpreg)
-# else
-#  include <stdint.h>
-#  ifdef SHARED
-extern uintptr_t __pointer_chk_guard attribute_relro;
-#   define PTR_MANGLE(var) \
-  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
-#  else
+# define PTR_DEMANGLE2(dreg, reg, tmpreg) PTR_MANGLE2 (dreg, reg, tmpreg)
+#else
+# include <stdint.h>
+# if IS_IN (rtld) || !defined SHARED
 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
-#   define PTR_MANGLE(var) \
+#  define PTR_MANGLE(var) \
   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
-#  endif
-#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#  define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
 # endif
+# define PTR_DEMANGLE(var)     PTR_MANGLE (var)
 #endif
 
 #endif /* POINTER_GUARD_H */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard.h b/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard.h
index 6515e0dd072..8cdb2edf7be 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard.h
@@ -19,52 +19,49 @@ 
 #ifndef POINTER_GUARD_H
 #define POINTER_GUARD_H
 
-#if IS_IN (rtld)
-/* We cannot use the thread descriptor because in ld.so we use setjmp
-   earlier than the descriptor is initialized.  */
-# include <sysdeps/generic/pointer_guard.h>
-#else
-# ifdef __ASSEMBLER__
-#  include <sysdep.h>
-#  ifdef SHARED
-#   define PTR_GUARD_SYM	__pointer_chk_guard
-#  else
-#   define PTR_GUARD_SYM	__pointer_chk_guard_local
-#  endif
-#  ifdef PIC
+/* In ld.so and in statically linked programs the guard is the module-local
+   relro variable __pointer_chk_guard_local; in other shared objects it is
+   the global __pointer_chk_guard provided by the dynamic loader.  */
+#ifdef __ASSEMBLER__
+# include <sysdep.h>
+# if IS_IN (rtld) || !defined SHARED
+#  define PTR_GUARD_SYM	__pointer_chk_guard_local
+# else
+#  define PTR_GUARD_SYM	__pointer_chk_guard
+# endif
+# ifdef PIC
 /* Load the guard through the GOT.  SETUP_PIC_REG_LEAF computes the GOT
    pointer in %o2 while preserving %o7, using %o3 as a scratch register.  */
-#   define PTR_GUARD_LOAD(tmpreg)					\
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	SETUP_PIC_REG_LEAF(o2, o3);					\
 	sethi	%gdop_hix22(PTR_GUARD_SYM), tmpreg;			\
 	xor	tmpreg, %gdop_lox10(PTR_GUARD_SYM), tmpreg;		\
 	ldx	[%o2 + tmpreg], tmpreg, %gdop(PTR_GUARD_SYM);		\
 	ldx	[tmpreg], tmpreg
-#  else
-#   define PTR_GUARD_LOAD(tmpreg)					\
+# else
+#  define PTR_GUARD_LOAD(tmpreg)					\
 	sethi	%hi(PTR_GUARD_SYM), tmpreg;				\
 	ldx	[tmpreg + %lo(PTR_GUARD_SYM)], tmpreg
-#  endif
-#  define PTR_MANGLE(dreg, reg, tmpreg) \
+# endif
+# define PTR_MANGLE(dreg, reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg);					\
 	xor	reg, tmpreg, dreg
-#  define PTR_DEMANGLE(dreg, reg, tmpreg) PTR_MANGLE (dreg, reg, tmpreg)
-#  define PTR_MANGLE2(dreg, reg, tmpreg) \
+# define PTR_DEMANGLE(dreg, reg, tmpreg) PTR_MANGLE (dreg, reg, tmpreg)
+# define PTR_MANGLE2(dreg, reg, tmpreg) \
 	xor	reg, tmpreg, dreg
-#  define PTR_DEMANGLE2(dreg, reg, tmpreg) PTR_MANGLE2 (dreg, reg, tmpreg)
-# else
-#  include <stdint.h>
-#  ifdef SHARED
-extern uintptr_t __pointer_chk_guard attribute_relro;
-#   define PTR_MANGLE(var) \
-  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
-#  else
+# define PTR_DEMANGLE2(dreg, reg, tmpreg) PTR_MANGLE2 (dreg, reg, tmpreg)
+#else
+# include <stdint.h>
+# if IS_IN (rtld) || !defined SHARED
 extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
-#   define PTR_MANGLE(var) \
+#  define PTR_MANGLE(var) \
   (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
-#  endif
-#  define PTR_DEMANGLE(var)     PTR_MANGLE (var)
+# else
+extern uintptr_t __pointer_chk_guard attribute_relro;
+#  define PTR_MANGLE(var) \
+  (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
 # endif
+# define PTR_DEMANGLE(var)     PTR_MANGLE (var)
 #endif
 
 #endif /* POINTER_GUARD_H */