<div dir="auto"><div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Mon, May 27, 2024, 10:38 PM H.J. Lu <<a href="mailto:hjl.tools@gmail.com">hjl.tools@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">When a static PIE is loaded at the specific address, its PT_DYNAMIC<br>
segment entries contain the relocated values for the load address.<br>
Compute the load address from the p_vaddr of the PT_LOAD segement<br>
which covers the file start.  This fixes BZ #31799.<br>
<br>
Signed-off-by: H.J. Lu <<a href="mailto:hjl.tools@gmail.com" target="_blank" rel="noreferrer">hjl.tools@gmail.com</a>><br>
---<br>
 configure                    | 67 ++++++++++++++++++++++++++++++++++++<br>
 <a href="http://configure.ac" rel="noreferrer noreferrer" target="_blank">configure.ac</a>                 | 30 ++++++++++++++++<br>
 elf/Makefile                 | 20 +++++++++++<br>
 elf/dl-reloc-static-pie.c    | 25 ++++++++++----<br>
 elf/tst-pie-address-static.c | 19 ++++++++++<br>
 elf/tst-pie-address.c        | 28 +++++++++++++++<br>
 6 files changed, 182 insertions(+), 7 deletions(-)<br>
 create mode 100644 elf/tst-pie-address-static.c<br>
 create mode 100644 elf/tst-pie-address.c<br>
<br>
diff --git a/configure b/configure<br>
index 49b093043c..612fa0cf77 100755<br>
--- a/configure<br>
+++ b/configure<br>
@@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }<br>
 config_vars="$config_vars<br>
 cc-pie-default = $libc_cv_cc_pie_default"<br>
<br>
+# Get PDE load address.<br>
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5<br>
+printf %s "checking PDE load address... " >&6; }<br>
+if test ${libc_cv_pde_load_address+y}<br>
+then :<br>
+  printf %s "(cached) " >&6<br>
+else $as_nop<br>
+  cat > conftest.S <<EOF<br>
+.globl _start<br>
+_start:<br>
+.globl __start<br>
+__start:<br>
+EOF<br>
+if test $libc_cv_cc_pie_default = yes; then<br>
+  pde_ld_flags="-no-pie"<br>
+fi<br>
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \<br>
+           -nostartfiles -nostdlib $no_ssp \<br>
+           -o conftest conftest.S 1>&5 2>&5; then<br>
+  # Get the load address of the first PT_LOAD segment.<br>
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \<br>
+                            | $AWK '/LOAD/ { print $3; exit 0; }')<br>
+else<br>
+  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5<br>
+fi<br>
+rm -f conftest*<br>
+fi<br>
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5<br>
+printf "%s\n" "$libc_cv_pde_load_address" >&6; }<br>
+config_vars="$config_vars<br>
+pde-load-address = $libc_cv_pde_load_address"<br>
+<br>
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5<br>
+printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }<br>
+libc_linker_feature=no<br>
+cat > conftest.c <<EOF<br>
+int _start (void) { return 42; }<br>
+EOF<br>
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp<br>
+                 -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles<br>
+                 -fPIC -shared -o conftest.so conftest.c<br>
+                 1>&5'<br>
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5<br>
+  (eval $ac_try) 2>&5<br>
+  ac_status=$?<br>
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5<br>
+  test $ac_status = 0; }; }<br>
+then<br>
+  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \<br>
+      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \<br>
+      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then<br>
+    true<br>
+  else<br>
+    libc_linker_feature=yes<br>
+  fi<br>
+fi<br>
+rm -f conftest*<br>
+if test $libc_linker_feature = yes; then<br>
+  libc_cv_load_address=-Wl,-Ttext-segment<br>
+else<br>
+  libc_cv_load_address=<br>
+fi<br>
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5<br>
+printf "%s\n" "$libc_linker_feature" >&6; }<br>
+config_vars="$config_vars<br>
+load-address-ldflag = $libc_cv_load_address"<br>
+<br>
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5<br>
 printf %s "checking if we can build programs as PIE... " >&6; }<br>
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext<br>
diff --git a/<a href="http://configure.ac" rel="noreferrer noreferrer" target="_blank">configure.ac</a> b/<a href="http://configure.ac" rel="noreferrer noreferrer" target="_blank">configure.ac</a><br>
index e48957f318..89a2f5d842 100644<br>
--- a/<a href="http://configure.ac" rel="noreferrer noreferrer" target="_blank">configure.ac</a><br>
+++ b/<a href="http://configure.ac" rel="noreferrer noreferrer" target="_blank">configure.ac</a><br>
@@ -1721,6 +1721,36 @@ fi<br>
 rm -f conftest.*])<br>
 LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])<br>
<br>
+# Get PDE load address.<br>
+AC_CACHE_CHECK([PDE load address],<br>
+              libc_cv_pde_load_address, [dnl<br>
+cat > conftest.S <<EOF<br>
+.globl _start<br>
+_start:<br>
+.globl __start<br>
+__start:<br>
+EOF<br>
+if test $libc_cv_cc_pie_default = yes; then<br>
+  pde_ld_flags="-no-pie"<br>
+fi<br>
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \<br>
+           -nostartfiles -nostdlib $no_ssp \<br>
+           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then<br>
+  # Get the load address of the first PT_LOAD segment.<br>
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \<br>
+                            | $AWK '/LOAD/ { print $3; exit 0; }')<br>
+else<br>
+  AC_MSG_ERROR([${CC-cc} can not create PDE])<br>
+fi<br>
+rm -f conftest*])<br>
+LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])<br>
+<br>
+LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],<br>
+                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],<br>
+                   [libc_cv_load_address=-Wl,-Ttext-segment],<br>
+                   [libc_cv_load_address=])<br>
+LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])<br>
+<br>
 AC_MSG_CHECKING(if we can build programs as PIE)<br>
 AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED<br>
 # error PIE is not supported<br>
diff --git a/elf/Makefile b/elf/Makefile<br>
index 57b3a19d36..4e2d123b8e 100644<br>
--- a/elf/Makefile<br>
+++ b/elf/Makefile<br>
@@ -1046,6 +1046,25 @@ tests-pie += \<br>
   tst-pie1 \<br>
   tst-pie2 \<br>
   # tests-pie<br>
+ifneq (,$(load-address-ldflag))<br>
+tests += \<br>
+  tst-pie-address \<br>
+  # tests<br>
+tests-pie += \<br>
+  tst-pie-address \<br>
+  # tests-pie<br>
+LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)<br>
+ifeq (yes,$(enable-static-pie))<br>
+tests += \<br>
+  tst-pie-address-static \<br>
+  # tests<br>
+tests-static += \<br>
+  tst-pie-address-static \<br>
+  # tests-static<br>
+LDFLAGS-tst-pie-address-static += \<br>
+  $(load-address-ldflag)=$(pde-load-address)<br>
+endif<br>
+endif<br>
 ifeq (yes,$(have-protected-data))<br>
 tests += vismain<br>
 tests-pie += vismain<br>
@@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \<br>
<br>
 CFLAGS-tst-pie1.c += $(pie-ccflag)<br>
 CFLAGS-tst-pie2.c += $(pie-ccflag)<br>
+CFLAGS-tst-pie-address.c += $(pie-ccflag)<br>
<br>
 $(objpfx)tst-piemod1.so: $(libsupport)<br>
 $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so<br>
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c<br>
index 10c23d0bf0..6286f19f1f 100644<br>
--- a/elf/dl-reloc-static-pie.c<br>
+++ b/elf/dl-reloc-static-pie.c<br>
@@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)<br>
 {<br>
   struct link_map *main_map = _dl_get_dl_main_map ();<br>
<br>
-  /* Figure out the run-time load address of static PIE.  */<br>
-  main_map->l_addr = elf_machine_load_address ();<br>
-<br>
-  /* Read our own dynamic section and fill in the info array.  */<br>
-  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());<br>
-<br>
+  ElfW(Addr) file_p_vaddr = 0;<br>
   const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);<br>
   size_t phnum = GL(dl_phnum);<br>
   for (ph = phdr; ph < &phdr[phnum]; ++ph)<br>
-    if (ph->p_type == PT_DYNAMIC)<br>
+    switch (ph->p_type)<br>
       {<br>
+      case PT_LOAD:<br>
+       /* Get p_vaddr of the PT_LOAD segement which covers the file<br>
+          start.  */<br>
+       if (ph->p_offset == 0)<br>
+         file_p_vaddr = ph->p_vaddr;<br>
+       break;<br>
+      case PT_DYNAMIC:<br>
        main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;<br>
        break;<br>
+      default:<br>
+       break;<br>
       }<br>
<br>
+  /* Figure out the run-time load address of static PIE.  */<br>
+  ElfW(Addr) l_addr = elf_machine_load_address ();<br>
+  main_map->l_addr = l_addr - file_p_vaddr;<br>
+<br>
+  /* Read our own dynamic section and fill in the info array.  */<br>
+  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());<br>
+<br>
   elf_get_dynamic_info (main_map, false, true);<br>
<br>
 # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC<br>
diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c<br>
new file mode 100644<br>
index 0000000000..25d27fb962<br>
--- /dev/null<br>
+++ b/elf/tst-pie-address-static.c<br>
@@ -0,0 +1,19 @@<br>
+/* Test static PIE loaded at the specific address.<br>
+   Copyright (C) 2024 Free Software Foundation, Inc.<br>
+   This file is part of the GNU C Library.<br>
+<br>
+   The GNU C Library is free software; you can redistribute it and/or<br>
+   modify it under the terms of the GNU Lesser General Public<br>
+   License as published by the Free Software Foundation; either<br>
+   version 2.1 of the License, or (at your option) any later version.<br>
+<br>
+   The GNU C Library is distributed in the hope that it will be useful,<br>
+   but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
+   Lesser General Public License for more details.<br>
+<br>
+   You should have received a copy of the GNU Lesser General Public<br>
+   License along with the GNU C Library; if not, see<br>
+   <<a href="https://www.gnu.org/licenses/" rel="noreferrer noreferrer" target="_blank">https://www.gnu.org/licenses/</a>>.  */<br>
+<br>
+#include "tst-pie-address.c"<br>
diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c<br>
new file mode 100644<br>
index 0000000000..1f01783631<br>
--- /dev/null<br>
+++ b/elf/tst-pie-address.c<br>
@@ -0,0 +1,28 @@<br>
+/* Test PIE loaded at the specific address.<br>
+   Copyright (C) 2024 Free Software Foundation, Inc.<br>
+   This file is part of the GNU C Library.<br>
+<br>
+   The GNU C Library is free software; you can redistribute it and/or<br>
+   modify it under the terms of the GNU Lesser General Public<br>
+   License as published by the Free Software Foundation; either<br>
+   version 2.1 of the License, or (at your option) any later version.<br>
+<br>
+   The GNU C Library is distributed in the hope that it will be useful,<br>
+   but WITHOUT ANY WARRANTY; without even the implied warranty of<br>
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU<br>
+   Lesser General Public License for more details.<br>
+<br>
+   You should have received a copy of the GNU Lesser General Public<br>
+   License along with the GNU C Library; if not, see<br>
+   <<a href="https://www.gnu.org/licenses/" rel="noreferrer noreferrer" target="_blank">https://www.gnu.org/licenses/</a>>.  */<br>
+<br>
+#include <stdio.h><br>
+<br>
+static int<br>
+do_test (void)<br>
+{<br>
+  printf ("Hello\n");<br>
+  return 0;<br>
+}<br>
+<br>
+#include <support/test-driver.c><br>
-- <br>
2.45.1<br></blockquote></div></div><div dir="auto"><br></div><div dir="auto">Ping.</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
</blockquote></div></div></div>