<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>