[PATCH v2 0/8] Pointer guard hardening and consolidation

Adhemerval Zanella adhemerval.zanella@linaro.org
Fri Jun 12 16:10:08 GMT 2026


This series hardens the pointer guard (and, to a lesser extent, the stack
canary) and consolidates the current fragmented implementation.  Today the
pointer guard support is scattered across many per-architecture headers,
the assembly and C manglers do not agree, several architectures keep the
guard in the writable thread control block, and the dynamic loader uses a
no-op mangler on some targets.  The following table have summary:


		PTR_MANGLE (loader)		PTR_MANGLE (libc)		MANGLE / DEMANGLE
aarch64		__pointer_chk_guard_local	__pointer_chk_guard		val ^ pointer_guard
alpha		__pointer_chk_guard_local	__pointer_chk_guard		val ^ pointer_guard
arc		noop				noop				noop
arm		__pointer_chk_guard_local	__pointer_chk_guard		val ^ pointer_guard
csky		__pointer_chk_guard_local	__pointer_chk_guard		val ^ pointer_guard
hppa		noop				noop				noop
i386		noop				tcbhead_t->pointer_guard	stdc_rotate_left (val ^ pointer_guard, 9)
loongarch	__pointer_chk_guard_local	__pointer_chk_guard		val ^ pointer_guard
m68k		noop				noop				noop
microblaze	noop				noop				noop
mips		noop				noop				noop
or1k		noop				noop				noop
powerpc		noop				tcbhead_t->pointer_guard	val ^ tcbhead_t->pointer_guard
riscv		noop				noop				noop
s390		noop				tcbhead_t->pointer_guard	val ^ tcbhead_t->pointer_guard
sh		noop				tcbhead_t->pointer_guard	val ^ tcbhead_t->pointer_guard
sparc		noop				tcbhead_t->pointer_guard	val ^ tcbhead_t->pointer_guard
x86_64		__pointer_chk_guard_local	tcbhead_t->pointer_guard	stdc_rotate_left (val ^ pointer_guard, 17)

Along the way two latent defects are fixed: a crash with static
dlopen (BZ #34196) and an information leak that lets the guards be
recovered from AT_RANDOM (BZ #34197).

The high-level goals are:

* Keep the pointer guard in a read-only-after-relocation (relro) process
  variable instead of the writable TCB field, so it cannot be overwritten
  by a stray write into thread-local storage.

* Actually mangle pointers in the dynamic loader on every target, rather
  than leaving a no-op on some (it still depends whether setjmp does
  mangle the pointer).

* Make the assembly PTR_MANGLE/PTR_DEMANGLE match the generic C
  implementation (exclusive-or with the guard followed by a rotate), so
  the two domains agree and the mangling is identical everywhere.

* Collapse the duplicated per-architecture C and assembly headers into the
  generic ones, keeping only the genuinely arch-specific assembly bits.

* Stop leaking the guard material: scrub the AT_RANDOM bytes after the
  guards are derived from them, and refill them with fresh, unrelated
  entropy so getauxval (AT_RANDOM) keeps returning random bytes.

Changes from v1:

* Squash the C consolidation and assembly rotate patches so both
  manglers agree at every commit.

* New patch: do not demangle the jmp_buf stack pointer on arc, m68k,
  microblaze, mips, and riscv, whose setjmp stores it unmangled.

* i386: pass a dead scratch register to the assembly manglers instead
  of clobbering the callee-saved %ebx/%esi in setjmp (Hurd call sites
  updated as well).

* BZ #34196: assert the loaded ld.so exports __pointer_chk_guard.

* BZ #34197: clear the AT_RANDOM pointer through the argument, not the
  global; check guards and reseeded bytes are nonzero in the test.

Adhemerval Zanella (8):
  elf: Propagate the pointer guard to ld.so loaded via static dlopen (BZ
    34196)
  Consolidate pointer guard to use a relro variable instead of the TCB
  Enable the pointer guard in the dynamic loader
  Split pointer_guard.h into C and assembly headers
  Remove the jmp_buf stack pointer demangle on ABIs that do not mangle
    it
  Consolidate the C pointer guard and align the assembly implementations
  Consolidate dl-osinfo.h into the generic implementation
  elf: Scrub and reseed the AT_RANDOM bytes after deriving the guards
    (BZ 34197)

 csu/libc-start.c                              |  7 ++
 elf/Makefile                                  | 11 +++
 elf/rtld.c                                    |  9 +-
 elf/rtld_static_init.c                        | 12 +++
 elf/tst-atrandom-scrub-static.c               |  1 +
 elf/tst-atrandom-scrub.c                      | 89 +++++++++++++++++++
 elf/tst-ptrguard-static-dlopen-mod.c          | 29 ++++++
 elf/tst-ptrguard-static-dlopen.c              | 51 +++++++++++
 .../tst-ptrguard-static-dlopen.script         |  1 +
 sysdeps/alpha/__longjmp.S                     |  6 +-
 sysdeps/alpha/setjmp.S                        |  8 +-
 sysdeps/arc/jmpbuf-unwind.h                   |  7 +-
 sysdeps/arm/pointer_guard-asm.h               | 46 ++++++++++
 sysdeps/arm/pointer_guard.h                   | 67 --------------
 sysdeps/generic/dl-osinfo.h                   |  1 +
 sysdeps/generic/dl-reseed-random.h            | 34 +++++++
 sysdeps/generic/pointer_guard-asm.h           | 19 ++++
 sysdeps/generic/pointer_guard.h               | 32 +++++--
 sysdeps/i386/__longjmp.S                      |  4 +-
 sysdeps/i386/bsd-_setjmp.S                    |  6 +-
 sysdeps/i386/bsd-setjmp.S                     |  4 +-
 sysdeps/i386/htl/tcb-offsets.sym              |  1 -
 sysdeps/i386/nptl/tcb-offsets.sym             |  1 -
 sysdeps/i386/nptl/tls.h                       | 10 +--
 sysdeps/i386/pointer_guard-asm.h              | 59 ++++++++++++
 sysdeps/i386/setjmp.S                         |  4 +-
 sysdeps/i386/stackguard-macros.h              | 10 ++-
 sysdeps/m68k/jmpbuf-unwind.h                  |  7 +-
 sysdeps/mach/hurd/i386/____longjmp_chk.S      |  4 +-
 sysdeps/mach/hurd/i386/__longjmp.S            |  4 +-
 sysdeps/mach/hurd/i386/tls.h                  |  9 +-
 sysdeps/mach/hurd/x86_64/tls.h                |  8 +-
 sysdeps/microblaze/jmpbuf-unwind.h            |  7 +-
 sysdeps/mips/jmpbuf-unwind.h                  |  7 +-
 sysdeps/powerpc/nptl/tcb-offsets.sym          |  1 -
 sysdeps/powerpc/nptl/tls.h                    | 16 +---
 sysdeps/powerpc/powerpc32/stackguard-macros.h | 16 ++--
 sysdeps/powerpc/powerpc64/stackguard-macros.h | 16 ++--
 sysdeps/riscv/jmpbuf-unwind.h                 |  7 +-
 sysdeps/s390/__longjmp.c                      |  9 +-
 sysdeps/s390/nptl/tls.h                       |  7 --
 sysdeps/s390/stackguard-macros.h              | 20 ++---
 sysdeps/sh/nptl/tcb-offsets.sym               |  1 -
 sysdeps/sh/nptl/tls.h                         | 15 +---
 sysdeps/sh/stackguard-macros.h                |  8 +-
 sysdeps/sparc/nptl/tcb-offsets.sym            |  1 -
 sysdeps/sparc/nptl/tls.h                      | 10 +--
 sysdeps/sparc/sparc32/__longjmp.S             | 10 +--
 sysdeps/sparc/sparc32/setjmp.S                |  6 +-
 sysdeps/sparc/sparc32/stackguard-macros.h     |  9 +-
 sysdeps/sparc/sparc64/stackguard-macros.h     |  9 +-
 .../sysv/linux/aarch64/pointer_guard-asm.h    | 45 ++++++++++
 .../unix/sysv/linux/aarch64/pointer_guard.h   | 55 ------------
 .../unix/sysv/linux/alpha/____longjmp_chk.S   |  6 +-
 .../unix/sysv/linux/alpha/pointer_guard-asm.h | 52 +++++++++++
 sysdeps/unix/sysv/linux/alpha/pointer_guard.h | 62 -------------
 .../unix/sysv/linux/csky/pointer_guard-asm.h  | 57 ++++++++++++
 sysdeps/unix/sysv/linux/csky/pointer_guard.h  | 68 --------------
 sysdeps/unix/sysv/linux/dl-osinfo.h           | 54 -----------
 sysdeps/unix/sysv/linux/dl-parse_auxv.h       |  1 +
 sysdeps/unix/sysv/linux/dl-reseed-random.h    | 43 +++++++++
 .../unix/sysv/linux/i386/____longjmp_chk.S    |  4 +-
 sysdeps/unix/sysv/linux/i386/pointer_guard.h  | 55 ------------
 .../sysv/linux/loongarch/pointer_guard-asm.h  | 47 ++++++++++
 .../unix/sysv/linux/loongarch/pointer_guard.h | 70 ---------------
 .../sysv/linux/powerpc/pointer_guard-asm.h    | 85 ++++++++++++++++++
 .../unix/sysv/linux/powerpc/pointer_guard.h   | 55 ------------
 .../unix/sysv/linux/s390/____longjmp_chk.c    |  4 +-
 .../unix/sysv/linux/s390/pointer_guard-asm.h  | 49 ++++++++++
 sysdeps/unix/sysv/linux/s390/pointer_guard.h  | 47 ----------
 .../unix/sysv/linux/sh/pointer_guard-asm.h    | 70 +++++++++++++++
 sysdeps/unix/sysv/linux/sh/pointer_guard.h    | 43 ---------
 .../linux/sparc/sparc32/____longjmp_chk.S     |  6 +-
 .../linux/sparc/sparc32/pointer_guard-asm.h   | 60 +++++++++++++
 .../sysv/linux/sparc/sparc32/pointer_guard.h  | 44 ---------
 .../linux/sparc/sparc64/pointer_guard-asm.h   | 60 +++++++++++++
 .../sysv/linux/sparc/sparc64/pointer_guard.h  | 44 ---------
 .../unix/sysv/linux/x86_64/pointer_guard.h    | 78 ----------------
 sysdeps/x86_64/htl/tcb-offsets.sym            |  1 -
 sysdeps/x86_64/nptl/tcb-offsets.sym           |  1 -
 sysdeps/x86_64/nptl/tls.h                     | 10 +--
 sysdeps/x86_64/pointer_guard-asm.h            | 42 +++++++++
 sysdeps/x86_64/stackguard-macros.h            | 10 ++-
 83 files changed, 1128 insertions(+), 936 deletions(-)
 create mode 100644 elf/tst-atrandom-scrub-static.c
 create mode 100644 elf/tst-atrandom-scrub.c
 create mode 100644 elf/tst-ptrguard-static-dlopen-mod.c
 create mode 100644 elf/tst-ptrguard-static-dlopen.c
 create mode 100644 elf/tst-ptrguard-static-dlopen.root/tst-ptrguard-static-dlopen.script
 create mode 100644 sysdeps/arm/pointer_guard-asm.h
 delete mode 100644 sysdeps/arm/pointer_guard.h
 create mode 100644 sysdeps/generic/dl-reseed-random.h
 create mode 100644 sysdeps/generic/pointer_guard-asm.h
 create mode 100644 sysdeps/i386/pointer_guard-asm.h
 create mode 100644 sysdeps/unix/sysv/linux/aarch64/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/aarch64/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/alpha/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/alpha/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/csky/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/csky/pointer_guard.h
 delete mode 100644 sysdeps/unix/sysv/linux/dl-osinfo.h
 create mode 100644 sysdeps/unix/sysv/linux/dl-reseed-random.h
 delete mode 100644 sysdeps/unix/sysv/linux/i386/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/loongarch/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/loongarch/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/powerpc/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/powerpc/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/s390/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/s390/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/sh/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/sh/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc32/pointer_guard.h
 create mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard-asm.h
 delete mode 100644 sysdeps/unix/sysv/linux/sparc/sparc64/pointer_guard.h
 delete mode 100644 sysdeps/unix/sysv/linux/x86_64/pointer_guard.h
 create mode 100644 sysdeps/x86_64/pointer_guard-asm.h

-- 
2.43.0



More information about the Libc-alpha mailing list