public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
To: libc-alpha@sourceware.org
Cc: Anderson Nascimento <anderson@allelesecurity.com>,
	Carlos O'Donell <carlos@redhat.com>
Subject: [PATCH 1/8] elf: Propagate the pointer guard to ld.so loaded via static dlopen (BZ 34196)
Date: Tue,  2 Jun 2026 21:04:32 -0300	[thread overview]
Message-ID: <20260603000656.3287796-2-adhemerval.zanella@linaro.org> (raw)
In-Reply-To: <20260603000656.3287796-1-adhemerval.zanella@linaro.org>

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
failures (a jmp_buf set up by the loaded ibc.so.6 cannot be restored
by the static program's __longjmp, and vice versa).

Seed the just-mapped loader's __pointer_chk_guard from the program's
__pointer_chk_guard_local in __rtld_static_init, next to the other
runtime values copied there.

Checked on aarch64-linux-gnu, x86_64-linux-gnu, and i686-linux-gnu.
---
 elf/Makefile                                  |  6 +++
 elf/rtld_static_init.c                        | 12 +++++
 elf/tst-ptrguard-static-dlopen-mod.c          | 29 +++++++++++
 elf/tst-ptrguard-static-dlopen.c              | 51 +++++++++++++++++++
 .../tst-ptrguard-static-dlopen.script         |  1 +
 5 files changed, 99 insertions(+)
 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

diff --git a/elf/Makefile b/elf/Makefile
index bdf9a786d54..a940b3045e5 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -270,6 +270,7 @@ tests-static-normal := \
   tst-env-setuid-static \
   tst-getauxval-static \
   tst-linkall-static \
+  tst-ptrguard-static-dlopen \
   tst-single_threaded-pthread-static \
   tst-single_threaded-static \
   tst-tls-allocation-failure-static \
@@ -576,6 +577,7 @@ tests-container += \
   tst-dlopen-tlsmodid-container \
   tst-pldd \
   tst-preload-pthread-libc \
+  tst-ptrguard-static-dlopen \
   tst-rootdir \
   # tests-container
 
@@ -1013,6 +1015,7 @@ modules-names += \
   tst-null-argv-lib \
   tst-p_alignmod-base \
   tst-p_alignmod3 \
+  tst-ptrguard-static-dlopen-mod \
   tst-recursive-tlsmallocmod \
   tst-recursive-tlsmod0 \
   tst-recursive-tlsmod1 \
@@ -3177,6 +3180,9 @@ $(objpfx)tst-tls21mod.so: $(tst-tls-many-dynamic-modules:%=$(objpfx)%.so)
 $(objpfx)tst-getauxval-static.out: $(objpfx)tst-auxvalmod.so
 tst-getauxval-static-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx)
 
+$(objpfx)tst-ptrguard-static-dlopen.out: \
+  $(objpfx)tst-ptrguard-static-dlopen-mod.so
+
 $(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so
 
 $(objpfx)tst-ro-dynamic: $(objpfx)tst-ro-dynamic-mod.so
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.  */
+			 "GLIBC_PRIVATE",
+			 0x0963cf85); /* _dl_elf_hash output.  */
+  if (guard_sym != NULL)
+    *(uintptr_t *) DL_SYMBOL_ADDRESS (map, guard_sym)
+	= __pointer_chk_guard_local;
+#endif
+
   __rtld_static_init_arch (map, dl);
 }
diff --git a/elf/tst-ptrguard-static-dlopen-mod.c b/elf/tst-ptrguard-static-dlopen-mod.c
new file mode 100644
index 00000000000..1b98e24d038
--- /dev/null
+++ b/elf/tst-ptrguard-static-dlopen-mod.c
@@ -0,0 +1,29 @@
+/* Shared object for the static-dlopen pointer guard test.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <setjmp.h>
+
+static jmp_buf jb;
+void (*do_longjmp) (jmp_buf);
+
+void
+foo (void)
+{
+  if (setjmp (jb) == 0)
+    do_longjmp (jb);
+}
diff --git a/elf/tst-ptrguard-static-dlopen.c b/elf/tst-ptrguard-static-dlopen.c
new file mode 100644
index 00000000000..5e4337b11cd
--- /dev/null
+++ b/elf/tst-ptrguard-static-dlopen.c
@@ -0,0 +1,51 @@
+/* Test that the pointer guard is propagated to ld.so via static dlopen.
+   Copyright (C) 2026 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+/* 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>
diff --git a/elf/tst-ptrguard-static-dlopen.root/tst-ptrguard-static-dlopen.script b/elf/tst-ptrguard-static-dlopen.root/tst-ptrguard-static-dlopen.script
new file mode 100644
index 00000000000..e4f49b34754
--- /dev/null
+++ b/elf/tst-ptrguard-static-dlopen.root/tst-ptrguard-static-dlopen.script
@@ -0,0 +1 @@
+cp $B/elf/tst-ptrguard-static-dlopen-mod.so $L/tst-ptrguard-static-dlopen-mod.so
-- 
2.43.0


  reply	other threads:[~2026-06-03  0:07 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-03  0:04 [PATCH 0/8] Pointer guard hardening and consolidation Adhemerval Zanella
2026-06-03  0:04 ` Adhemerval Zanella [this message]
2026-06-10  1:35   ` [PATCH 1/8] elf: Propagate the pointer guard to ld.so loaded via static dlopen (BZ 34196) DJ Delorie
2026-06-10 12:14     ` Adhemerval Zanella Netto
2026-06-30 18:15   ` Sachin Monga
2026-06-30 19:56     ` Adhemerval Zanella Netto
2026-06-03  0:04 ` [PATCH 2/8] Consolidate pointer guard to use a relro variable instead of the TCB Adhemerval Zanella
2026-06-10  3:03   ` DJ Delorie
2026-06-03  0:04 ` [PATCH 3/8] Enable the pointer guard in the dynamic loader Adhemerval Zanella
2026-06-10 19:37   ` DJ Delorie
2026-06-03  0:04 ` [PATCH 4/8] Split pointer_guard.h into C and assembly headers Adhemerval Zanella
2026-06-10 20:12   ` DJ Delorie
2026-06-03  0:04 ` [PATCH 5/8] Consolidate the C pointer guard implementation into the generic header Adhemerval Zanella
2026-06-10 21:14   ` DJ Delorie
2026-06-11 18:59     ` Adhemerval Zanella Netto
2026-06-03  0:04 ` [PATCH 6/8] Add the pointer guard rotate to the assembly implementations Adhemerval Zanella
2026-06-10 21:36   ` DJ Delorie
2026-06-12 14:18     ` Adhemerval Zanella Netto
2026-06-03  0:04 ` [PATCH 7/8] Consolidate dl-osinfo.h into the generic implementation Adhemerval Zanella
2026-06-10 21:43   ` DJ Delorie
2026-06-03  0:04 ` [PATCH 8/8] elf: Scrub and reseed the AT_RANDOM bytes after deriving the guards (BZ 34197) Adhemerval Zanella
2026-06-10 22:05   ` DJ Delorie
2026-06-11 19:57     ` Adhemerval Zanella Netto
2026-06-11 20:25       ` DJ Delorie
2026-06-11 20:36         ` Adhemerval Zanella Netto

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260603000656.3287796-2-adhemerval.zanella@linaro.org \
    --to=adhemerval.zanella@linaro.org \
    --cc=anderson@allelesecurity.com \
    --cc=carlos@redhat.com \
    --cc=libc-alpha@sourceware.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).