[PATCH 1/8] elf: Propagate the pointer guard to ld.so loaded via static dlopen (BZ 34196)

DJ Delorie dj@redhat.com
Wed Jun 10 01:35:31 GMT 2026


Adhemerval Zanella <adhemerval.zanella@linaro.org> writes:

> The static-dlopen does not initialize the pointer guard for ABIs that
> define THREAD_SET_POINTER_GUARD.  Besides not properly guard the
> pointer if a libc.so symbol is called, this can leads to setjmp

"can lead"

> failures (a jmp_buf set up by the loaded ibc.so.6 cannot be restored
> by the static program's __longjmp, and vice versa).

s/ibc/libc/

> diff --git a/elf/rtld_static_init.c b/elf/rtld_static_init.c
> index 04eb1c6fcc4..a428542e57e 100644
> --- a/elf/rtld_static_init.c
> +++ b/elf/rtld_static_init.c
> @@ -81,5 +81,17 @@ __rtld_static_init (struct link_map *map)
>    dl->_dl_find_object = _dl_find_object;
>    dl->_dl_readonly_area = _dl_readonly_area;
>  
> +#ifndef THREAD_SET_POINTER_GUARD
> +  extern uintptr_t __pointer_chk_guard_local attribute_hidden;
> +  const ElfW(Sym) *guard_sym
> +    = _dl_lookup_direct (map, "__pointer_chk_guard",
> +			 0x69f99cab, /* dl_new_hash output.  */

Missing _

> +			 "GLIBC_PRIVATE",
> +			 0x0963cf85); /* _dl_elf_hash output.  */
> +  if (guard_sym != NULL)

What do we do if it is NULL ?  Just ignore it?

> +    *(uintptr_t *) DL_SYMBOL_ADDRESS (map, guard_sym)
> +	= __pointer_chk_guard_local;

Do we need to check for DL_SYMBOL_ADDRESS() returning NULL?  The
definitions include such returns.

> diff --git a/elf/tst-ptrguard-static-dlopen-mod.c b/elf/tst-ptrguard-static-dlopen-mod.c
> @@ -0,0 +1,29 @@
> +#include <setjmp.h>
> +
> +static jmp_buf jb;
> +void (*do_longjmp) (jmp_buf);
> +
> +void
> +foo (void)
> +{
> +  if (setjmp (jb) == 0)
> +    do_longjmp (jb);
> +}

Ok.

> diff --git a/elf/tst-ptrguard-static-dlopen.c b/elf/tst-ptrguard-static-dlopen.c
> +/* A statically linked program dlopens a shared object; the object's setjmp
> +   uses the just-mapped libc.so's pointer guard while the longjmp below uses
> +   the program's guard.  Unless __rtld_static_init propagates the guard to
> +   the loaded loader the two differ, and the setjmp/longjmp round-trip jumps
> +   to a corrupt address and crashes.  */
> +
> +#include <setjmp.h>
> +#include <support/check.h>
> +#include <support/xdlfcn.h>
> +
> +static void
> +call_longjmp (jmp_buf jb)
> +{
> +  longjmp (jb, 1);
> +}
> +
> +static int
> +do_test (void)
> +{
> +  void *h = xdlopen ("tst-ptrguard-static-dlopen-mod.so", RTLD_NOW);
> +  void (*foo) (void) = xdlsym (h, "foo");
> +  void (**do_longjmp) (jmp_buf) = xdlsym (h, "do_longjmp");
> +  *do_longjmp = call_longjmp;
> +
> +  /* foo () sets the jump buffer and calls back into call_longjmp; a
> +     mismatched guard makes the return jump fault.  */
> +  foo ();
> +
> +  xdlclose (h);
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>

Ok.



More information about the Libc-alpha mailing list