[0/8] Pointer guard hardening and consolidation

Message ID 20260603000656.3287796-1-adhemerval.zanella@linaro.org (mailing list archive)
Headers
Series Pointer guard hardening and consolidation |

Message

Adhemerval Zanella Netto June 3, 2026, 12:04 a.m. UTC
  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			noop				noop				noop
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.

Testing: built with build-many-glibcs for all supported ABIs and ran the
test suite under emulation for x86_64, i686, aarch64, arm, powerpc64
(LE/BE), powerpc, s390x, sh4, sparc64, loongarch64, and alpha, plus the
Hurd (i686-gnu) build.

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
  Consolidate the C pointer guard implementation into the generic header
  Add the pointer guard rotate to 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                              |  4 +
 elf/Makefile                                  | 11 +++
 elf/rtld.c                                    |  6 +-
 elf/rtld_static_init.c                        | 12 +++
 elf/tst-atrandom-scrub-static.c               |  1 +
 elf/tst-atrandom-scrub.c                      | 74 ++++++++++++++++
 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/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/htl/tcb-offsets.sym              |  1 -
 sysdeps/i386/nptl/tcb-offsets.sym             |  1 -
 sysdeps/i386/nptl/tls.h                       | 10 +--
 sysdeps/i386/pointer_guard-asm.h              | 51 +++++++++++
 sysdeps/i386/stackguard-macros.h              | 10 ++-
 sysdeps/mach/hurd/i386/tls.h                  |  9 +-
 sysdeps/mach/hurd/x86_64/tls.h                |  8 +-
 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/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 ++++++++++
 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 ++-
 71 files changed, 1069 insertions(+), 901 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