[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