[6/8] Add the pointer guard rotate to the assembly implementations

Message ID 20260603000656.3287796-7-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_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_glibc_check--master-aarch64 success Test 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
  The generic C PTR_MANGLE/PTR_DEMANGLE mangle a pointer with an
exclusive-or by the guard followed by a rotate left by
2 * sizeof (uintptr_t) + 1 bits (9 on 32-bit, 17 on 64-bit); a demangle
rotates right by the same amount before the exclusive-or.  The assembly
implementations only did the exclusive-or, so align them with the C one.

Targets with a rotate instruction (aarch64, arm, loongarch, powerpc,
s390, csky) just add it.  Those without one (alpha, sparc, sh) synthesize
the rotation: alpha and sparc with a shift/shift/or sequence, which needs
an extra scratch register added to the PTR_MANGLE/PTR_DEMANGLE macros and
their setjmp/__longjmp/____longjmp_chk call sites; sh with single-bit
rotates, which needs no scratch.  The s390 __longjmp and ____longjmp_chk
demangle the return address and stack pointer in C, so update those too.

Checked with setjmp, ptrguard and longjmp_chk tests for all supported
ABIs that can run under qemu (all but csky).
---
 sysdeps/alpha/__longjmp.S                     |  6 +--
 sysdeps/alpha/setjmp.S                        |  8 ++--
 sysdeps/arm/pointer_guard-asm.h               | 31 ++++++--------
 sysdeps/s390/__longjmp.c                      |  2 +
 sysdeps/sparc/sparc32/__longjmp.S             | 10 ++---
 sysdeps/sparc/sparc32/setjmp.S                |  6 +--
 .../sysv/linux/aarch64/pointer_guard-asm.h    | 20 +++++----
 .../unix/sysv/linux/alpha/____longjmp_chk.S   |  6 +--
 .../unix/sysv/linux/alpha/pointer_guard-asm.h | 37 +++++++++-------
 .../unix/sysv/linux/csky/pointer_guard-asm.h  | 42 ++++++++++---------
 .../sysv/linux/loongarch/pointer_guard-asm.h  | 35 +++++++---------
 .../sysv/linux/powerpc/pointer_guard-asm.h    | 31 +++++++++++---
 .../unix/sysv/linux/s390/____longjmp_chk.c    |  4 +-
 .../unix/sysv/linux/s390/pointer_guard-asm.h  | 13 ++++--
 .../unix/sysv/linux/sh/pointer_guard-asm.h    | 14 +++++--
 .../linux/sparc/sparc32/____longjmp_chk.S     |  6 +--
 .../linux/sparc/sparc32/pointer_guard-asm.h   | 21 +++++++---
 .../linux/sparc/sparc64/pointer_guard-asm.h   | 21 +++++++---
 18 files changed, 184 insertions(+), 129 deletions(-)
  

Comments

DJ Delorie June 10, 2026, 9:36 p.m. UTC | #1
See comment about logic change implications in previous review...

LGTM
Reviewed-by: DJ Delorie <dj@redhat.com>
  
Adhemerval Zanella Netto June 12, 2026, 2:18 p.m. UTC | #2
On 10/06/26 18:36, DJ Delorie wrote:
> 
> See comment about logic change implications in previous review...

Yeah, I think it for consistency it would be better to squash this patch witht
the previous one.

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

Patch

diff --git a/sysdeps/alpha/__longjmp.S b/sysdeps/alpha/__longjmp.S
index 0a18a37789c..f516e9ba614 100644
--- a/sysdeps/alpha/__longjmp.S
+++ b/sysdeps/alpha/__longjmp.S
@@ -53,9 +53,9 @@  ENTRY(__longjmp)
 	ldt     $f8, JB_F8*8(a0)
 	ldt     $f9, JB_F9*8(a0)
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE(ra, t1)
-	PTR_DEMANGLE2(t0, t1)
-	PTR_DEMANGLE2(fp, t1)
+	PTR_DEMANGLE(ra, t1, t2)
+	PTR_DEMANGLE2(t0, t1, t2)
+	PTR_DEMANGLE2(fp, t1, t2)
 #endif
 	cmoveq  v0, 1, v0
 	mov     t0, sp
diff --git a/sysdeps/alpha/setjmp.S b/sysdeps/alpha/setjmp.S
index 8dc3dacab44..bf228991daf 100644
--- a/sysdeps/alpha/setjmp.S
+++ b/sysdeps/alpha/setjmp.S
@@ -52,22 +52,22 @@  $sigsetjmp_local:
 	stq	s4, JB_S4*8(a0)
 	stq	s5, JB_S5*8(a0)
 #ifdef PTR_MANGLE
-	PTR_MANGLE(t1, ra, t0)
+	PTR_MANGLE(t1, ra, t0, t2)
 	stq	t1, JB_PC*8(a0)
 #else
 	stq	ra, JB_PC*8(a0)
 #endif
 #if defined(PTR_MANGLE) && FRAME == 0
-	PTR_MANGLE2(t1, sp, t0)
+	PTR_MANGLE2(t1, sp, t0, t2)
 #else
 	addq	sp, FRAME, t1
 # ifdef PTR_MANGLE
-	PTR_MANGLE2(t1, t1, t0)
+	PTR_MANGLE2(t1, t1, t0, t2)
 # endif
 #endif
 	stq	t1, JB_SP*8(a0)
 #ifdef PTR_MANGLE
-	PTR_MANGLE2(t1, fp, t0)
+	PTR_MANGLE2(t1, fp, t0, t2)
 	stq	t1, JB_FP*8(a0)
 #else
 	stq	fp, JB_FP*8(a0)
diff --git a/sysdeps/arm/pointer_guard-asm.h b/sysdeps/arm/pointer_guard-asm.h
index 86a9055b617..e34faa40ca2 100644
--- a/sysdeps/arm/pointer_guard-asm.h
+++ b/sysdeps/arm/pointer_guard-asm.h
@@ -24,30 +24,23 @@ 
       || (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
 #  define PTR_MANGLE_LOAD(guard, tmp)                                   \
   LDR_HIDDEN (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard_local), 0)
-#  define PTR_MANGLE(dst, src, guard, tmp)                              \
-  PTR_MANGLE_LOAD(guard, tmp);                                          \
-  PTR_MANGLE2(dst, src, guard)
-/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
-#  define PTR_MANGLE2(dst, src, guard)          \
-  eor dst, src, guard
-#  define PTR_DEMANGLE(dst, src, guard, tmp)    \
-  PTR_MANGLE (dst, src, guard, tmp)
-#  define PTR_DEMANGLE2(dst, src, guard)        \
-  PTR_MANGLE2 (dst, src, guard)
 # else
 #  define PTR_MANGLE_LOAD(guard, tmp)                                   \
-  LDR_GLOBAL (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard), 0);
-#  define PTR_MANGLE(dst, src, guard, tmp)                              \
+  LDR_GLOBAL (guard, tmp, C_SYMBOL_NAME(__pointer_chk_guard), 0)
+# endif
+# define PTR_MANGLE(dst, src, guard, tmp)                              \
   PTR_MANGLE_LOAD(guard, tmp);                                          \
   PTR_MANGLE2(dst, src, guard)
 /* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
-#  define PTR_MANGLE2(dst, src, guard)          \
-  eor dst, src, guard
-#  define PTR_DEMANGLE(dst, src, guard, tmp)    \
-  PTR_MANGLE (dst, src, guard, tmp)
-#  define PTR_DEMANGLE2(dst, src, guard)        \
-  PTR_MANGLE2 (dst, src, guard)
-# endif
+# define PTR_MANGLE2(dst, src, guard)          \
+  eor dst, src, guard;                         \
+  ror dst, dst, #23
+# define PTR_DEMANGLE(dst, src, guard, tmp)    \
+  PTR_MANGLE_LOAD(guard, tmp);                  \
+  PTR_DEMANGLE2(dst, src, guard)
+# define PTR_DEMANGLE2(dst, src, guard)        \
+  ror dst, src, #9;                            \
+  eor dst, dst, guard
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/s390/__longjmp.c b/sysdeps/s390/__longjmp.c
index 50d67bf42cc..cf59686579a 100644
--- a/sysdeps/s390/__longjmp.c
+++ b/sysdeps/s390/__longjmp.c
@@ -48,7 +48,9 @@  __longjmp (__jmp_buf env, int val)
 			   argument and target address.  */
 #ifdef PTR_DEMANGLE
 			"lmg  %%r4,%%r5,64(%1)\n\t"
+			"rllg %%r4,%%r4,47\n\t"
 			"xgr  %%r4,%2\n\t"
+			"rllg %%r5,%%r5,47\n\t"
 			"xgr  %%r5,%2\n\t"
 			LIBC_PROBE_ASM (longjmp, 8@%1 -4@%0 8@%%r4)
 #else
diff --git a/sysdeps/sparc/sparc32/__longjmp.S b/sysdeps/sparc/sparc32/__longjmp.S
index 732a250e4d2..c443011996e 100644
--- a/sysdeps/sparc/sparc32/__longjmp.S
+++ b/sysdeps/sparc/sparc32/__longjmp.S
@@ -28,7 +28,7 @@  ENTRY(__longjmp)
 
 	ld ENV(o0,JB_FP), %g3	/* Cache target FP in register %g3.  */
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE (%g3, %g3, %g4)
+	PTR_DEMANGLE (%g3, %g3, %g4, %g5)
 #endif
 	mov %o0, %g1		/* ENV in %g1 */
 	orcc %o1, %g0, %g2	/* VAL in %g2 */
@@ -66,8 +66,8 @@  LOC(thread):
 #ifdef PTR_DEMANGLE
 	ld	ENV(g1,JB_PC), %g5 /* Set return PC. */
 	ld	ENV(g1,JB_SP), %g1 /* Set saved SP on restore below. */
-	PTR_DEMANGLE2 (%i7, %g5, %g4)
-	PTR_DEMANGLE2 (%fp, %g1, %g4)
+	PTR_DEMANGLE2 (%i7, %g5, %g4, %g3)
+	PTR_DEMANGLE2 (%fp, %g1, %g4, %g3)
 #else
 	ld	ENV(g1,JB_PC), %i7 /* Set return PC. */
 	ld	ENV(g1,JB_SP), %fp /* Set saved SP on restore below. */
@@ -78,7 +78,7 @@  LOC(thread):
 LOC(found):
 	/* We have unwound register windows so %fp matches the target.  */
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE2 (%sp, %o0, %g4)
+	PTR_DEMANGLE2 (%sp, %o0, %g4, %g3)
 #else
 	mov %o0, %sp		/* OK, install new SP.  */
 #endif
@@ -86,7 +86,7 @@  LOC(found):
 LOC(sp_ok):
 	ld ENV(g1,JB_PC), %o0	/* Extract target return PC.  */
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE2 (%o0, %o0, %g4)
+	PTR_DEMANGLE2 (%o0, %o0, %g4, %g3)
 #endif
 	jmp %o0 + 8		/* Return there.  */
 	 mov %g2, %o0		/* Delay slot: set return value.  */
diff --git a/sysdeps/sparc/sparc32/setjmp.S b/sysdeps/sparc/sparc32/setjmp.S
index 5f2aec113ac..e389c5077e5 100644
--- a/sysdeps/sparc/sparc32/setjmp.S
+++ b/sysdeps/sparc/sparc32/setjmp.S
@@ -38,9 +38,9 @@  ENTRY (__sigsetjmp)
 	ta	ST_FLUSH_WINDOWS
 
 #ifdef PTR_MANGLE
-	PTR_MANGLE (%g1, %o7, %g4)
-	PTR_MANGLE2 (%g2, %sp, %g4)
-	PTR_MANGLE2 (%g3, %fp, %g4)
+	PTR_MANGLE (%g1, %o7, %g4, %g5)
+	PTR_MANGLE2 (%g2, %sp, %g4, %g5)
+	PTR_MANGLE2 (%g3, %fp, %g4, %g5)
 	st	%g1, [%o0 + (JB_PC * 4)]
 	st	%g2, [%o0 + (JB_SP * 4)]
 	st	%g3, [%o0 + (JB_FP * 4)]
diff --git a/sysdeps/unix/sysv/linux/aarch64/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/aarch64/pointer_guard-asm.h
index ed483a806a6..0fd26973412 100644
--- a/sysdeps/unix/sysv/linux/aarch64/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/aarch64/pointer_guard-asm.h
@@ -23,19 +23,23 @@ 
 # if (IS_IN (rtld) \
       || (!defined SHARED && (IS_IN (libc) \
                               || IS_IN (libpthread))))
-#  define PTR_MANGLE(dst, src, tmp)					    \
+#  define PTR_GUARD_LOAD(tmp)						    \
 	adrp    tmp, C_SYMBOL_NAME(__pointer_chk_guard_local);		    \
-	ldr	tmp, [tmp, :lo12:C_SYMBOL_NAME(__pointer_chk_guard_local)]; \
-	eor	dst, src, tmp
-#  define PTR_DEMANGLE(dst, src, tmp) PTR_MANGLE (dst, src, tmp)
+	ldr	tmp, [tmp, :lo12:C_SYMBOL_NAME(__pointer_chk_guard_local)]
 # else
-#  define PTR_MANGLE(dst, src, tmp)					  \
+#  define PTR_GUARD_LOAD(tmp)						  \
 	adrp	tmp, :got:C_SYMBOL_NAME(__pointer_chk_guard);		  \
 	ldr	tmp, [tmp, :got_lo12:C_SYMBOL_NAME(__pointer_chk_guard)]; \
-	ldr	tmp, [tmp];						  \
-	eor	dst, src, tmp;
-#  define PTR_DEMANGLE(dst, src, tmp) PTR_MANGLE (dst, src, tmp)
+	ldr	tmp, [tmp]
 # endif
+#  define PTR_MANGLE(dst, src, tmp)					    \
+	PTR_GUARD_LOAD (tmp);						    \
+	eor	dst, src, tmp;						    \
+	ror	dst, dst, #(64 - 17)
+#  define PTR_DEMANGLE(dst, src, tmp)					    \
+	PTR_GUARD_LOAD (tmp);						    \
+	ror	dst, src, #17;						    \
+	eor	dst, dst, tmp
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/alpha/____longjmp_chk.S b/sysdeps/unix/sysv/linux/alpha/____longjmp_chk.S
index 6661db76c9b..135eb10faa0 100644
--- a/sysdeps/unix/sysv/linux/alpha/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/alpha/____longjmp_chk.S
@@ -54,9 +54,9 @@  ____longjmp_chk:
 	cmoveq  s1, 1, s1
 
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE(s2, t1)
-	PTR_DEMANGLE2(s3, t1)
-	PTR_DEMANGLE2(fp, t1)
+	PTR_DEMANGLE(s2, t1, t2)
+	PTR_DEMANGLE2(s3, t1, t2)
+	PTR_DEMANGLE2(fp, t1, t2)
 #endif
 	/* ??? While this is a proper test for detecting a longjmp to an
 	   invalid frame within any given stack, the main thread stack is
diff --git a/sysdeps/unix/sysv/linux/alpha/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/alpha/pointer_guard-asm.h
index 15f9e6cacef..3ca56dd7aa4 100644
--- a/sysdeps/unix/sysv/linux/alpha/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/alpha/pointer_guard-asm.h
@@ -21,25 +21,32 @@ 
 
 #ifdef __ASSEMBLER__
 # if IS_IN (rtld)
-#  define PTR_MANGLE(dst, src, tmp)                             \
+#  define PTR_GUARD_LOAD(tmp)                                   \
         ldah    tmp, __pointer_chk_guard_local($29) !gprelhigh; \
-        ldq     tmp, __pointer_chk_guard_local(tmp) !gprellow;  \
-        xor     src, tmp, dst
-#  define PTR_MANGLE2(dst, src, tmp)                            \
-        xor     src, tmp, dst
+        ldq     tmp, __pointer_chk_guard_local(tmp) !gprellow
 # elif defined SHARED
-#  define PTR_MANGLE(dst, src, tmp)             \
-        ldq     tmp, __pointer_chk_guard;       \
-        xor     src, tmp, dst
+#  define PTR_GUARD_LOAD(tmp)                   \
+        ldq     tmp, __pointer_chk_guard
 # else
-#  define PTR_MANGLE(dst, src, tmp)             \
-        ldq     tmp, __pointer_chk_guard_local; \
-        xor     src, tmp, dst
+#  define PTR_GUARD_LOAD(tmp)                   \
+        ldq     tmp, __pointer_chk_guard_local
 # endif
-# define PTR_MANGLE2(dst, src, tmp)             \
-        xor     src, tmp, dst
-# define PTR_DEMANGLE(dst, tmp)   PTR_MANGLE(dst, dst, tmp)
-# define PTR_DEMANGLE2(dst, tmp)  PTR_MANGLE2(dst, dst, tmp)
+# define PTR_MANGLE(dst, src, tmp, tmp2)        \
+        PTR_GUARD_LOAD (tmp);                   \
+        PTR_MANGLE2 (dst, src, tmp, tmp2)
+# define PTR_MANGLE2(dst, src, tmp, tmp2)       \
+        xor     src, tmp, dst;                  \
+        sll     dst, 17, tmp2;                  \
+        srl     dst, 47, dst;                   \
+        bis     dst, tmp2, dst
+# define PTR_DEMANGLE(dst, tmp, tmp2)           \
+        PTR_GUARD_LOAD (tmp);                   \
+        PTR_DEMANGLE2 (dst, tmp, tmp2)
+# define PTR_DEMANGLE2(dst, tmp, tmp2)          \
+        sll     dst, 47, tmp2;                  \
+        srl     dst, 17, dst;                   \
+        bis     dst, tmp2, dst;                 \
+        xor     dst, tmp, dst
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/csky/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/csky/pointer_guard-asm.h
index 8eb6d2c1d42..074251cbdf8 100644
--- a/sysdeps/unix/sysv/linux/csky/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/csky/pointer_guard-asm.h
@@ -22,34 +22,36 @@ 
 #ifdef __ASSEMBLER__
 # if (IS_IN (rtld) \
       || (!defined SHARED && (IS_IN (libc) || IS_IN (libpthread))))
-#  define PTR_MANGLE(dst, src, guard)                   \
+#  define PTR_MANGLE_LOAD(guard)                        \
         grs     t0, 1f;                                 \
 1:                                                      \
         lrw     guard, 1b@GOTPC;                        \
         addu    t0, guard;                              \
         lrw     guard, __pointer_chk_guard_local@GOT;   \
         ldr.w   guard, (t0, guard << 0);                \
-        ldw     guard, (guard, 0);                      \
-        xor     dst, src, guard;
-#  define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
-#  define PTR_MANGLE2(dst, src, guard) \
-        xor     dst, src, guard
-#  define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
+        ldw     guard, (guard, 0);
 # else
-#  define PTR_MANGLE(dst, src, guard)           \
-        grs     t0, 1f;                         \
-1:                                              \
-        lrw     guard, 1b@GOTPC;                \
-        addu    t0, guard;                      \
-        lrw     guard, __pointer_chk_guard@GOT; \
-        ldr.w   guard, (t0, guard << 0);        \
-        ldw     guard, (guard, 0);              \
-        xor     dst, src, guard;
-#  define PTR_DEMANGLE(dst, src, guard) PTR_MANGLE (dst, src, guard)
-#  define PTR_MANGLE2(dst, src, guard) \
-        xor     dst, src, guard
-#  define PTR_DEMANGLE2(dst, src, guard) PTR_MANGLE2 (dst, src, guard)
+#  define PTR_MANGLE_LOAD(guard)                        \
+        grs     t0, 1f;                                 \
+1:                                                      \
+        lrw     guard, 1b@GOTPC;                        \
+        addu    t0, guard;                              \
+        lrw     guard, __pointer_chk_guard@GOT;         \
+        ldr.w   guard, (t0, guard << 0);                \
+        ldw     guard, (guard, 0);
 # endif
+# define PTR_MANGLE(dst, src, guard)                    \
+        PTR_MANGLE_LOAD (guard);                        \
+        PTR_MANGLE2 (dst, src, guard)
+# define PTR_MANGLE2(dst, src, guard)                   \
+        xor     dst, src, guard;                        \
+        rotli   dst, dst, 9
+# define PTR_DEMANGLE(dst, src, guard)                  \
+        PTR_MANGLE_LOAD (guard);                        \
+        PTR_DEMANGLE2 (dst, src, guard)
+# define PTR_DEMANGLE2(dst, src, guard)                 \
+        rotli   dst, src, 23;                           \
+        xor     dst, dst, guard
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/loongarch/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/loongarch/pointer_guard-asm.h
index ac55dd8c95c..75498545cb9 100644
--- a/sysdeps/unix/sysv/linux/loongarch/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/loongarch/pointer_guard-asm.h
@@ -23,30 +23,25 @@ 
 # if (IS_IN (rtld) \
       || (!defined SHARED && (IS_IN (libc) \
       || IS_IN (libpthread))))
-#  define PTR_MANGLE(dst, src, guard) \
-  LOAD_LOCAL (guard, __pointer_chk_guard_local); \
-  PTR_MANGLE2 (dst, src, guard);
-#  define PTR_DEMANGLE(dst, src, guard) \
-  LOAD_LOCAL (guard, __pointer_chk_guard_local); \
-  PTR_DEMANGLE2 (dst, src, guard);
-/* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
-#  define PTR_MANGLE2(dst, src, guard) \
-  xor  dst, src, guard;
-#  define PTR_DEMANGLE2(dst, src, guard) \
-  PTR_MANGLE2 (dst, src, guard);
+#  define PTR_MANGLE_LOAD(guard) \
+  LOAD_LOCAL (guard, __pointer_chk_guard_local);
 # else
-#  define PTR_MANGLE(dst, src, guard) \
-  LOAD_GLOBAL (guard, __pointer_chk_guard); \
+#  define PTR_MANGLE_LOAD(guard) \
+  LOAD_GLOBAL (guard, __pointer_chk_guard);
+# endif
+# define PTR_MANGLE(dst, src, guard) \
+  PTR_MANGLE_LOAD (guard); \
   PTR_MANGLE2 (dst, src, guard);
-#  define PTR_DEMANGLE(dst, src, guard) \
-  LOAD_GLOBAL (guard, __pointer_chk_guard); \
+# define PTR_DEMANGLE(dst, src, guard) \
+  PTR_MANGLE_LOAD (guard); \
   PTR_DEMANGLE2 (dst, src, guard);
 /* Use PTR_MANGLE2 for efficiency if guard is already loaded.  */
-#  define PTR_MANGLE2(dst, src, guard) \
-  xor dst, src, guard;
-#  define PTR_DEMANGLE2(dst, src, guard) \
-  PTR_MANGLE2 (dst, src, guard);
-# endif
+# define PTR_MANGLE2(dst, src, guard) \
+  xor  dst, src, guard; \
+  rotri.d  dst, dst, 47;
+# define PTR_DEMANGLE2(dst, src, guard) \
+  rotri.d  dst, src, 17; \
+  xor  dst, dst, guard;
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/powerpc/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/powerpc/pointer_guard-asm.h
index ca4278cc00a..962ad10e596 100644
--- a/sysdeps/unix/sysv/linux/powerpc/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/powerpc/pointer_guard-asm.h
@@ -50,17 +50,36 @@ 
 	lwz	tmpreg,PTR_GUARD_SYM@l(tmpreg)
 # endif
 
+# if defined(__PPC64__) || defined(__powerpc64__)
+#  define PTR_ROT_MANGLE(dst, src)	rotldi	dst,src,17
+#  define PTR_ROT_DEMANGLE(dst, src)	rotldi	dst,src,47
+# else
+#  define PTR_ROT_MANGLE(dst, src)	rotlwi	dst,src,9
+#  define PTR_ROT_DEMANGLE(dst, src)	rotlwi	dst,src,23
+# endif
+
 # define PTR_MANGLE(reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg); \
-	xor	reg,tmpreg,reg
+	xor	reg,tmpreg,reg; \
+	PTR_ROT_MANGLE (reg, reg)
 # define PTR_MANGLE2(reg, tmpreg) \
-	xor	reg,tmpreg,reg
+	xor	reg,tmpreg,reg; \
+	PTR_ROT_MANGLE (reg, reg)
 # 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)
+	xor	destreg,tmpreg,reg; \
+	PTR_ROT_MANGLE (destreg, destreg)
+# define PTR_DEMANGLE(reg, tmpreg) \
+	PTR_GUARD_LOAD (tmpreg); \
+	PTR_ROT_DEMANGLE (reg, reg); \
+	xor	reg,tmpreg,reg
+# define PTR_DEMANGLE2(reg, tmpreg) \
+	PTR_ROT_DEMANGLE (reg, reg); \
+	xor	reg,tmpreg,reg
+# define PTR_DEMANGLE3(destreg, reg, tmpreg) \
+	PTR_GUARD_LOAD (tmpreg); \
+	PTR_ROT_DEMANGLE (destreg, reg); \
+	xor	destreg,tmpreg,destreg
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/s390/____longjmp_chk.c b/sysdeps/unix/sysv/linux/s390/____longjmp_chk.c
index 4186114844d..7ee7bf71cff 100644
--- a/sysdeps/unix/sysv/linux/s390/____longjmp_chk.c
+++ b/sysdeps/unix/sysv/linux/s390/____longjmp_chk.c
@@ -23,6 +23,7 @@ 
 #include <unistd.h>
 #include <stdio.h>
 #include <stdint.h>
+#include <stdbit.h>
 #include <signal.h>
 #include <sys/syscall.h>
 
@@ -34,7 +35,8 @@ 
       uintptr_t cur_sp;							\
       uintptr_t new_sp = env->__gregs[9];				\
       __asm__ ("lgr %0, %%r15" : "=r" (cur_sp));			\
-      new_sp ^= guard;							\
+      new_sp = stdc_rotate_right (new_sp, 2 * sizeof (uintptr_t) + 1)	\
+	       ^ guard;							\
       if (new_sp < cur_sp)						\
 	{								\
 	  stack_t oss;							\
diff --git a/sysdeps/unix/sysv/linux/s390/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/s390/pointer_guard-asm.h
index 71cc0465d13..44c9a2a156b 100644
--- a/sysdeps/unix/sysv/linux/s390/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/s390/pointer_guard-asm.h
@@ -32,11 +32,18 @@ 
 # endif
 # define PTR_MANGLE(reg, tmpreg) \
 	PTR_GUARD_LOAD (tmpreg);					\
-	xgr	reg,tmpreg
+	xgr	reg,tmpreg;						\
+	rllg	reg,reg,17
 # define PTR_MANGLE2(reg, tmpreg) \
+	xgr	reg,tmpreg;						\
+	rllg	reg,reg,17
+# define PTR_DEMANGLE(reg, tmpreg) \
+	PTR_GUARD_LOAD (tmpreg);					\
+	rllg	reg,reg,47;						\
+	xgr	reg,tmpreg
+# define PTR_DEMANGLE2(reg, tmpreg) \
+	rllg	reg,reg,47;						\
 	xgr	reg,tmpreg
-# define PTR_DEMANGLE(reg, tmpreg) PTR_MANGLE (reg, tmpreg)
-# define PTR_DEMANGLE2(reg, tmpreg) PTR_MANGLE2 (reg, tmpreg)
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/sh/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/sh/pointer_guard-asm.h
index 64e6f6153e8..f6002efdead 100644
--- a/sysdeps/unix/sysv/linux/sh/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/sh/pointer_guard-asm.h
@@ -55,10 +55,16 @@ 
 .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)
+     PTR_GUARD_LOAD (tmp); PTR_MANGLE2 (reg, tmp)
+# define PTR_MANGLE2(reg, tmp) \
+     xor tmp,reg;							\
+     rotl reg; rotl reg; rotl reg; rotl reg; rotl reg;			\
+     rotl reg; rotl reg; rotl reg; rotl reg
+# define PTR_DEMANGLE(reg, tmp)        PTR_GUARD_LOAD (tmp); PTR_DEMANGLE2 (reg, tmp)
+# define PTR_DEMANGLE2(reg, tmp) \
+     rotr reg; rotr reg; rotr reg; rotr reg; rotr reg;			\
+     rotr reg; rotr reg; rotr reg; rotr reg;				\
+     xor tmp,reg
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/____longjmp_chk.S b/sysdeps/unix/sysv/linux/sparc/sparc32/____longjmp_chk.S
index b0c6160bd28..07baa0c9ed2 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/____longjmp_chk.S
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/____longjmp_chk.S
@@ -32,7 +32,7 @@  longjmp_msg:
 ENTRY (____longjmp_chk)
 	ld	ENV(o0,JB_SP), %g5
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE (%g5, %g5, %g4)
+	PTR_DEMANGLE (%g5, %g5, %g4, %g3)
 #endif
 
 	cmp	%sp, %g5
@@ -82,7 +82,7 @@  ENTRY (____longjmp_chk)
 .Lok_norestore:
 	ld	ENV(o0,JB_FP), %g3	/* Cache target FP in register %g3.  */
 #ifdef PTR_DEMANGLE
-	PTR_DEMANGLE2 (%g3, %g3, %g4)
+	PTR_DEMANGLE2 (%g3, %g3, %g4, %g1)
 #endif
 
 	mov %o0, %g1		/* ENV in %g1 */
@@ -103,7 +103,7 @@  ENTRY (____longjmp_chk)
 	ta	ST_FLUSH_WINDOWS
 #ifdef PTR_DEMANGLE
 	ld	ENV(g1,JB_PC), %g1 /* Set return PC. */
-	PTR_DEMANGLE2 (%i7, %g1, %g4)
+	PTR_DEMANGLE2 (%i7, %g1, %g4, %g3)
 #else
 	ld	ENV(g1,JB_PC), %i7 /* Set return PC. */
 #endif
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard-asm.h
index e1e42f8087a..aa2b7609c92 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard-asm.h
@@ -39,13 +39,22 @@ 
 	sethi	%hi(PTR_GUARD_SYM), tmpreg;				\
 	ld	[tmpreg + %lo(PTR_GUARD_SYM)], tmpreg
 # endif
-# define PTR_MANGLE(dreg, reg, tmpreg) \
+# define PTR_MANGLE(dreg, reg, tmpreg, tmp2) \
 	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) \
-	xor	reg, tmpreg, dreg
-# define PTR_DEMANGLE2(dreg, reg, tmpreg) PTR_MANGLE2 (dreg, reg, tmpreg)
+	PTR_MANGLE2 (dreg, reg, tmpreg, tmp2)
+# define PTR_MANGLE2(dreg, reg, tmpreg, tmp2) \
+	xor	reg, tmpreg, dreg;					\
+	sll	dreg, 9, tmp2;						\
+	srl	dreg, 23, dreg;						\
+	or	dreg, tmp2, dreg
+# define PTR_DEMANGLE(dreg, reg, tmpreg, tmp2) \
+	PTR_GUARD_LOAD (tmpreg);					\
+	PTR_DEMANGLE2 (dreg, reg, tmpreg, tmp2)
+# define PTR_DEMANGLE2(dreg, reg, tmpreg, tmp2) \
+	srl	reg, 9, tmp2;						\
+	sll	reg, 23, dreg;						\
+	or	dreg, tmp2, dreg;					\
+	xor	dreg, tmpreg, dreg
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard-asm.h b/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard-asm.h
index f378c88e58c..ef5b38f541b 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard-asm.h
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard-asm.h
@@ -39,13 +39,22 @@ 
 	sethi	%hi(PTR_GUARD_SYM), tmpreg;				\
 	ldx	[tmpreg + %lo(PTR_GUARD_SYM)], tmpreg
 # endif
-# define PTR_MANGLE(dreg, reg, tmpreg) \
+# define PTR_MANGLE(dreg, reg, tmpreg, tmp2) \
 	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) \
-	xor	reg, tmpreg, dreg
-# define PTR_DEMANGLE2(dreg, reg, tmpreg) PTR_MANGLE2 (dreg, reg, tmpreg)
+	PTR_MANGLE2 (dreg, reg, tmpreg, tmp2)
+# define PTR_MANGLE2(dreg, reg, tmpreg, tmp2) \
+	xor	reg, tmpreg, dreg;					\
+	sllx	dreg, 17, tmp2;						\
+	srlx	dreg, 47, dreg;						\
+	or	dreg, tmp2, dreg
+# define PTR_DEMANGLE(dreg, reg, tmpreg, tmp2) \
+	PTR_GUARD_LOAD (tmpreg);					\
+	PTR_DEMANGLE2 (dreg, reg, tmpreg, tmp2)
+# define PTR_DEMANGLE2(dreg, reg, tmpreg, tmp2) \
+	srlx	reg, 17, tmp2;						\
+	sllx	reg, 47, dreg;						\
+	or	dreg, tmp2, dreg;					\
+	xor	dreg, tmpreg, dreg
 #endif
 
 #endif /* POINTER_GUARD_ASM_H */