[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