public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH v5 0/1] elf: Handle static PIE loaded at the specific address
@ 2024-05-27 14:38 H.J. Lu
  2024-05-27 14:38 ` [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799] H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-05-27 14:38 UTC (permalink / raw)
  To: libc-alpha; +Cc: fweimer

Changes in v5:

1. Compute the load address from the p_vaddr of the PT_LOAD segement
which covers the file start, instead of checking the e_type field in
the ELF header.
2. Use $AWK '/LOAD/ { print $3; exit 0; }'.

---
When a static PIE is loaded at the specific address, its PT_DYNAMIC
segment entries contain the relocated values for the load address.
Compute the load address from the p_vaddr of the PT_LOAD segement
which covers the file start.  This fixes BZ #31799.

H.J. Lu (1):
  elf: Handle static PIE loaded at the specific address [BZ #31799]

 configure                    | 67 ++++++++++++++++++++++++++++++++++++
 configure.ac                 | 30 ++++++++++++++++
 elf/Makefile                 | 20 +++++++++++
 elf/dl-reloc-static-pie.c    | 25 ++++++++++----
 elf/tst-pie-address-static.c | 19 ++++++++++
 elf/tst-pie-address.c        | 28 +++++++++++++++
 6 files changed, 182 insertions(+), 7 deletions(-)
 create mode 100644 elf/tst-pie-address-static.c
 create mode 100644 elf/tst-pie-address.c

-- 
2.45.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-27 14:38 [PATCH v5 0/1] elf: Handle static PIE loaded at the specific address H.J. Lu
@ 2024-05-27 14:38 ` H.J. Lu
  2024-05-28  6:05   ` Florian Weimer
                     ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: H.J. Lu @ 2024-05-27 14:38 UTC (permalink / raw)
  To: libc-alpha; +Cc: fweimer

When a static PIE is loaded at the specific address, its PT_DYNAMIC
segment entries contain the relocated values for the load address.
Compute the load address from the p_vaddr of the PT_LOAD segement
which covers the file start.  This fixes BZ #31799.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 configure                    | 67 ++++++++++++++++++++++++++++++++++++
 configure.ac                 | 30 ++++++++++++++++
 elf/Makefile                 | 20 +++++++++++
 elf/dl-reloc-static-pie.c    | 25 ++++++++++----
 elf/tst-pie-address-static.c | 19 ++++++++++
 elf/tst-pie-address.c        | 28 +++++++++++++++
 6 files changed, 182 insertions(+), 7 deletions(-)
 create mode 100644 elf/tst-pie-address-static.c
 create mode 100644 elf/tst-pie-address.c

diff --git a/configure b/configure
index 49b093043c..612fa0cf77 100755
--- a/configure
+++ b/configure
@@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
 config_vars="$config_vars
 cc-pie-default = $libc_cv_cc_pie_default"
 
+# Get PDE load address.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
+printf %s "checking PDE load address... " >&6; }
+if test ${libc_cv_pde_load_address+y}
+then :
+  printf %s "(cached) " >&6
+else $as_nop
+  cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+  pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+	    -nostartfiles -nostdlib $no_ssp \
+	    -o conftest conftest.S 1>&5 2>&5; then
+  # Get the load address of the first PT_LOAD segment.
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+			     | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
+fi
+rm -f conftest*
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
+printf "%s\n" "$libc_cv_pde_load_address" >&6; }
+config_vars="$config_vars
+pde-load-address = $libc_cv_pde_load_address"
+
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
+printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
+libc_linker_feature=no
+cat > conftest.c <<EOF
+int _start (void) { return 42; }
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
+		  -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
+		  -fPIC -shared -o conftest.so conftest.c
+		  1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+then
+  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
+      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
+      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
+    true
+  else
+    libc_linker_feature=yes
+  fi
+fi
+rm -f conftest*
+if test $libc_linker_feature = yes; then
+  libc_cv_load_address=-Wl,-Ttext-segment
+else
+  libc_cv_load_address=
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
+printf "%s\n" "$libc_linker_feature" >&6; }
+config_vars="$config_vars
+load-address-ldflag = $libc_cv_load_address"
+
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
 printf %s "checking if we can build programs as PIE... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff --git a/configure.ac b/configure.ac
index e48957f318..89a2f5d842 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1721,6 +1721,36 @@ fi
 rm -f conftest.*])
 LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
 
+# Get PDE load address.
+AC_CACHE_CHECK([PDE load address],
+	       libc_cv_pde_load_address, [dnl
+cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+  pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+	    -nostartfiles -nostdlib $no_ssp \
+	    -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
+  # Get the load address of the first PT_LOAD segment.
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+			     | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+  AC_MSG_ERROR([${CC-cc} can not create PDE])
+fi
+rm -f conftest*])
+LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
+
+LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
+		    [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
+		    [libc_cv_load_address=-Wl,-Ttext-segment],
+		    [libc_cv_load_address=])
+LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
+
 AC_MSG_CHECKING(if we can build programs as PIE)
 AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
 # error PIE is not supported
diff --git a/elf/Makefile b/elf/Makefile
index 57b3a19d36..4e2d123b8e 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1046,6 +1046,25 @@ tests-pie += \
   tst-pie1 \
   tst-pie2 \
   # tests-pie
+ifneq (,$(load-address-ldflag))
+tests += \
+  tst-pie-address \
+  # tests
+tests-pie += \
+  tst-pie-address \
+  # tests-pie
+LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
+ifeq (yes,$(enable-static-pie))
+tests += \
+  tst-pie-address-static \
+  # tests
+tests-static += \
+  tst-pie-address-static \
+  # tests-static
+LDFLAGS-tst-pie-address-static += \
+  $(load-address-ldflag)=$(pde-load-address)
+endif
+endif
 ifeq (yes,$(have-protected-data))
 tests += vismain
 tests-pie += vismain
@@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
 
 CFLAGS-tst-pie1.c += $(pie-ccflag)
 CFLAGS-tst-pie2.c += $(pie-ccflag)
+CFLAGS-tst-pie-address.c += $(pie-ccflag)
 
 $(objpfx)tst-piemod1.so: $(libsupport)
 $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
index 10c23d0bf0..6286f19f1f 100644
--- a/elf/dl-reloc-static-pie.c
+++ b/elf/dl-reloc-static-pie.c
@@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
 {
   struct link_map *main_map = _dl_get_dl_main_map ();
 
-  /* Figure out the run-time load address of static PIE.  */
-  main_map->l_addr = elf_machine_load_address ();
-
-  /* Read our own dynamic section and fill in the info array.  */
-  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
-
+  ElfW(Addr) file_p_vaddr = 0;
   const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
   size_t phnum = GL(dl_phnum);
   for (ph = phdr; ph < &phdr[phnum]; ++ph)
-    if (ph->p_type == PT_DYNAMIC)
+    switch (ph->p_type)
       {
+      case PT_LOAD:
+	/* Get p_vaddr of the PT_LOAD segement which covers the file
+	   start.  */
+	if (ph->p_offset == 0)
+	  file_p_vaddr = ph->p_vaddr;
+	break;
+      case PT_DYNAMIC:
 	main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
 	break;
+      default:
+	break;
       }
 
+  /* Figure out the run-time load address of static PIE.  */
+  ElfW(Addr) l_addr = elf_machine_load_address ();
+  main_map->l_addr = l_addr - file_p_vaddr;
+
+  /* Read our own dynamic section and fill in the info array.  */
+  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
+
   elf_get_dynamic_info (main_map, false, true);
 
 # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
new file mode 100644
index 0000000000..25d27fb962
--- /dev/null
+++ b/elf/tst-pie-address-static.c
@@ -0,0 +1,19 @@
+/* Test static PIE loaded at the specific address.
+   Copyright (C) 2024 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 "tst-pie-address.c"
diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
new file mode 100644
index 0000000000..1f01783631
--- /dev/null
+++ b/elf/tst-pie-address.c
@@ -0,0 +1,28 @@
+/* Test PIE loaded at the specific address.
+   Copyright (C) 2024 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 <stdio.h>
+
+static int
+do_test (void)
+{
+  printf ("Hello\n");
+  return 0;
+}
+
+#include <support/test-driver.c>
-- 
2.45.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-27 14:38 ` [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799] H.J. Lu
@ 2024-05-28  6:05   ` Florian Weimer
  2024-05-28 12:21     ` H.J. Lu
  2024-05-28 14:28   ` Adhemerval Zanella Netto
  2024-06-30 20:47   ` PING: " H.J. Lu
  2 siblings, 1 reply; 33+ messages in thread
From: Florian Weimer @ 2024-05-28  6:05 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha

* H. J. Lu:

> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> segment entries contain the relocated values for the load address.
> Compute the load address from the p_vaddr of the PT_LOAD segement
> which covers the file start.  This fixes BZ #31799.

A PIE loaded at a specific address is no longer PIE.

I think this should work:

cat > t.c <<EOF
#include <stdio.h>

int
main (void)
{
  puts ("Hello, world!");
}
EOF
ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
  > ld.script
gcc -fpie -static -Wl,-T,ld.script t.c

But it fails with:

/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
(.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
collect2: error: ld returned 1 exit status

This is the relocation:

  18:   48 8b 3d 00 00 00 00    mov    0x0(%rip),%rdi        # 1f <_start+0x1f>
                        1b: R_X86_64_REX_GOTPCRELX      main-0x4
  1f:   ff 15 00 00 00 00       call   *0x0(%rip)        # 25 <_start+0x25>
                        21: R_X86_64_GOTPCRELX  __libc_start_main-0x4

Shouldn't it be possible to relax it to this?

	lea main(%rip),%rdi

Thanks,
Florian


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-28  6:05   ` Florian Weimer
@ 2024-05-28 12:21     ` H.J. Lu
  2024-06-14 10:36       ` Florian Weimer
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-05-28 12:21 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
>
> * H. J. Lu:
>
> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> > segment entries contain the relocated values for the load address.
> > Compute the load address from the p_vaddr of the PT_LOAD segement
> > which covers the file start.  This fixes BZ #31799.
>
> A PIE loaded at a specific address is no longer PIE.
>
> I think this should work:
>
> cat > t.c <<EOF
> #include <stdio.h>
>
> int
> main (void)
> {
>   puts ("Hello, world!");
> }
> EOF
> ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
>   > ld.script
> gcc -fpie -static -Wl,-T,ld.script t.c
>
> But it fails with:
>
> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
> collect2: error: ld returned 1 exit status

Did you mean?

[hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
function `_start':
(.text+0x1b): failed to convert GOTPCREL relocation against 'main';
relink with --no-relax
/usr/local/bin/ld: final link failed
collect2: error: ld returned 1 exit status
[hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
/usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
function `_start':
(.text+0x1b): failed to convert GOTPCREL relocation against 'main';
relink with --no-relax
/usr/local/bin/ld: final link failed
collect2: error: ld returned 1 exit status
[hjl@gnu-cfl-3 tmp]$

This no longer fits in the small model.

> This is the relocation:
>
>   18:   48 8b 3d 00 00 00 00    mov    0x0(%rip),%rdi        # 1f <_start+0x1f>
>                         1b: R_X86_64_REX_GOTPCRELX      main-0x4
>   1f:   ff 15 00 00 00 00       call   *0x0(%rip)        # 25 <_start+0x25>
>                         21: R_X86_64_GOTPCRELX  __libc_start_main-0x4
>
> Shouldn't it be possible to relax it to this?
>
>         lea main(%rip),%rdi
>

This is just a tip of the icebug when you try -Wl,-Ttext-segment=0x100000000
with PDE.  Linker can't help here.

-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-27 14:38 ` [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799] H.J. Lu
  2024-05-28  6:05   ` Florian Weimer
@ 2024-05-28 14:28   ` Adhemerval Zanella Netto
  2024-05-28 14:45     ` H.J. Lu
  2024-06-30 20:47   ` PING: " H.J. Lu
  2 siblings, 1 reply; 33+ messages in thread
From: Adhemerval Zanella Netto @ 2024-05-28 14:28 UTC (permalink / raw)
  To: H.J. Lu, libc-alpha; +Cc: fweimer



On 27/05/24 11:38, H.J. Lu wrote:
> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> segment entries contain the relocated values for the load address.
> Compute the load address from the p_vaddr of the PT_LOAD segement
> which covers the file start.  This fixes BZ #31799.
> 
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  configure                    | 67 ++++++++++++++++++++++++++++++++++++
>  configure.ac                 | 30 ++++++++++++++++
>  elf/Makefile                 | 20 +++++++++++
>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
>  elf/tst-pie-address-static.c | 19 ++++++++++
>  elf/tst-pie-address.c        | 28 +++++++++++++++
>  6 files changed, 182 insertions(+), 7 deletions(-)
>  create mode 100644 elf/tst-pie-address-static.c
>  create mode 100644 elf/tst-pie-address.c
> 
> diff --git a/configure b/configure
> index 49b093043c..612fa0cf77 100755
> --- a/configure
> +++ b/configure
> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>  config_vars="$config_vars
>  cc-pie-default = $libc_cv_cc_pie_default"
>  
> +# Get PDE load address.
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
> +printf %s "checking PDE load address... " >&6; }
> +if test ${libc_cv_pde_load_address+y}
> +then :
> +  printf %s "(cached) " >&6
> +else $as_nop
> +  cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> +  pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> +	    -nostartfiles -nostdlib $no_ssp \
> +	    -o conftest conftest.S 1>&5 2>&5; then
> +  # Get the load address of the first PT_LOAD segment.
> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> +			     | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> +fi
> +rm -f conftest*
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> +config_vars="$config_vars
> +pde-load-address = $libc_cv_pde_load_address"
> +
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> +libc_linker_feature=no
> +cat > conftest.c <<EOF
> +int _start (void) { return 42; }
> +EOF
> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> +		  -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
> +		  -fPIC -shared -o conftest.so conftest.c
> +		  1>&5'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +then
> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
> +    true
> +  else
> +    libc_linker_feature=yes
> +  fi
> +fi
> +rm -f conftest*
> +if test $libc_linker_feature = yes; then
> +  libc_cv_load_address=-Wl,-Ttext-segment
> +else
> +  libc_cv_load_address=
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
> +printf "%s\n" "$libc_linker_feature" >&6; }
> +config_vars="$config_vars
> +load-address-ldflag = $libc_cv_load_address"
> +
>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
>  printf %s "checking if we can build programs as PIE... " >&6; }
>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> diff --git a/configure.ac b/configure.ac
> index e48957f318..89a2f5d842 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1721,6 +1721,36 @@ fi
>  rm -f conftest.*])
>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>  
> +# Get PDE load address.
> +AC_CACHE_CHECK([PDE load address],
> +	       libc_cv_pde_load_address, [dnl
> +cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> +  pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> +	    -nostartfiles -nostdlib $no_ssp \
> +	    -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
> +  # Get the load address of the first PT_LOAD segment.
> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> +			     | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
> +fi
> +rm -f conftest*])
> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])

This does seems to work on ARM, RISCV, nor on loongarch (the current 
architectures that support static-pie):

aarch64-linux-gnu$ cat t.S
.globl _start
_start:
.globl __start
__start:
aarch64-linux-gnu$ aarch64-glibc-linux-gnu-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
aarch64-linux-gnu$ aarch64-glibc-linux-gnu-readelf -Wl t

There are no program headers in this file.
$ aarch64-glibc-linux-gnu-ld -v
GNU ld (GNU Binutils) 2.42.0.20240312

armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-readelf -Wl -t

There are no program headers in this file.
armv7a-linux-gnueabihf$ arm-glibc-linux-ld -v
GNU ld (GNU Binutils) 2.42.0.20240312

I am not sure why BFD is not creating programs headers for this scenario,
but this makes the test innefective on these architectures.

> +
> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> +		    [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> +		    [libc_cv_load_address=-Wl,-Ttext-segment],
> +		    [libc_cv_load_address=])
> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> +
>  AC_MSG_CHECKING(if we can build programs as PIE)
>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>  # error PIE is not supported
> diff --git a/elf/Makefile b/elf/Makefile
> index 57b3a19d36..4e2d123b8e 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -1046,6 +1046,25 @@ tests-pie += \
>    tst-pie1 \
>    tst-pie2 \
>    # tests-pie
> +ifneq (,$(load-address-ldflag))
> +tests += \
> +  tst-pie-address \
> +  # tests
> +tests-pie += \
> +  tst-pie-address \
> +  # tests-pie
> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> +ifeq (yes,$(enable-static-pie))
> +tests += \
> +  tst-pie-address-static \
> +  # tests
> +tests-static += \
> +  tst-pie-address-static \
> +  # tests-static
> +LDFLAGS-tst-pie-address-static += \
> +  $(load-address-ldflag)=$(pde-load-address)
> +endif
> +endif


For the tst-pie-address-static test (where although is set as ET_EXEC, still has
DF_1_PIE) will the kernel always enforce the loading address set by -Wl,-Ttext-segment
or it might eventually take this just a hint and thus creating a possible false negative
in the future?

And reading all the discussion on BZ#31795, I am not really convinced that setting
ET_EXEC for a static-pie with a defined loading address makes much sense (even though
it tried to overcome a kernel limitation), specially that BFD seems to be only linker
that does it. Maybe we should check with the kernel so it can enforce the loading
address for DF_1_PIE instead of trying the ET_EXEC hack.

>  ifeq (yes,$(have-protected-data))
>  tests += vismain
>  tests-pie += vismain
> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
>  
>  CFLAGS-tst-pie1.c += $(pie-ccflag)
>  CFLAGS-tst-pie2.c += $(pie-ccflag)
> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>  
>  $(objpfx)tst-piemod1.so: $(libsupport)
>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> index 10c23d0bf0..6286f19f1f 100644
> --- a/elf/dl-reloc-static-pie.c
> +++ b/elf/dl-reloc-static-pie.c
> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>  {
>    struct link_map *main_map = _dl_get_dl_main_map ();
>  
> -  /* Figure out the run-time load address of static PIE.  */
> -  main_map->l_addr = elf_machine_load_address ();
> -
> -  /* Read our own dynamic section and fill in the info array.  */
> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> -
> +  ElfW(Addr) file_p_vaddr = 0;
>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>    size_t phnum = GL(dl_phnum);
>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> -    if (ph->p_type == PT_DYNAMIC)
> +    switch (ph->p_type)
>        {
> +      case PT_LOAD:
> +	/* Get p_vaddr of the PT_LOAD segement which covers the file
> +	   start.  */
> +	if (ph->p_offset == 0)
> +	  file_p_vaddr = ph->p_vaddr;
> +	break;
> +      case PT_DYNAMIC:
>  	main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>  	break;
> +      default:
> +	break;
>        }
>  
> +  /* Figure out the run-time load address of static PIE.  */
> +  ElfW(Addr) l_addr = elf_machine_load_address ();
> +  main_map->l_addr = l_addr - file_p_vaddr;
> +
> +  /* Read our own dynamic section and fill in the info array.  */
> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> +
>    elf_get_dynamic_info (main_map, false, true);
>  
>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> new file mode 100644
> index 0000000000..25d27fb962
> --- /dev/null
> +++ b/elf/tst-pie-address-static.c
> @@ -0,0 +1,19 @@
> +/* Test static PIE loaded at the specific address.
> +   Copyright (C) 2024 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 "tst-pie-address.c"
> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> new file mode 100644
> index 0000000000..1f01783631
> --- /dev/null
> +++ b/elf/tst-pie-address.c
> @@ -0,0 +1,28 @@
> +/* Test PIE loaded at the specific address.
> +   Copyright (C) 2024 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 <stdio.h>
> +
> +static int
> +do_test (void)
> +{
> +  printf ("Hello\n");
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-28 14:28   ` Adhemerval Zanella Netto
@ 2024-05-28 14:45     ` H.J. Lu
  0 siblings, 0 replies; 33+ messages in thread
From: H.J. Lu @ 2024-05-28 14:45 UTC (permalink / raw)
  To: Adhemerval Zanella Netto; +Cc: libc-alpha, fweimer

On Tue, May 28, 2024 at 7:28 AM Adhemerval Zanella Netto
<adhemerval.zanella@linaro.org> wrote:
>
>
>
> On 27/05/24 11:38, H.J. Lu wrote:
> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> > segment entries contain the relocated values for the load address.
> > Compute the load address from the p_vaddr of the PT_LOAD segement
> > which covers the file start.  This fixes BZ #31799.
> >
> > Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> > ---
> >  configure                    | 67 ++++++++++++++++++++++++++++++++++++
> >  configure.ac                 | 30 ++++++++++++++++
> >  elf/Makefile                 | 20 +++++++++++
> >  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
> >  elf/tst-pie-address-static.c | 19 ++++++++++
> >  elf/tst-pie-address.c        | 28 +++++++++++++++
> >  6 files changed, 182 insertions(+), 7 deletions(-)
> >  create mode 100644 elf/tst-pie-address-static.c
> >  create mode 100644 elf/tst-pie-address.c
> >
> > diff --git a/configure b/configure
> > index 49b093043c..612fa0cf77 100755
> > --- a/configure
> > +++ b/configure
> > @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
> >  config_vars="$config_vars
> >  cc-pie-default = $libc_cv_cc_pie_default"
> >
> > +# Get PDE load address.
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
> > +printf %s "checking PDE load address... " >&6; }
> > +if test ${libc_cv_pde_load_address+y}
> > +then :
> > +  printf %s "(cached) " >&6
> > +else $as_nop
> > +  cat > conftest.S <<EOF
> > +.globl _start
> > +_start:
> > +.globl __start
> > +__start:
> > +EOF
> > +if test $libc_cv_cc_pie_default = yes; then
> > +  pde_ld_flags="-no-pie"
> > +fi
> > +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> > +         -nostartfiles -nostdlib $no_ssp \
> > +         -o conftest conftest.S 1>&5 2>&5; then
> > +  # Get the load address of the first PT_LOAD segment.
> > +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> > +                          | $AWK '/LOAD/ { print $3; exit 0; }')
> > +else
> > +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> > +fi
> > +rm -f conftest*
> > +fi
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
> > +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> > +config_vars="$config_vars
> > +pde-load-address = $libc_cv_pde_load_address"
> > +
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> > +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> > +libc_linker_feature=no
> > +cat > conftest.c <<EOF
> > +int _start (void) { return 42; }
> > +EOF
> > +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> > +               -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
> > +               -fPIC -shared -o conftest.so conftest.c
> > +               1>&5'
> > +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> > +  (eval $ac_try) 2>&5
> > +  ac_status=$?
> > +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> > +  test $ac_status = 0; }; }
> > +then
> > +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> > +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> > +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
> > +    true
> > +  else
> > +    libc_linker_feature=yes
> > +  fi
> > +fi
> > +rm -f conftest*
> > +if test $libc_linker_feature = yes; then
> > +  libc_cv_load_address=-Wl,-Ttext-segment
> > +else
> > +  libc_cv_load_address=
> > +fi
> > +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
> > +printf "%s\n" "$libc_linker_feature" >&6; }
> > +config_vars="$config_vars
> > +load-address-ldflag = $libc_cv_load_address"
> > +
> >  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
> >  printf %s "checking if we can build programs as PIE... " >&6; }
> >  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> > diff --git a/configure.ac b/configure.ac
> > index e48957f318..89a2f5d842 100644
> > --- a/configure.ac
> > +++ b/configure.ac
> > @@ -1721,6 +1721,36 @@ fi
> >  rm -f conftest.*])
> >  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
> >
> > +# Get PDE load address.
> > +AC_CACHE_CHECK([PDE load address],
> > +            libc_cv_pde_load_address, [dnl
> > +cat > conftest.S <<EOF
> > +.globl _start
> > +_start:
> > +.globl __start
> > +__start:
> > +EOF
> > +if test $libc_cv_cc_pie_default = yes; then
> > +  pde_ld_flags="-no-pie"
> > +fi
> > +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> > +         -nostartfiles -nostdlib $no_ssp \
> > +         -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
> > +  # Get the load address of the first PT_LOAD segment.
> > +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> > +                          | $AWK '/LOAD/ { print $3; exit 0; }')
> > +else
> > +  AC_MSG_ERROR([${CC-cc} can not create PDE])
> > +fi
> > +rm -f conftest*])
> > +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>
> This does seems to work on ARM, RISCV, nor on loongarch (the current
> architectures that support static-pie):
>
> aarch64-linux-gnu$ cat t.S
> .globl _start
> _start:
> .globl __start
> __start:
> aarch64-linux-gnu$ aarch64-glibc-linux-gnu-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
> aarch64-linux-gnu$ aarch64-glibc-linux-gnu-readelf -Wl t
>
> There are no program headers in this file.
> $ aarch64-glibc-linux-gnu-ld -v
> GNU ld (GNU Binutils) 2.42.0.20240312
>
> armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-gcc -g -O2 -static -nostartfiles -nostdlib -fno-stack-protector -o t t.S
> armv7a-linux-gnueabihf$ arm-glibc-linux-gnueabihf-readelf -Wl -t
>
> There are no program headers in this file.
> armv7a-linux-gnueabihf$ arm-glibc-linux-ld -v
> GNU ld (GNU Binutils) 2.42.0.20240312
>
> I am not sure why BFD is not creating programs headers for this scenario,
> but this makes the test innefective on these architectures.
>
> > +
> > +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> > +                 [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> > +                 [libc_cv_load_address=-Wl,-Ttext-segment],
> > +                 [libc_cv_load_address=])
> > +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> > +
> >  AC_MSG_CHECKING(if we can build programs as PIE)
> >  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> >  # error PIE is not supported
> > diff --git a/elf/Makefile b/elf/Makefile
> > index 57b3a19d36..4e2d123b8e 100644
> > --- a/elf/Makefile
> > +++ b/elf/Makefile
> > @@ -1046,6 +1046,25 @@ tests-pie += \
> >    tst-pie1 \
> >    tst-pie2 \
> >    # tests-pie
> > +ifneq (,$(load-address-ldflag))
> > +tests += \
> > +  tst-pie-address \
> > +  # tests
> > +tests-pie += \
> > +  tst-pie-address \
> > +  # tests-pie
> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> > +ifeq (yes,$(enable-static-pie))
> > +tests += \
> > +  tst-pie-address-static \
> > +  # tests
> > +tests-static += \
> > +  tst-pie-address-static \
> > +  # tests-static
> > +LDFLAGS-tst-pie-address-static += \
> > +  $(load-address-ldflag)=$(pde-load-address)
> > +endif
> > +endif
>
>
> For the tst-pie-address-static test (where although is set as ET_EXEC, still has
> DF_1_PIE) will the kernel always enforce the loading address set by -Wl,-Ttext-segment
> or it might eventually take this just a hint and thus creating a possible false negative
> in the future?

Kernel will guarantee PT_LOAD segment p_vaddr for ET_EXEC.   For ET_DYN,
kernel may load ET_DYN at some random address.   ET_EXEC is the only way
to always load a small model binary above 4G.

> And reading all the discussion on BZ#31795, I am not really convinced that setting
> ET_EXEC for a static-pie with a defined loading address makes much sense (even though

Without ET_EXEC, you don't know if a binary will be loaded at the
specific address.

> it tried to overcome a kernel limitation), specially that BFD seems to be only linker
> that does it. Maybe we should check with the kernel so it can enforce the loading
> address for DF_1_PIE instead of trying the ET_EXEC hack.
>
> >  ifeq (yes,$(have-protected-data))
> >  tests += vismain
> >  tests-pie += vismain
> > @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
> >
> >  CFLAGS-tst-pie1.c += $(pie-ccflag)
> >  CFLAGS-tst-pie2.c += $(pie-ccflag)
> > +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> >
> >  $(objpfx)tst-piemod1.so: $(libsupport)
> >  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> > diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> > index 10c23d0bf0..6286f19f1f 100644
> > --- a/elf/dl-reloc-static-pie.c
> > +++ b/elf/dl-reloc-static-pie.c
> > @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> >  {
> >    struct link_map *main_map = _dl_get_dl_main_map ();
> >
> > -  /* Figure out the run-time load address of static PIE.  */
> > -  main_map->l_addr = elf_machine_load_address ();
> > -
> > -  /* Read our own dynamic section and fill in the info array.  */
> > -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> > -
> > +  ElfW(Addr) file_p_vaddr = 0;
> >    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> >    size_t phnum = GL(dl_phnum);
> >    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> > -    if (ph->p_type == PT_DYNAMIC)
> > +    switch (ph->p_type)
> >        {
> > +      case PT_LOAD:
> > +     /* Get p_vaddr of the PT_LOAD segement which covers the file
> > +        start.  */
> > +     if (ph->p_offset == 0)
> > +       file_p_vaddr = ph->p_vaddr;
> > +     break;
> > +      case PT_DYNAMIC:
> >       main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> >       break;
> > +      default:
> > +     break;
> >        }
> >
> > +  /* Figure out the run-time load address of static PIE.  */
> > +  ElfW(Addr) l_addr = elf_machine_load_address ();
> > +  main_map->l_addr = l_addr - file_p_vaddr;
> > +
> > +  /* Read our own dynamic section and fill in the info array.  */
> > +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> > +
> >    elf_get_dynamic_info (main_map, false, true);
> >
> >  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> > diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> > new file mode 100644
> > index 0000000000..25d27fb962
> > --- /dev/null
> > +++ b/elf/tst-pie-address-static.c
> > @@ -0,0 +1,19 @@
> > +/* Test static PIE loaded at the specific address.
> > +   Copyright (C) 2024 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 "tst-pie-address.c"
> > diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> > new file mode 100644
> > index 0000000000..1f01783631
> > --- /dev/null
> > +++ b/elf/tst-pie-address.c
> > @@ -0,0 +1,28 @@
> > +/* Test PIE loaded at the specific address.
> > +   Copyright (C) 2024 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 <stdio.h>
> > +
> > +static int
> > +do_test (void)
> > +{
> > +  printf ("Hello\n");
> > +  return 0;
> > +}
> > +
> > +#include <support/test-driver.c>



-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-28 12:21     ` H.J. Lu
@ 2024-06-14 10:36       ` Florian Weimer
  2024-06-15  1:59         ` H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: Florian Weimer @ 2024-06-14 10:36 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha

* H. J. Lu:

> On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> > segment entries contain the relocated values for the load address.
>> > Compute the load address from the p_vaddr of the PT_LOAD segement
>> > which covers the file start.  This fixes BZ #31799.
>>
>> A PIE loaded at a specific address is no longer PIE.
>>
>> I think this should work:
>>
>> cat > t.c <<EOF
>> #include <stdio.h>
>>
>> int
>> main (void)
>> {
>>   puts ("Hello, world!");
>> }
>> EOF
>> ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
>>   > ld.script
>> gcc -fpie -static -Wl,-T,ld.script t.c
>>
>> But it fails with:
>>
>> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
>> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
>> collect2: error: ld returned 1 exit status
>
> Did you mean?
>
> [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> function `_start':
> (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> relink with --no-relax
> /usr/local/bin/ld: final link failed
> collect2: error: ld returned 1 exit status
> [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> function `_start':
> (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> relink with --no-relax
> /usr/local/bin/ld: final link failed
> collect2: error: ld returned 1 exit status
> [hjl@gnu-cfl-3 tmp]$

Sort of, but I compiled with PIE as well.

> This no longer fits in the small model.

You need to *compile* as PIE.  The link editor should be able to produce
a position-dependent executable that is loaded at an arbitrary address
from such relocatable input files.  The small model and GOTPCREL still
work because the GOT is still less than 2 GiB away from the code.  This
is just a linker limitation.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-06-14 10:36       ` Florian Weimer
@ 2024-06-15  1:59         ` H.J. Lu
  2024-07-01 17:22           ` Florian Weimer
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-06-15  1:59 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On Fri, Jun 14, 2024 at 12:36:30PM +0200, Florian Weimer wrote:
> * H. J. Lu:
> 
> > On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu:
> >>
> >> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> >> > segment entries contain the relocated values for the load address.
> >> > Compute the load address from the p_vaddr of the PT_LOAD segement
> >> > which covers the file start.  This fixes BZ #31799.
> >>
> >> A PIE loaded at a specific address is no longer PIE.
> >>
> >> I think this should work:
> >>
> >> cat > t.c <<EOF
> >> #include <stdio.h>
> >>
> >> int
> >> main (void)
> >> {
> >>   puts ("Hello, world!");
> >> }
> >> EOF
> >> ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> >>   > ld.script
> >> gcc -fpie -static -Wl,-T,ld.script t.c
> >>
> >> But it fails with:
> >>
> >> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
> >> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
> >> collect2: error: ld returned 1 exit status
> >
> > Did you mean?
> >
> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> > function `_start':
> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> > relink with --no-relax
> > /usr/local/bin/ld: final link failed
> > collect2: error: ld returned 1 exit status
> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> > function `_start':
> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> > relink with --no-relax
> > /usr/local/bin/ld: final link failed
> > collect2: error: ld returned 1 exit status
> > [hjl@gnu-cfl-3 tmp]$
> 
> Sort of, but I compiled with PIE as well.
> 
> > This no longer fits in the small model.
> 
> You need to *compile* as PIE.  The link editor should be able to produce
> a position-dependent executable that is loaded at an arbitrary address
> from such relocatable input files.  The small model and GOTPCREL still
> work because the GOT is still less than 2 GiB away from the code.  This
> is just a linker limitation.
> 

There are no large model *crt*.o nor .a files.  The only way to create
a small model executable loaded at a specific address above 4GB is to
build it as PIE with non-zero load address and marked as ET_EXEC.

If you believe it is a linker issue, please open a linker bug.

H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* PING: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-05-27 14:38 ` [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799] H.J. Lu
  2024-05-28  6:05   ` Florian Weimer
  2024-05-28 14:28   ` Adhemerval Zanella Netto
@ 2024-06-30 20:47   ` H.J. Lu
  2024-09-21 23:36     ` PING^2: " H.J. Lu
  2 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-06-30 20:47 UTC (permalink / raw)
  To: GNU C Library; +Cc: Florian Weimer

[-- Attachment #1: Type: text/plain, Size: 10782 bytes --]

On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> segment entries contain the relocated values for the load address.
> Compute the load address from the p_vaddr of the PT_LOAD segement
> which covers the file start.  This fixes BZ #31799.
>
> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> ---
>  configure                    | 67 ++++++++++++++++++++++++++++++++++++
>  configure.ac                 | 30 ++++++++++++++++
>  elf/Makefile                 | 20 +++++++++++
>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
>  elf/tst-pie-address-static.c | 19 ++++++++++
>  elf/tst-pie-address.c        | 28 +++++++++++++++
>  6 files changed, 182 insertions(+), 7 deletions(-)
>  create mode 100644 elf/tst-pie-address-static.c
>  create mode 100644 elf/tst-pie-address.c
>
> diff --git a/configure b/configure
> index 49b093043c..612fa0cf77 100755
> --- a/configure
> +++ b/configure
> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>  config_vars="$config_vars
>  cc-pie-default = $libc_cv_cc_pie_default"
>
> +# Get PDE load address.
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address"
> >&5
> +printf %s "checking PDE load address... " >&6; }
> +if test ${libc_cv_pde_load_address+y}
> +then :
> +  printf %s "(cached) " >&6
> +else $as_nop
> +  cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> +  pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> +           -nostartfiles -nostdlib $no_ssp \
> +           -o conftest conftest.S 1>&5 2>&5; then
> +  # Get the load address of the first PT_LOAD segment.
> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> +fi
> +rm -f conftest*
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_cv_pde_load_address" >&5
> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> +config_vars="$config_vars
> +pde-load-address = $libc_cv_pde_load_address"
> +
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that
> supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> +printf %s "checking for linker that supports
> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> +libc_linker_feature=no
> +cat > conftest.c <<EOF
> +int _start (void) { return 42; }
> +EOF
> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> +                 -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib
> -nostartfiles
> +                 -fPIC -shared -o conftest.so conftest.c
> +                 1>&5'
> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> +  (eval $ac_try) 2>&5
> +  ac_status=$?
> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> +  test $ac_status = 0; }; }
> +then
> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored"
> > /dev/null 2>&1; then
> +    true
> +  else
> +    libc_linker_feature=yes
> +  fi
> +fi
> +rm -f conftest*
> +if test $libc_linker_feature = yes; then
> +  libc_cv_load_address=-Wl,-Ttext-segment
> +else
> +  libc_cv_load_address=
> +fi
> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_linker_feature" >&5
> +printf "%s\n" "$libc_linker_feature" >&6; }
> +config_vars="$config_vars
> +load-address-ldflag = $libc_cv_load_address"
> +
>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build
> programs as PIE" >&5
>  printf %s "checking if we can build programs as PIE... " >&6; }
>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> diff --git a/configure.ac b/configure.ac
> index e48957f318..89a2f5d842 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -1721,6 +1721,36 @@ fi
>  rm -f conftest.*])
>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>
> +# Get PDE load address.
> +AC_CACHE_CHECK([PDE load address],
> +              libc_cv_pde_load_address, [dnl
> +cat > conftest.S <<EOF
> +.globl _start
> +_start:
> +.globl __start
> +__start:
> +EOF
> +if test $libc_cv_cc_pie_default = yes; then
> +  pde_ld_flags="-no-pie"
> +fi
> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> +           -nostartfiles -nostdlib $no_ssp \
> +           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
> 2>&AS_MESSAGE_LOG_FD; then
> +  # Get the load address of the first PT_LOAD segment.
> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
> +else
> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
> +fi
> +rm -f conftest*])
> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> +
> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
> +                   [libc_cv_load_address=])
> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> +
>  AC_MSG_CHECKING(if we can build programs as PIE)
>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>  # error PIE is not supported
> diff --git a/elf/Makefile b/elf/Makefile
> index 57b3a19d36..4e2d123b8e 100644
> --- a/elf/Makefile
> +++ b/elf/Makefile
> @@ -1046,6 +1046,25 @@ tests-pie += \
>    tst-pie1 \
>    tst-pie2 \
>    # tests-pie
> +ifneq (,$(load-address-ldflag))
> +tests += \
> +  tst-pie-address \
> +  # tests
> +tests-pie += \
> +  tst-pie-address \
> +  # tests-pie
> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> +ifeq (yes,$(enable-static-pie))
> +tests += \
> +  tst-pie-address-static \
> +  # tests
> +tests-static += \
> +  tst-pie-address-static \
> +  # tests-static
> +LDFLAGS-tst-pie-address-static += \
> +  $(load-address-ldflag)=$(pde-load-address)
> +endif
> +endif
>  ifeq (yes,$(have-protected-data))
>  tests += vismain
>  tests-pie += vismain
> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
> tst-array5-static.exp \
>
>  CFLAGS-tst-pie1.c += $(pie-ccflag)
>  CFLAGS-tst-pie2.c += $(pie-ccflag)
> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>
>  $(objpfx)tst-piemod1.so: $(libsupport)
>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> index 10c23d0bf0..6286f19f1f 100644
> --- a/elf/dl-reloc-static-pie.c
> +++ b/elf/dl-reloc-static-pie.c
> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>  {
>    struct link_map *main_map = _dl_get_dl_main_map ();
>
> -  /* Figure out the run-time load address of static PIE.  */
> -  main_map->l_addr = elf_machine_load_address ();
> -
> -  /* Read our own dynamic section and fill in the info array.  */
> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> -
> +  ElfW(Addr) file_p_vaddr = 0;
>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>    size_t phnum = GL(dl_phnum);
>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> -    if (ph->p_type == PT_DYNAMIC)
> +    switch (ph->p_type)
>        {
> +      case PT_LOAD:
> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
> +          start.  */
> +       if (ph->p_offset == 0)
> +         file_p_vaddr = ph->p_vaddr;
> +       break;
> +      case PT_DYNAMIC:
>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>         break;
> +      default:
> +       break;
>        }
>
> +  /* Figure out the run-time load address of static PIE.  */
> +  ElfW(Addr) l_addr = elf_machine_load_address ();
> +  main_map->l_addr = l_addr - file_p_vaddr;
> +
> +  /* Read our own dynamic section and fill in the info array.  */
> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> +
>    elf_get_dynamic_info (main_map, false, true);
>
>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> new file mode 100644
> index 0000000000..25d27fb962
> --- /dev/null
> +++ b/elf/tst-pie-address-static.c
> @@ -0,0 +1,19 @@
> +/* Test static PIE loaded at the specific address.
> +   Copyright (C) 2024 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 "tst-pie-address.c"
> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> new file mode 100644
> index 0000000000..1f01783631
> --- /dev/null
> +++ b/elf/tst-pie-address.c
> @@ -0,0 +1,28 @@
> +/* Test PIE loaded at the specific address.
> +   Copyright (C) 2024 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 <stdio.h>
> +
> +static int
> +do_test (void)
> +{
> +  printf ("Hello\n");
> +  return 0;
> +}
> +
> +#include <support/test-driver.c>
> --
> 2.45.1
>

Ping.


>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-06-15  1:59         ` H.J. Lu
@ 2024-07-01 17:22           ` Florian Weimer
  2024-07-01 21:26             ` H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: Florian Weimer @ 2024-07-01 17:22 UTC (permalink / raw)
  To: H.J. Lu; +Cc: libc-alpha

* H. J. Lu:

> On Fri, Jun 14, 2024 at 12:36:30PM +0200, Florian Weimer wrote:
>> * H. J. Lu:
>> 
>> > On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com> wrote:
>> >>
>> >> * H. J. Lu:
>> >>
>> >> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> >> > segment entries contain the relocated values for the load address.
>> >> > Compute the load address from the p_vaddr of the PT_LOAD segement
>> >> > which covers the file start.  This fixes BZ #31799.
>> >>
>> >> A PIE loaded at a specific address is no longer PIE.
>> >>
>> >> I think this should work:
>> >>
>> >> cat > t.c <<EOF
>> >> #include <stdio.h>
>> >>
>> >> int
>> >> main (void)
>> >> {
>> >>   puts ("Hello, world!");
>> >> }
>> >> EOF
>> >> ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
>> >>   > ld.script
>> >> gcc -fpie -static -Wl,-T,ld.script t.c
>> >>
>> >> But it fails with:
>> >>
>> >> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in function `_start':
>> >> (.text+0x1b): failed to convert GOTPCREL relocation against 'main'; relink with --no-relax
>> >> collect2: error: ld returned 1 exit status
>> >
>> > Did you mean?
>> >
>> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
>> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
>> > function `_start':
>> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
>> > relink with --no-relax
>> > /usr/local/bin/ld: final link failed
>> > collect2: error: ld returned 1 exit status
>> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
>> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
>> > function `_start':
>> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
>> > relink with --no-relax
>> > /usr/local/bin/ld: final link failed
>> > collect2: error: ld returned 1 exit status
>> > [hjl@gnu-cfl-3 tmp]$
>> 
>> Sort of, but I compiled with PIE as well.
>> 
>> > This no longer fits in the small model.
>> 
>> You need to *compile* as PIE.  The link editor should be able to produce
>> a position-dependent executable that is loaded at an arbitrary address
>> from such relocatable input files.  The small model and GOTPCREL still
>> work because the GOT is still less than 2 GiB away from the code.  This
>> is just a linker limitation.
>> 
>
> There are no large model *crt*.o nor .a files.  The only way to create
> a small model executable loaded at a specific address above 4GB is to
> build it as PIE with non-zero load address and marked as ET_EXEC.

This works for me:

cat > t.c <<EOF
#include <stdio.h>

char *volatile s = "Hello, world!"; /* Force relocation.  */

int
main (void)
{
  printf ("%s at %p\n", s, s);
}
EOF
ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
  > ld.script
gcc -fpie -pie -Wl,-T,ld.script,--no-relax t.c

$ ./a.out 
Hello, world! at 0x100002004
$ readelf -hW ./a.out 
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              EXEC (Executable file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x100001050
  Start of program headers:          64 (bytes into file)
  Start of section headers:          14728 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         13
  Size of section headers:           64 (bytes)
  Number of section headers:         33
  Section header string table index: 32

So it can be done, for dynamic linking.

My preference would still be to change the static non-PIE objects not to
use absolute 32-bit relocations, so that they can be used for this.
Rather than changing the PIE-specific objects to work with ET_EXEC
binaries, too.

Thanks,
Florian


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-07-01 17:22           ` Florian Weimer
@ 2024-07-01 21:26             ` H.J. Lu
  0 siblings, 0 replies; 33+ messages in thread
From: H.J. Lu @ 2024-07-01 21:26 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 4881 bytes --]

On Tue, Jul 2, 2024, 1:22 AM Florian Weimer <fweimer@redhat.com> wrote:

> * H. J. Lu:
>
> > On Fri, Jun 14, 2024 at 12:36:30PM +0200, Florian Weimer wrote:
> >> * H. J. Lu:
> >>
> >> > On Mon, May 27, 2024 at 11:05 PM Florian Weimer <fweimer@redhat.com>
> wrote:
> >> >>
> >> >> * H. J. Lu:
> >> >>
> >> >> > When a static PIE is loaded at the specific address, its PT_DYNAMIC
> >> >> > segment entries contain the relocated values for the load address.
> >> >> > Compute the load address from the p_vaddr of the PT_LOAD segement
> >> >> > which covers the file start.  This fixes BZ #31799.
> >> >>
> >> >> A PIE loaded at a specific address is no longer PIE.
> >> >>
> >> >> I think this should work:
> >> >>
> >> >> cat > t.c <<EOF
> >> >> #include <stdio.h>
> >> >>
> >> >> int
> >> >> main (void)
> >> >> {
> >> >>   puts ("Hello, world!");
> >> >> }
> >> >> EOF
> >> >> ld --verbose  | sed -n -e
> '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
> >> >>   > ld.script
> >> >> gcc -fpie -static -Wl,-T,ld.script t.c
> >> >>
> >> >> But it fails with:
> >> >>
> >> >> /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> function `_start':
> >> >> (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> relink with --no-relax
> >> >> collect2: error: ld returned 1 exit status
> >> >
> >> > Did you mean?
> >> >
> >> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
> >> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> >> > function `_start':
> >> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> >> > relink with --no-relax
> >> > /usr/local/bin/ld: final link failed
> >> > collect2: error: ld returned 1 exit status
> >> > [hjl@gnu-cfl-3 tmp]$ gcc -static -Wl,-Ttext-segment=0x100000000  x.c
> >> > /usr/lib/gcc/x86_64-redhat-linux/14/../../../../lib64/crt1.o: in
> >> > function `_start':
> >> > (.text+0x1b): failed to convert GOTPCREL relocation against 'main';
> >> > relink with --no-relax
> >> > /usr/local/bin/ld: final link failed
> >> > collect2: error: ld returned 1 exit status
> >> > [hjl@gnu-cfl-3 tmp]$
> >>
> >> Sort of, but I compiled with PIE as well.
> >>
> >> > This no longer fits in the small model.
> >>
> >> You need to *compile* as PIE.  The link editor should be able to produce
> >> a position-dependent executable that is loaded at an arbitrary address
> >> from such relocatable input files.  The small model and GOTPCREL still
> >> work because the GOT is still less than 2 GiB away from the code.  This
> >> is just a linker limitation.
> >>
> >
> > There are no large model *crt*.o nor .a files.  The only way to create
> > a small model executable loaded at a specific address above 4GB is to
> > build it as PIE with non-zero load address and marked as ET_EXEC.
>
> This works for me:
>
> cat > t.c <<EOF
> #include <stdio.h>
>
> char *volatile s = "Hello, world!"; /* Force relocation.  */
>
> int
> main (void)
> {
>   printf ("%s at %p\n", s, s);
> }
> EOF
> ld --verbose  | sed -n -e '/^=/,/^=/{//!{s/0x400000/0x100000000/g;p}}' \
>   > ld.script
> gcc -fpie -pie -Wl,-T,ld.script,--no-relax t.c
>
> $ ./a.out
> Hello, world! at 0x100002004
> $ readelf -hW ./a.out
> ELF Header:
>   Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
>   Class:                             ELF64
>   Data:                              2's complement, little endian
>   Version:                           1 (current)
>   OS/ABI:                            UNIX - System V
>   ABI Version:                       0
>   Type:                              EXEC (Executable file)
>   Machine:                           Advanced Micro Devices X86-64
>   Version:                           0x1
>   Entry point address:               0x100001050
>   Start of program headers:          64 (bytes into file)
>   Start of section headers:          14728 (bytes into file)
>   Flags:                             0x0
>   Size of this header:               64 (bytes)
>   Size of program headers:           56 (bytes)
>   Number of program headers:         13
>   Size of section headers:           64 (bytes)
>   Number of section headers:         33
>   Section header string table index: 32
>
> So it can be done, for dynamic linking.
>

Of course, PIE can be loaded above 4GB. But this is unrelated to my glibc
patch,
which applies to both ET_DYN and ET_EXEC.

The reason for ET_EXEC is that the non zero load address in ET_DYN is a hint
and kernel may ignore it.


> My preference would still be to change the static non-PIE objects not to
> use absolute 32-bit relocations, so that they can be used for this.
> Rather than changing the PIE-specific objects to work with ET_EXEC
> binaries, too.
>
> Thanks,
> Florian
>
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* PING^2: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-06-30 20:47   ` PING: " H.J. Lu
@ 2024-09-21 23:36     ` H.J. Lu
  2024-10-02  9:45       ` PING^3: " H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-09-21 23:36 UTC (permalink / raw)
  To: GNU C Library, Carlos O'Donell; +Cc: Florian Weimer, Noah Goldstein

On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
>
> On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> segment entries contain the relocated values for the load address.
>> Compute the load address from the p_vaddr of the PT_LOAD segement
>> which covers the file start.  This fixes BZ #31799.
>>
>> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>> ---
>>  configure                    | 67 ++++++++++++++++++++++++++++++++++++
>>  configure.ac                 | 30 ++++++++++++++++
>>  elf/Makefile                 | 20 +++++++++++
>>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
>>  elf/tst-pie-address-static.c | 19 ++++++++++
>>  elf/tst-pie-address.c        | 28 +++++++++++++++
>>  6 files changed, 182 insertions(+), 7 deletions(-)
>>  create mode 100644 elf/tst-pie-address-static.c
>>  create mode 100644 elf/tst-pie-address.c
>>
>> diff --git a/configure b/configure
>> index 49b093043c..612fa0cf77 100755
>> --- a/configure
>> +++ b/configure
>> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>>  config_vars="$config_vars
>>  cc-pie-default = $libc_cv_cc_pie_default"
>>
>> +# Get PDE load address.
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
>> +printf %s "checking PDE load address... " >&6; }
>> +if test ${libc_cv_pde_load_address+y}
>> +then :
>> +  printf %s "(cached) " >&6
>> +else $as_nop
>> +  cat > conftest.S <<EOF
>> +.globl _start
>> +_start:
>> +.globl __start
>> +__start:
>> +EOF
>> +if test $libc_cv_cc_pie_default = yes; then
>> +  pde_ld_flags="-no-pie"
>> +fi
>> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> +           -nostartfiles -nostdlib $no_ssp \
>> +           -o conftest conftest.S 1>&5 2>&5; then
>> +  # Get the load address of the first PT_LOAD segment.
>> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>> +else
>> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>> +fi
>> +rm -f conftest*
>> +fi
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
>> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>> +config_vars="$config_vars
>> +pde-load-address = $libc_cv_pde_load_address"
>> +
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>> +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>> +libc_linker_feature=no
>> +cat > conftest.c <<EOF
>> +int _start (void) { return 42; }
>> +EOF
>> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>> +                 -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
>> +                 -fPIC -shared -o conftest.so conftest.c
>> +                 1>&5'
>> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
>> +  (eval $ac_try) 2>&5
>> +  ac_status=$?
>> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>> +  test $ac_status = 0; }; }
>> +then
>> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
>> +    true
>> +  else
>> +    libc_linker_feature=yes
>> +  fi
>> +fi
>> +rm -f conftest*
>> +if test $libc_linker_feature = yes; then
>> +  libc_cv_load_address=-Wl,-Ttext-segment
>> +else
>> +  libc_cv_load_address=
>> +fi
>> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
>> +printf "%s\n" "$libc_linker_feature" >&6; }
>> +config_vars="$config_vars
>> +load-address-ldflag = $libc_cv_load_address"
>> +
>>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
>>  printf %s "checking if we can build programs as PIE... " >&6; }
>>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>> diff --git a/configure.ac b/configure.ac
>> index e48957f318..89a2f5d842 100644
>> --- a/configure.ac
>> +++ b/configure.ac
>> @@ -1721,6 +1721,36 @@ fi
>>  rm -f conftest.*])
>>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>>
>> +# Get PDE load address.
>> +AC_CACHE_CHECK([PDE load address],
>> +              libc_cv_pde_load_address, [dnl
>> +cat > conftest.S <<EOF
>> +.globl _start
>> +_start:
>> +.globl __start
>> +__start:
>> +EOF
>> +if test $libc_cv_cc_pie_default = yes; then
>> +  pde_ld_flags="-no-pie"
>> +fi
>> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> +           -nostartfiles -nostdlib $no_ssp \
>> +           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
>> +  # Get the load address of the first PT_LOAD segment.
>> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>> +else
>> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
>> +fi
>> +rm -f conftest*])
>> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>> +
>> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
>> +                   [libc_cv_load_address=])
>> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>> +
>>  AC_MSG_CHECKING(if we can build programs as PIE)
>>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>>  # error PIE is not supported
>> diff --git a/elf/Makefile b/elf/Makefile
>> index 57b3a19d36..4e2d123b8e 100644
>> --- a/elf/Makefile
>> +++ b/elf/Makefile
>> @@ -1046,6 +1046,25 @@ tests-pie += \
>>    tst-pie1 \
>>    tst-pie2 \
>>    # tests-pie
>> +ifneq (,$(load-address-ldflag))
>> +tests += \
>> +  tst-pie-address \
>> +  # tests
>> +tests-pie += \
>> +  tst-pie-address \
>> +  # tests-pie
>> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>> +ifeq (yes,$(enable-static-pie))
>> +tests += \
>> +  tst-pie-address-static \
>> +  # tests
>> +tests-static += \
>> +  tst-pie-address-static \
>> +  # tests-static
>> +LDFLAGS-tst-pie-address-static += \
>> +  $(load-address-ldflag)=$(pde-load-address)
>> +endif
>> +endif
>>  ifeq (yes,$(have-protected-data))
>>  tests += vismain
>>  tests-pie += vismain
>> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
>>
>>  CFLAGS-tst-pie1.c += $(pie-ccflag)
>>  CFLAGS-tst-pie2.c += $(pie-ccflag)
>> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>>
>>  $(objpfx)tst-piemod1.so: $(libsupport)
>>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>> index 10c23d0bf0..6286f19f1f 100644
>> --- a/elf/dl-reloc-static-pie.c
>> +++ b/elf/dl-reloc-static-pie.c
>> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>>  {
>>    struct link_map *main_map = _dl_get_dl_main_map ();
>>
>> -  /* Figure out the run-time load address of static PIE.  */
>> -  main_map->l_addr = elf_machine_load_address ();
>> -
>> -  /* Read our own dynamic section and fill in the info array.  */
>> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
>> -
>> +  ElfW(Addr) file_p_vaddr = 0;
>>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>>    size_t phnum = GL(dl_phnum);
>>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
>> -    if (ph->p_type == PT_DYNAMIC)
>> +    switch (ph->p_type)
>>        {
>> +      case PT_LOAD:
>> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
>> +          start.  */
>> +       if (ph->p_offset == 0)
>> +         file_p_vaddr = ph->p_vaddr;
>> +       break;
>> +      case PT_DYNAMIC:
>>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>>         break;
>> +      default:
>> +       break;
>>        }
>>
>> +  /* Figure out the run-time load address of static PIE.  */
>> +  ElfW(Addr) l_addr = elf_machine_load_address ();
>> +  main_map->l_addr = l_addr - file_p_vaddr;
>> +
>> +  /* Read our own dynamic section and fill in the info array.  */
>> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>> +
>>    elf_get_dynamic_info (main_map, false, true);
>>
>>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
>> new file mode 100644
>> index 0000000000..25d27fb962
>> --- /dev/null
>> +++ b/elf/tst-pie-address-static.c
>> @@ -0,0 +1,19 @@
>> +/* Test static PIE loaded at the specific address.
>> +   Copyright (C) 2024 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 "tst-pie-address.c"
>> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>> new file mode 100644
>> index 0000000000..1f01783631
>> --- /dev/null
>> +++ b/elf/tst-pie-address.c
>> @@ -0,0 +1,28 @@
>> +/* Test PIE loaded at the specific address.
>> +   Copyright (C) 2024 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 <stdio.h>
>> +
>> +static int
>> +do_test (void)
>> +{
>> +  printf ("Hello\n");
>> +  return 0;
>> +}
>> +
>> +#include <support/test-driver.c>
>> --
>> 2.45.1
>
>
> Ping.
>

PING.

-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* PING^3: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-09-21 23:36     ` PING^2: " H.J. Lu
@ 2024-10-02  9:45       ` H.J. Lu
  2024-10-07 22:41         ` PING^4: " H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-10-02  9:45 UTC (permalink / raw)
  To: GNU C Library, Carlos O'Donell; +Cc: Florian Weimer, Noah Goldstein

[-- Attachment #1: Type: text/plain, Size: 11840 bytes --]

On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> >
> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
> >> segment entries contain the relocated values for the load address.
> >> Compute the load address from the p_vaddr of the PT_LOAD segement
> >> which covers the file start.  This fixes BZ #31799.
> >>
> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
> >> ---
> >>  configure                    | 67 ++++++++++++++++++++++++++++++++++++
> >>  configure.ac                 | 30 ++++++++++++++++
> >>  elf/Makefile                 | 20 +++++++++++
> >>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
> >>  elf/tst-pie-address-static.c | 19 ++++++++++
> >>  elf/tst-pie-address.c        | 28 +++++++++++++++
> >>  6 files changed, 182 insertions(+), 7 deletions(-)
> >>  create mode 100644 elf/tst-pie-address-static.c
> >>  create mode 100644 elf/tst-pie-address.c
> >>
> >> diff --git a/configure b/configure
> >> index 49b093043c..612fa0cf77 100755
> >> --- a/configure
> >> +++ b/configure
> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
> >>  config_vars="$config_vars
> >>  cc-pie-default = $libc_cv_cc_pie_default"
> >>
> >> +# Get PDE load address.
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load
> address" >&5
> >> +printf %s "checking PDE load address... " >&6; }
> >> +if test ${libc_cv_pde_load_address+y}
> >> +then :
> >> +  printf %s "(cached) " >&6
> >> +else $as_nop
> >> +  cat > conftest.S <<EOF
> >> +.globl _start
> >> +_start:
> >> +.globl __start
> >> +__start:
> >> +EOF
> >> +if test $libc_cv_cc_pie_default = yes; then
> >> +  pde_ld_flags="-no-pie"
> >> +fi
> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> >> +           -nostartfiles -nostdlib $no_ssp \
> >> +           -o conftest conftest.S 1>&5 2>&5; then
> >> +  # Get the load address of the first PT_LOAD segment.
> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
> >> +else
> >> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
> >> +fi
> >> +rm -f conftest*
> >> +fi
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_cv_pde_load_address" >&5
> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
> >> +config_vars="$config_vars
> >> +pde-load-address = $libc_cv_pde_load_address"
> >> +
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that
> supports -Ttext-segment=$libc_cv_pde_load_address" >&5
> >> +printf %s "checking for linker that supports
> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
> >> +libc_linker_feature=no
> >> +cat > conftest.c <<EOF
> >> +int _start (void) { return 42; }
> >> +EOF
> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> >> +                 -Wl,-Ttext-segment=$libc_cv_pde_load_address
> -nostdlib -nostartfiles
> >> +                 -fPIC -shared -o conftest.so conftest.c
> >> +                 1>&5'
> >> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
> >> +  (eval $ac_try) 2>&5
> >> +  ac_status=$?
> >> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
> >> +  test $ac_status = 0; }; }
> >> +then
> >> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
> >> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
> >> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address
> ignored" > /dev/null 2>&1; then
> >> +    true
> >> +  else
> >> +    libc_linker_feature=yes
> >> +  fi
> >> +fi
> >> +rm -f conftest*
> >> +if test $libc_linker_feature = yes; then
> >> +  libc_cv_load_address=-Wl,-Ttext-segment
> >> +else
> >> +  libc_cv_load_address=
> >> +fi
> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
> $libc_linker_feature" >&5
> >> +printf "%s\n" "$libc_linker_feature" >&6; }
> >> +config_vars="$config_vars
> >> +load-address-ldflag = $libc_cv_load_address"
> >> +
> >>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build
> programs as PIE" >&5
> >>  printf %s "checking if we can build programs as PIE... " >&6; }
> >>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
> >> diff --git a/configure.ac b/configure.ac
> >> index e48957f318..89a2f5d842 100644
> >> --- a/configure.ac
> >> +++ b/configure.ac
> >> @@ -1721,6 +1721,36 @@ fi
> >>  rm -f conftest.*])
> >>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
> >>
> >> +# Get PDE load address.
> >> +AC_CACHE_CHECK([PDE load address],
> >> +              libc_cv_pde_load_address, [dnl
> >> +cat > conftest.S <<EOF
> >> +.globl _start
> >> +_start:
> >> +.globl __start
> >> +__start:
> >> +EOF
> >> +if test $libc_cv_cc_pie_default = yes; then
> >> +  pde_ld_flags="-no-pie"
> >> +fi
> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
> >> +           -nostartfiles -nostdlib $no_ssp \
> >> +           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
> 2>&AS_MESSAGE_LOG_FD; then
> >> +  # Get the load address of the first PT_LOAD segment.
> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
> >> +else
> >> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
> >> +fi
> >> +rm -f conftest*])
> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> >> +
> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
> >> +                   [libc_cv_load_address=])
> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> >> +
> >>  AC_MSG_CHECKING(if we can build programs as PIE)
> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> >>  # error PIE is not supported
> >> diff --git a/elf/Makefile b/elf/Makefile
> >> index 57b3a19d36..4e2d123b8e 100644
> >> --- a/elf/Makefile
> >> +++ b/elf/Makefile
> >> @@ -1046,6 +1046,25 @@ tests-pie += \
> >>    tst-pie1 \
> >>    tst-pie2 \
> >>    # tests-pie
> >> +ifneq (,$(load-address-ldflag))
> >> +tests += \
> >> +  tst-pie-address \
> >> +  # tests
> >> +tests-pie += \
> >> +  tst-pie-address \
> >> +  # tests-pie
> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> >> +ifeq (yes,$(enable-static-pie))
> >> +tests += \
> >> +  tst-pie-address-static \
> >> +  # tests
> >> +tests-static += \
> >> +  tst-pie-address-static \
> >> +  # tests-static
> >> +LDFLAGS-tst-pie-address-static += \
> >> +  $(load-address-ldflag)=$(pde-load-address)
> >> +endif
> >> +endif
> >>  ifeq (yes,$(have-protected-data))
> >>  tests += vismain
> >>  tests-pie += vismain
> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
> tst-array5-static.exp \
> >>
> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> >>
> >>  $(objpfx)tst-piemod1.so: $(libsupport)
> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> >> index 10c23d0bf0..6286f19f1f 100644
> >> --- a/elf/dl-reloc-static-pie.c
> >> +++ b/elf/dl-reloc-static-pie.c
> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> >>  {
> >>    struct link_map *main_map = _dl_get_dl_main_map ();
> >>
> >> -  /* Figure out the run-time load address of static PIE.  */
> >> -  main_map->l_addr = elf_machine_load_address ();
> >> -
> >> -  /* Read our own dynamic section and fill in the info array.  */
> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic
> ());
> >> -
> >> +  ElfW(Addr) file_p_vaddr = 0;
> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> >>    size_t phnum = GL(dl_phnum);
> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> >> -    if (ph->p_type == PT_DYNAMIC)
> >> +    switch (ph->p_type)
> >>        {
> >> +      case PT_LOAD:
> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
> >> +          start.  */
> >> +       if (ph->p_offset == 0)
> >> +         file_p_vaddr = ph->p_vaddr;
> >> +       break;
> >> +      case PT_DYNAMIC:
> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> >>         break;
> >> +      default:
> >> +       break;
> >>        }
> >>
> >> +  /* Figure out the run-time load address of static PIE.  */
> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
> >> +  main_map->l_addr = l_addr - file_p_vaddr;
> >> +
> >> +  /* Read our own dynamic section and fill in the info array.  */
> >> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
> >> +
> >>    elf_get_dynamic_info (main_map, false, true);
> >>
> >>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
> >> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
> >> new file mode 100644
> >> index 0000000000..25d27fb962
> >> --- /dev/null
> >> +++ b/elf/tst-pie-address-static.c
> >> @@ -0,0 +1,19 @@
> >> +/* Test static PIE loaded at the specific address.
> >> +   Copyright (C) 2024 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 "tst-pie-address.c"
> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
> >> new file mode 100644
> >> index 0000000000..1f01783631
> >> --- /dev/null
> >> +++ b/elf/tst-pie-address.c
> >> @@ -0,0 +1,28 @@
> >> +/* Test PIE loaded at the specific address.
> >> +   Copyright (C) 2024 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 <stdio.h>
> >> +
> >> +static int
> >> +do_test (void)
> >> +{
> >> +  printf ("Hello\n");
> >> +  return 0;
> >> +}
> >> +
> >> +#include <support/test-driver.c>
> >> --
> >> 2.45.1
> >
> >
> > Ping.
> >
>
> PING.
>

PING.


> --
> H.J.
>
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* PING^4: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-10-02  9:45       ` PING^3: " H.J. Lu
@ 2024-10-07 22:41         ` H.J. Lu
  2024-10-21 21:51           ` PING^5: " H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-10-07 22:41 UTC (permalink / raw)
  To: GNU C Library, Carlos O'Donell; +Cc: Florian Weimer, Noah Goldstein

[-- Attachment #1: Type: text/plain, Size: 12255 bytes --]

On Wed, Oct 2, 2024, 5:45 PM H.J. Lu <hjl.tools@gmail.com> wrote:

> On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
>> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >
>> >
>> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >>
>> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>> >> segment entries contain the relocated values for the load address.
>> >> Compute the load address from the p_vaddr of the PT_LOAD segement
>> >> which covers the file start.  This fixes BZ #31799.
>> >>
>> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>> >> ---
>> >>  configure                    | 67 ++++++++++++++++++++++++++++++++++++
>> >>  configure.ac                 | 30 ++++++++++++++++
>> >>  elf/Makefile                 | 20 +++++++++++
>> >>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
>> >>  elf/tst-pie-address-static.c | 19 ++++++++++
>> >>  elf/tst-pie-address.c        | 28 +++++++++++++++
>> >>  6 files changed, 182 insertions(+), 7 deletions(-)
>> >>  create mode 100644 elf/tst-pie-address-static.c
>> >>  create mode 100644 elf/tst-pie-address.c
>> >>
>> >> diff --git a/configure b/configure
>> >> index 49b093043c..612fa0cf77 100755
>> >> --- a/configure
>> >> +++ b/configure
>> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>> >>  config_vars="$config_vars
>> >>  cc-pie-default = $libc_cv_cc_pie_default"
>> >>
>> >> +# Get PDE load address.
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load
>> address" >&5
>> >> +printf %s "checking PDE load address... " >&6; }
>> >> +if test ${libc_cv_pde_load_address+y}
>> >> +then :
>> >> +  printf %s "(cached) " >&6
>> >> +else $as_nop
>> >> +  cat > conftest.S <<EOF
>> >> +.globl _start
>> >> +_start:
>> >> +.globl __start
>> >> +__start:
>> >> +EOF
>> >> +if test $libc_cv_cc_pie_default = yes; then
>> >> +  pde_ld_flags="-no-pie"
>> >> +fi
>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> >> +           -nostartfiles -nostdlib $no_ssp \
>> >> +           -o conftest conftest.S 1>&5 2>&5; then
>> >> +  # Get the load address of the first PT_LOAD segment.
>> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>> >> +else
>> >> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>> >> +fi
>> >> +rm -f conftest*
>> >> +fi
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>> $libc_cv_pde_load_address" >&5
>> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>> >> +config_vars="$config_vars
>> >> +pde-load-address = $libc_cv_pde_load_address"
>> >> +
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker
>> that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>> >> +printf %s "checking for linker that supports
>> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>> >> +libc_linker_feature=no
>> >> +cat > conftest.c <<EOF
>> >> +int _start (void) { return 42; }
>> >> +EOF
>> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>> >> +                 -Wl,-Ttext-segment=$libc_cv_pde_load_address
>> -nostdlib -nostartfiles
>> >> +                 -fPIC -shared -o conftest.so conftest.c
>> >> +                 1>&5'
>> >> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
>> >> +  (eval $ac_try) 2>&5
>> >> +  ac_status=$?
>> >> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>> >> +  test $ac_status = 0; }; }
>> >> +then
>> >> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>> >> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>> >> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address
>> ignored" > /dev/null 2>&1; then
>> >> +    true
>> >> +  else
>> >> +    libc_linker_feature=yes
>> >> +  fi
>> >> +fi
>> >> +rm -f conftest*
>> >> +if test $libc_linker_feature = yes; then
>> >> +  libc_cv_load_address=-Wl,-Ttext-segment
>> >> +else
>> >> +  libc_cv_load_address=
>> >> +fi
>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>> $libc_linker_feature" >&5
>> >> +printf "%s\n" "$libc_linker_feature" >&6; }
>> >> +config_vars="$config_vars
>> >> +load-address-ldflag = $libc_cv_load_address"
>> >> +
>> >>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can
>> build programs as PIE" >&5
>> >>  printf %s "checking if we can build programs as PIE... " >&6; }
>> >>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>> >> diff --git a/configure.ac b/configure.ac
>> >> index e48957f318..89a2f5d842 100644
>> >> --- a/configure.ac
>> >> +++ b/configure.ac
>> >> @@ -1721,6 +1721,36 @@ fi
>> >>  rm -f conftest.*])
>> >>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>> >>
>> >> +# Get PDE load address.
>> >> +AC_CACHE_CHECK([PDE load address],
>> >> +              libc_cv_pde_load_address, [dnl
>> >> +cat > conftest.S <<EOF
>> >> +.globl _start
>> >> +_start:
>> >> +.globl __start
>> >> +__start:
>> >> +EOF
>> >> +if test $libc_cv_cc_pie_default = yes; then
>> >> +  pde_ld_flags="-no-pie"
>> >> +fi
>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>> >> +           -nostartfiles -nostdlib $no_ssp \
>> >> +           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
>> 2>&AS_MESSAGE_LOG_FD; then
>> >> +  # Get the load address of the first PT_LOAD segment.
>> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>> >> +else
>> >> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
>> >> +fi
>> >> +rm -f conftest*])
>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>> >> +
>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
>> >> +                   [libc_cv_load_address=])
>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>> >> +
>> >>  AC_MSG_CHECKING(if we can build programs as PIE)
>> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>> >>  # error PIE is not supported
>> >> diff --git a/elf/Makefile b/elf/Makefile
>> >> index 57b3a19d36..4e2d123b8e 100644
>> >> --- a/elf/Makefile
>> >> +++ b/elf/Makefile
>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
>> >>    tst-pie1 \
>> >>    tst-pie2 \
>> >>    # tests-pie
>> >> +ifneq (,$(load-address-ldflag))
>> >> +tests += \
>> >> +  tst-pie-address \
>> >> +  # tests
>> >> +tests-pie += \
>> >> +  tst-pie-address \
>> >> +  # tests-pie
>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>> >> +ifeq (yes,$(enable-static-pie))
>> >> +tests += \
>> >> +  tst-pie-address-static \
>> >> +  # tests
>> >> +tests-static += \
>> >> +  tst-pie-address-static \
>> >> +  # tests-static
>> >> +LDFLAGS-tst-pie-address-static += \
>> >> +  $(load-address-ldflag)=$(pde-load-address)
>> >> +endif
>> >> +endif
>> >>  ifeq (yes,$(have-protected-data))
>> >>  tests += vismain
>> >>  tests-pie += vismain
>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
>> tst-array5-static.exp \
>> >>
>> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
>> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>> >>
>> >>  $(objpfx)tst-piemod1.so: $(libsupport)
>> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>> >> index 10c23d0bf0..6286f19f1f 100644
>> >> --- a/elf/dl-reloc-static-pie.c
>> >> +++ b/elf/dl-reloc-static-pie.c
>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>> >>  {
>> >>    struct link_map *main_map = _dl_get_dl_main_map ();
>> >>
>> >> -  /* Figure out the run-time load address of static PIE.  */
>> >> -  main_map->l_addr = elf_machine_load_address ();
>> >> -
>> >> -  /* Read our own dynamic section and fill in the info array.  */
>> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic
>> ());
>> >> -
>> >> +  ElfW(Addr) file_p_vaddr = 0;
>> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>> >>    size_t phnum = GL(dl_phnum);
>> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
>> >> -    if (ph->p_type == PT_DYNAMIC)
>> >> +    switch (ph->p_type)
>> >>        {
>> >> +      case PT_LOAD:
>> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
>> >> +          start.  */
>> >> +       if (ph->p_offset == 0)
>> >> +         file_p_vaddr = ph->p_vaddr;
>> >> +       break;
>> >> +      case PT_DYNAMIC:
>> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>> >>         break;
>> >> +      default:
>> >> +       break;
>> >>        }
>> >>
>> >> +  /* Figure out the run-time load address of static PIE.  */
>> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
>> >> +  main_map->l_addr = l_addr - file_p_vaddr;
>> >> +
>> >> +  /* Read our own dynamic section and fill in the info array.  */
>> >> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>> >> +
>> >>    elf_get_dynamic_info (main_map, false, true);
>> >>
>> >>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>> >> diff --git a/elf/tst-pie-address-static.c
>> b/elf/tst-pie-address-static.c
>> >> new file mode 100644
>> >> index 0000000000..25d27fb962
>> >> --- /dev/null
>> >> +++ b/elf/tst-pie-address-static.c
>> >> @@ -0,0 +1,19 @@
>> >> +/* Test static PIE loaded at the specific address.
>> >> +   Copyright (C) 2024 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 "tst-pie-address.c"
>> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>> >> new file mode 100644
>> >> index 0000000000..1f01783631
>> >> --- /dev/null
>> >> +++ b/elf/tst-pie-address.c
>> >> @@ -0,0 +1,28 @@
>> >> +/* Test PIE loaded at the specific address.
>> >> +   Copyright (C) 2024 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 <stdio.h>
>> >> +
>> >> +static int
>> >> +do_test (void)
>> >> +{
>> >> +  printf ("Hello\n");
>> >> +  return 0;
>> >> +}
>> >> +
>> >> +#include <support/test-driver.c>
>> >> --
>> >> 2.45.1
>> >
>> >
>> > Ping.
>> >
>>
>> PING.
>>
>
> PING.
>

PING.


>
>> --
>> H.J.
>>
>>
>>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* PING^5: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-10-07 22:41         ` PING^4: " H.J. Lu
@ 2024-10-21 21:51           ` H.J. Lu
  2024-10-23 14:30             ` Noah Goldstein
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-10-21 21:51 UTC (permalink / raw)
  To: GNU C Library, Carlos O'Donell; +Cc: Florian Weimer, Noah Goldstein

[-- Attachment #1: Type: text/plain, Size: 12679 bytes --]

On Tue, Oct 8, 2024, 6:41 AM H.J. Lu <hjl.tools@gmail.com> wrote:

> On Wed, Oct 2, 2024, 5:45 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
>> On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>>> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>> >
>>> >
>>> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>> >>
>>> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>>> >> segment entries contain the relocated values for the load address.
>>> >> Compute the load address from the p_vaddr of the PT_LOAD segement
>>> >> which covers the file start.  This fixes BZ #31799.
>>> >>
>>> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>>> >> ---
>>> >>  configure                    | 67
>>> ++++++++++++++++++++++++++++++++++++
>>> >>  configure.ac                 | 30 ++++++++++++++++
>>> >>  elf/Makefile                 | 20 +++++++++++
>>> >>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
>>> >>  elf/tst-pie-address-static.c | 19 ++++++++++
>>> >>  elf/tst-pie-address.c        | 28 +++++++++++++++
>>> >>  6 files changed, 182 insertions(+), 7 deletions(-)
>>> >>  create mode 100644 elf/tst-pie-address-static.c
>>> >>  create mode 100644 elf/tst-pie-address.c
>>> >>
>>> >> diff --git a/configure b/configure
>>> >> index 49b093043c..612fa0cf77 100755
>>> >> --- a/configure
>>> >> +++ b/configure
>>> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>>> >>  config_vars="$config_vars
>>> >>  cc-pie-default = $libc_cv_cc_pie_default"
>>> >>
>>> >> +# Get PDE load address.
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load
>>> address" >&5
>>> >> +printf %s "checking PDE load address... " >&6; }
>>> >> +if test ${libc_cv_pde_load_address+y}
>>> >> +then :
>>> >> +  printf %s "(cached) " >&6
>>> >> +else $as_nop
>>> >> +  cat > conftest.S <<EOF
>>> >> +.globl _start
>>> >> +_start:
>>> >> +.globl __start
>>> >> +__start:
>>> >> +EOF
>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>> >> +  pde_ld_flags="-no-pie"
>>> >> +fi
>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>> >> +           -nostartfiles -nostdlib $no_ssp \
>>> >> +           -o conftest conftest.S 1>&5 2>&5; then
>>> >> +  # Get the load address of the first PT_LOAD segment.
>>> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>>> >> +else
>>> >> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>>> >> +fi
>>> >> +rm -f conftest*
>>> >> +fi
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>>> $libc_cv_pde_load_address" >&5
>>> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>>> >> +config_vars="$config_vars
>>> >> +pde-load-address = $libc_cv_pde_load_address"
>>> >> +
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker
>>> that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>>> >> +printf %s "checking for linker that supports
>>> -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>>> >> +libc_linker_feature=no
>>> >> +cat > conftest.c <<EOF
>>> >> +int _start (void) { return 42; }
>>> >> +EOF
>>> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>>> >> +                 -Wl,-Ttext-segment=$libc_cv_pde_load_address
>>> -nostdlib -nostartfiles
>>> >> +                 -fPIC -shared -o conftest.so conftest.c
>>> >> +                 1>&5'
>>> >> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; }
>>> >&5
>>> >> +  (eval $ac_try) 2>&5
>>> >> +  ac_status=$?
>>> >> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>>> >> +  test $ac_status = 0; }; }
>>> >> +then
>>> >> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>>> -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>>> >> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>>> >> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address
>>> ignored" > /dev/null 2>&1; then
>>> >> +    true
>>> >> +  else
>>> >> +    libc_linker_feature=yes
>>> >> +  fi
>>> >> +fi
>>> >> +rm -f conftest*
>>> >> +if test $libc_linker_feature = yes; then
>>> >> +  libc_cv_load_address=-Wl,-Ttext-segment
>>> >> +else
>>> >> +  libc_cv_load_address=
>>> >> +fi
>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result:
>>> $libc_linker_feature" >&5
>>> >> +printf "%s\n" "$libc_linker_feature" >&6; }
>>> >> +config_vars="$config_vars
>>> >> +load-address-ldflag = $libc_cv_load_address"
>>> >> +
>>> >>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can
>>> build programs as PIE" >&5
>>> >>  printf %s "checking if we can build programs as PIE... " >&6; }
>>> >>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>>> >> diff --git a/configure.ac b/configure.ac
>>> >> index e48957f318..89a2f5d842 100644
>>> >> --- a/configure.ac
>>> >> +++ b/configure.ac
>>> >> @@ -1721,6 +1721,36 @@ fi
>>> >>  rm -f conftest.*])
>>> >>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>>> >>
>>> >> +# Get PDE load address.
>>> >> +AC_CACHE_CHECK([PDE load address],
>>> >> +              libc_cv_pde_load_address, [dnl
>>> >> +cat > conftest.S <<EOF
>>> >> +.globl _start
>>> >> +_start:
>>> >> +.globl __start
>>> >> +__start:
>>> >> +EOF
>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>> >> +  pde_ld_flags="-no-pie"
>>> >> +fi
>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>> >> +           -nostartfiles -nostdlib $no_ssp \
>>> >> +           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD
>>> 2>&AS_MESSAGE_LOG_FD; then
>>> >> +  # Get the load address of the first PT_LOAD segment.
>>> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>>> >> +else
>>> >> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
>>> >> +fi
>>> >> +rm -f conftest*])
>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>>> >> +
>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>>> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>>> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
>>> >> +                   [libc_cv_load_address=])
>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>>> >> +
>>> >>  AC_MSG_CHECKING(if we can build programs as PIE)
>>> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>>> >>  # error PIE is not supported
>>> >> diff --git a/elf/Makefile b/elf/Makefile
>>> >> index 57b3a19d36..4e2d123b8e 100644
>>> >> --- a/elf/Makefile
>>> >> +++ b/elf/Makefile
>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
>>> >>    tst-pie1 \
>>> >>    tst-pie2 \
>>> >>    # tests-pie
>>> >> +ifneq (,$(load-address-ldflag))
>>> >> +tests += \
>>> >> +  tst-pie-address \
>>> >> +  # tests
>>> >> +tests-pie += \
>>> >> +  tst-pie-address \
>>> >> +  # tests-pie
>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>>> >> +ifeq (yes,$(enable-static-pie))
>>> >> +tests += \
>>> >> +  tst-pie-address-static \
>>> >> +  # tests
>>> >> +tests-static += \
>>> >> +  tst-pie-address-static \
>>> >> +  # tests-static
>>> >> +LDFLAGS-tst-pie-address-static += \
>>> >> +  $(load-address-ldflag)=$(pde-load-address)
>>> >> +endif
>>> >> +endif
>>> >>  ifeq (yes,$(have-protected-data))
>>> >>  tests += vismain
>>> >>  tests-pie += vismain
>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out:
>>> tst-array5-static.exp \
>>> >>
>>> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
>>> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>>> >>
>>> >>  $(objpfx)tst-piemod1.so: $(libsupport)
>>> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>>> >> index 10c23d0bf0..6286f19f1f 100644
>>> >> --- a/elf/dl-reloc-static-pie.c
>>> >> +++ b/elf/dl-reloc-static-pie.c
>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>>> >>  {
>>> >>    struct link_map *main_map = _dl_get_dl_main_map ();
>>> >>
>>> >> -  /* Figure out the run-time load address of static PIE.  */
>>> >> -  main_map->l_addr = elf_machine_load_address ();
>>> >> -
>>> >> -  /* Read our own dynamic section and fill in the info array.  */
>>> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic
>>> ());
>>> >> -
>>> >> +  ElfW(Addr) file_p_vaddr = 0;
>>> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>>> >>    size_t phnum = GL(dl_phnum);
>>> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
>>> >> -    if (ph->p_type == PT_DYNAMIC)
>>> >> +    switch (ph->p_type)
>>> >>        {
>>> >> +      case PT_LOAD:
>>> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
>>> >> +          start.  */
>>> >> +       if (ph->p_offset == 0)
>>> >> +         file_p_vaddr = ph->p_vaddr;
>>> >> +       break;
>>> >> +      case PT_DYNAMIC:
>>> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>>> >>         break;
>>> >> +      default:
>>> >> +       break;
>>> >>        }
>>> >>
>>> >> +  /* Figure out the run-time load address of static PIE.  */
>>> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
>>> >> +  main_map->l_addr = l_addr - file_p_vaddr;
>>> >> +
>>> >> +  /* Read our own dynamic section and fill in the info array.  */
>>> >> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>>> >> +
>>> >>    elf_get_dynamic_info (main_map, false, true);
>>> >>
>>> >>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>>> >> diff --git a/elf/tst-pie-address-static.c
>>> b/elf/tst-pie-address-static.c
>>> >> new file mode 100644
>>> >> index 0000000000..25d27fb962
>>> >> --- /dev/null
>>> >> +++ b/elf/tst-pie-address-static.c
>>> >> @@ -0,0 +1,19 @@
>>> >> +/* Test static PIE loaded at the specific address.
>>> >> +   Copyright (C) 2024 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 "tst-pie-address.c"
>>> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>>> >> new file mode 100644
>>> >> index 0000000000..1f01783631
>>> >> --- /dev/null
>>> >> +++ b/elf/tst-pie-address.c
>>> >> @@ -0,0 +1,28 @@
>>> >> +/* Test PIE loaded at the specific address.
>>> >> +   Copyright (C) 2024 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 <stdio.h>
>>> >> +
>>> >> +static int
>>> >> +do_test (void)
>>> >> +{
>>> >> +  printf ("Hello\n");
>>> >> +  return 0;
>>> >> +}
>>> >> +
>>> >> +#include <support/test-driver.c>
>>> >> --
>>> >> 2.45.1
>>> >
>>> >
>>> > Ping.
>>> >
>>>
>>> PING.
>>>
>>
>> PING.
>>
>
> PING.
>

PING.


>
>>
>>> --
>>> H.J.
>>>
>>>
>>>
>>>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PING^5: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
  2024-10-21 21:51           ` PING^5: " H.J. Lu
@ 2024-10-23 14:30             ` Noah Goldstein
  2024-10-25 22:18               ` [PATCH v6 1/1] elf: Handle static PIE loaded at the non-zero " H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: Noah Goldstein @ 2024-10-23 14:30 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

On Mon, Oct 21, 2024 at 4:51 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Tue, Oct 8, 2024, 6:41 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Wed, Oct 2, 2024, 5:45 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>
>>> On Sun, Sep 22, 2024, 7:36 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>>
>>>> On Mon, Jul 1, 2024 at 4:47 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> >
>>>> >
>>>> > On Mon, May 27, 2024, 10:38 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>>>> >>
>>>> >> When a static PIE is loaded at the specific address, its PT_DYNAMIC
>>>> >> segment entries contain the relocated values for the load address.
>>>> >> Compute the load address from the p_vaddr of the PT_LOAD segement
>>>> >> which covers the file start.  This fixes BZ #31799.
>>>> >>
>>>> >> Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
>>>> >> ---
>>>> >>  configure                    | 67 ++++++++++++++++++++++++++++++++++++
>>>> >>  configure.ac                 | 30 ++++++++++++++++
>>>> >>  elf/Makefile                 | 20 +++++++++++
>>>> >>  elf/dl-reloc-static-pie.c    | 25 ++++++++++----
>>>> >>  elf/tst-pie-address-static.c | 19 ++++++++++
>>>> >>  elf/tst-pie-address.c        | 28 +++++++++++++++
>>>> >>  6 files changed, 182 insertions(+), 7 deletions(-)
>>>> >>  create mode 100644 elf/tst-pie-address-static.c
>>>> >>  create mode 100644 elf/tst-pie-address.c
>>>> >>
>>>> >> diff --git a/configure b/configure
>>>> >> index 49b093043c..612fa0cf77 100755
>>>> >> --- a/configure
>>>> >> +++ b/configure
>>>> >> @@ -7820,6 +7820,73 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
>>>> >>  config_vars="$config_vars
>>>> >>  cc-pie-default = $libc_cv_cc_pie_default"
>>>> >>
>>>> >> +# Get PDE load address.
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
>>>> >> +printf %s "checking PDE load address... " >&6; }
>>>> >> +if test ${libc_cv_pde_load_address+y}
>>>> >> +then :
>>>> >> +  printf %s "(cached) " >&6
>>>> >> +else $as_nop
>>>> >> +  cat > conftest.S <<EOF
>>>> >> +.globl _start
>>>> >> +_start:
>>>> >> +.globl __start
>>>> >> +__start:
>>>> >> +EOF
>>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>>> >> +  pde_ld_flags="-no-pie"
>>>> >> +fi
>>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>>> >> +           -nostartfiles -nostdlib $no_ssp \
>>>> >> +           -o conftest conftest.S 1>&5 2>&5; then
>>>> >> +  # Get the load address of the first PT_LOAD segment.
>>>> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>>> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>>>> >> +else
>>>> >> +  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
>>>> >> +fi
>>>> >> +rm -f conftest*
>>>> >> +fi
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
>>>> >> +printf "%s\n" "$libc_cv_pde_load_address" >&6; }
>>>> >> +config_vars="$config_vars
>>>> >> +pde-load-address = $libc_cv_pde_load_address"
>>>> >> +
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
>>>> >> +printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
>>>> >> +libc_linker_feature=no
>>>> >> +cat > conftest.c <<EOF
>>>> >> +int _start (void) { return 42; }
>>>> >> +EOF
>>>> >> +if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
>>>> >> +                 -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
>>>> >> +                 -fPIC -shared -o conftest.so conftest.c
>>>> >> +                 1>&5'
>>>> >> +  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
>>>> >> +  (eval $ac_try) 2>&5
>>>> >> +  ac_status=$?
>>>> >> +  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
>>>> >> +  test $ac_status = 0; }; }
>>>> >> +then
>>>> >> +  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
>>>> >> +      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
>>>> >> +      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
>>>> >> +    true
>>>> >> +  else
>>>> >> +    libc_linker_feature=yes
>>>> >> +  fi
>>>> >> +fi
>>>> >> +rm -f conftest*
>>>> >> +if test $libc_linker_feature = yes; then
>>>> >> +  libc_cv_load_address=-Wl,-Ttext-segment
>>>> >> +else
>>>> >> +  libc_cv_load_address=
>>>> >> +fi
>>>> >> +{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
>>>> >> +printf "%s\n" "$libc_linker_feature" >&6; }
>>>> >> +config_vars="$config_vars
>>>> >> +load-address-ldflag = $libc_cv_load_address"
>>>> >> +
>>>> >>  { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
>>>> >>  printf %s "checking if we can build programs as PIE... " >&6; }
>>>> >>  cat confdefs.h - <<_ACEOF >conftest.$ac_ext
>>>> >> diff --git a/configure.ac b/configure.ac
>>>> >> index e48957f318..89a2f5d842 100644
>>>> >> --- a/configure.ac
>>>> >> +++ b/configure.ac
>>>> >> @@ -1721,6 +1721,36 @@ fi
>>>> >>  rm -f conftest.*])
>>>> >>  LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
>>>> >>
>>>> >> +# Get PDE load address.
>>>> >> +AC_CACHE_CHECK([PDE load address],
>>>> >> +              libc_cv_pde_load_address, [dnl
>>>> >> +cat > conftest.S <<EOF
>>>> >> +.globl _start
>>>> >> +_start:
>>>> >> +.globl __start
>>>> >> +__start:
>>>> >> +EOF
>>>> >> +if test $libc_cv_cc_pie_default = yes; then
>>>> >> +  pde_ld_flags="-no-pie"
>>>> >> +fi
>>>> >> +if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
>>>> >> +           -nostartfiles -nostdlib $no_ssp \
>>>> >> +           -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
>>>> >> +  # Get the load address of the first PT_LOAD segment.
>>>> >> +  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
>>>> >> +                            | $AWK '/LOAD/ { print $3; exit 0; }')
>>>> >> +else
>>>> >> +  AC_MSG_ERROR([${CC-cc} can not create PDE])
>>>> >> +fi
>>>> >> +rm -f conftest*])
>>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
>>>> >> +
>>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
>>>> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
>>>> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
>>>> >> +                   [libc_cv_load_address=])
>>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
>>>> >> +

IIUC, all of the new conf code is for setting up tests.
Can you make that more clear in either comment or var names?

>>>> >>  AC_MSG_CHECKING(if we can build programs as PIE)
>>>> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
>>>> >>  # error PIE is not supported
>>>> >> diff --git a/elf/Makefile b/elf/Makefile
>>>> >> index 57b3a19d36..4e2d123b8e 100644
>>>> >> --- a/elf/Makefile
>>>> >> +++ b/elf/Makefile
>>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
>>>> >>    tst-pie1 \
>>>> >>    tst-pie2 \
>>>> >>    # tests-pie
>>>> >> +ifneq (,$(load-address-ldflag))
>>>> >> +tests += \
>>>> >> +  tst-pie-address \
>>>> >> +  # tests
>>>> >> +tests-pie += \
>>>> >> +  tst-pie-address \
>>>> >> +  # tests-pie
>>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>>>> >> +ifeq (yes,$(enable-static-pie))
>>>> >> +tests += \
>>>> >> +  tst-pie-address-static \
>>>> >> +  # tests
>>>> >> +tests-static += \
>>>> >> +  tst-pie-address-static \
>>>> >> +  # tests-static
>>>> >> +LDFLAGS-tst-pie-address-static += \
>>>> >> +  $(load-address-ldflag)=$(pde-load-address)
>>>> >> +endif
>>>> >> +endif
>>>> >>  ifeq (yes,$(have-protected-data))
>>>> >>  tests += vismain
>>>> >>  tests-pie += vismain
>>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
>>>> >>
>>>> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
>>>> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
>>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
>>>> >>
>>>> >>  $(objpfx)tst-piemod1.so: $(libsupport)
>>>> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
>>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
>>>> >> index 10c23d0bf0..6286f19f1f 100644
>>>> >> --- a/elf/dl-reloc-static-pie.c
>>>> >> +++ b/elf/dl-reloc-static-pie.c
>>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
>>>> >>  {
>>>> >>    struct link_map *main_map = _dl_get_dl_main_map ();
>>>> >>
>>>> >> -  /* Figure out the run-time load address of static PIE.  */
>>>> >> -  main_map->l_addr = elf_machine_load_address ();
>>>> >> -
>>>> >> -  /* Read our own dynamic section and fill in the info array.  */
>>>> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
>>>> >> -
>>>> >> +  ElfW(Addr) file_p_vaddr = 0;
>>>> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
>>>> >>    size_t phnum = GL(dl_phnum);
>>>> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
>>>> >> -    if (ph->p_type == PT_DYNAMIC)
>>>> >> +    switch (ph->p_type)
>>>> >>        {
>>>> >> +      case PT_LOAD:
>>>> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
>>>> >> +          start.  */
>>>> >> +       if (ph->p_offset == 0)
>>>> >> +         file_p_vaddr = ph->p_vaddr;
>>>> >> +       break;
>>>> >> +      case PT_DYNAMIC:
>>>> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
>>>> >>         break;
>>>> >> +      default:
>>>> >> +       break;
>>>> >>        }
>>>> >>
>>>> >> +  /* Figure out the run-time load address of static PIE.  */
>>>> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
>>>> >> +  main_map->l_addr = l_addr - file_p_vaddr;

Can you explain this? I though vaddr field was the true virtual-address
but you seem to be treating it as an offset here.
>>>> >> +
>>>> >> +  /* Read our own dynamic section and fill in the info array.  */
>>>> >> +  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
>>>> >> +
>>>> >>    elf_get_dynamic_info (main_map, false, true);
>>>> >>
>>>> >>  # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
>>>> >> diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
>>>> >> new file mode 100644
>>>> >> index 0000000000..25d27fb962
>>>> >> --- /dev/null
>>>> >> +++ b/elf/tst-pie-address-static.c
>>>> >> @@ -0,0 +1,19 @@
>>>> >> +/* Test static PIE loaded at the specific address.
>>>> >> +   Copyright (C) 2024 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 "tst-pie-address.c"
>>>> >> diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
>>>> >> new file mode 100644
>>>> >> index 0000000000..1f01783631
>>>> >> --- /dev/null
>>>> >> +++ b/elf/tst-pie-address.c
>>>> >> @@ -0,0 +1,28 @@
>>>> >> +/* Test PIE loaded at the specific address.
>>>> >> +   Copyright (C) 2024 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 <stdio.h>
>>>> >> +
>>>> >> +static int
>>>> >> +do_test (void)
>>>> >> +{
>>>> >> +  printf ("Hello\n");
>>>> >> +  return 0;
>>>> >> +}
>>>> >> +
>>>> >> +#include <support/test-driver.c>
>>>> >> --
>>>> >> 2.45.1
>>>> >
>>>> >
>>>> > Ping.
>>>> >
>>>>
>>>> PING.
>>>
>>>
>>> PING.
>>
>>
>> PING.
>
>
> PING.
>
>>
>>>
>>>>
>>>> --
>>>> H.J.
>>>>
>>>>
>>>>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v6 1/1] elf: Handle static PIE loaded at the non-zero address [BZ #31799]
  2024-10-23 14:30             ` Noah Goldstein
@ 2024-10-25 22:18               ` H.J. Lu
  2024-10-26 18:49                 ` Noah Goldstein
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-10-25 22:18 UTC (permalink / raw)
  To: Noah Goldstein; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

[-- Attachment #1: Type: text/plain, Size: 4332 bytes --]

On Wed, Oct 23, 2024 at 10:30 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
...
> >>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> >>>> >> +
> >>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> >>>> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> >>>> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
> >>>> >> +                   [libc_cv_load_address=])
> >>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> >>>> >> +
>
> IIUC, all of the new conf code is for setting up tests.
> Can you make that more clear in either comment or var names?

Done.

> >>>> >>  AC_MSG_CHECKING(if we can build programs as PIE)
> >>>> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> >>>> >>  # error PIE is not supported
> >>>> >> diff --git a/elf/Makefile b/elf/Makefile
> >>>> >> index 57b3a19d36..4e2d123b8e 100644
> >>>> >> --- a/elf/Makefile
> >>>> >> +++ b/elf/Makefile
> >>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
> >>>> >>    tst-pie1 \
> >>>> >>    tst-pie2 \
> >>>> >>    # tests-pie
> >>>> >> +ifneq (,$(load-address-ldflag))
> >>>> >> +tests += \
> >>>> >> +  tst-pie-address \
> >>>> >> +  # tests
> >>>> >> +tests-pie += \
> >>>> >> +  tst-pie-address \
> >>>> >> +  # tests-pie
> >>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> >>>> >> +ifeq (yes,$(enable-static-pie))
> >>>> >> +tests += \
> >>>> >> +  tst-pie-address-static \
> >>>> >> +  # tests
> >>>> >> +tests-static += \
> >>>> >> +  tst-pie-address-static \
> >>>> >> +  # tests-static
> >>>> >> +LDFLAGS-tst-pie-address-static += \
> >>>> >> +  $(load-address-ldflag)=$(pde-load-address)
> >>>> >> +endif
> >>>> >> +endif
> >>>> >>  ifeq (yes,$(have-protected-data))
> >>>> >>  tests += vismain
> >>>> >>  tests-pie += vismain
> >>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
> >>>> >>
> >>>> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
> >>>> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
> >>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> >>>> >>
> >>>> >>  $(objpfx)tst-piemod1.so: $(libsupport)
> >>>> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> >>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> >>>> >> index 10c23d0bf0..6286f19f1f 100644
> >>>> >> --- a/elf/dl-reloc-static-pie.c
> >>>> >> +++ b/elf/dl-reloc-static-pie.c
> >>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> >>>> >>  {
> >>>> >>    struct link_map *main_map = _dl_get_dl_main_map ();
> >>>> >>
> >>>> >> -  /* Figure out the run-time load address of static PIE.  */
> >>>> >> -  main_map->l_addr = elf_machine_load_address ();
> >>>> >> -
> >>>> >> -  /* Read our own dynamic section and fill in the info array.  */
> >>>> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> >>>> >> -
> >>>> >> +  ElfW(Addr) file_p_vaddr = 0;
> >>>> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> >>>> >>    size_t phnum = GL(dl_phnum);
> >>>> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> >>>> >> -    if (ph->p_type == PT_DYNAMIC)
> >>>> >> +    switch (ph->p_type)
> >>>> >>        {
> >>>> >> +      case PT_LOAD:
> >>>> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
> >>>> >> +          start.  */
> >>>> >> +       if (ph->p_offset == 0)
> >>>> >> +         file_p_vaddr = ph->p_vaddr;
> >>>> >> +       break;
> >>>> >> +      case PT_DYNAMIC:
> >>>> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> >>>> >>         break;
> >>>> >> +      default:
> >>>> >> +       break;
> >>>> >>        }
> >>>> >>
> >>>> >> +  /* Figure out the run-time load address of static PIE.  */
> >>>> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
> >>>> >> +  main_map->l_addr = l_addr - file_p_vaddr;
>
> Can you explain this? I though vaddr field was the true virtual-address
> but you seem to be treating it as an offset here.

The l_addr field contains the difference between the address in the ELF
file and the address in memory.  file_p_vaddr is used as the address in
static PIE.  I updated comments in the v6 patch,

Here is the v6 patch.  OK to install?

Thanks.

-- 
H.J.

[-- Attachment #2: v6-0001-elf-Handle-static-PIE-loaded-at-the-non-zero-addr.patch --]
[-- Type: text/x-patch, Size: 10993 bytes --]

From c309d6edd62b64d5d732ef9b662e6074a79c2eff Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 26 May 2024 04:55:32 -0700
Subject: [PATCH v6] elf: Handle static PIE loaded at the non-zero address [BZ
 #31799]

When a static PIE is loaded at the non-zero address, its PT_DYNAMIC
segment entries contain the relocated values for the load address in
static PIE.  Since static PIE usually doesn't have PT_PHDR segment,
use p_vaddr of the PT_LOAD segment which covers the file start as the
load address in static PIE and adjust the entries of PT_DYNAMIC segment
with the load address in static PIE by properly setting the l_addr field
for static PIE.  This fixes BZ #31799.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 configure                    | 72 ++++++++++++++++++++++++++++++++++++
 configure.ac                 | 34 +++++++++++++++++
 elf/Makefile                 | 20 ++++++++++
 elf/dl-reloc-static-pie.c    | 30 +++++++++++----
 elf/tst-pie-address-static.c | 19 ++++++++++
 elf/tst-pie-address.c        | 28 ++++++++++++++
 6 files changed, 196 insertions(+), 7 deletions(-)
 create mode 100644 elf/tst-pie-address-static.c
 create mode 100644 elf/tst-pie-address.c

diff --git a/configure b/configure
index 9c0c0dce03..a84bb53fc8 100755
--- a/configure
+++ b/configure
@@ -8107,6 +8107,78 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
 config_vars="$config_vars
 cc-pie-default = $libc_cv_cc_pie_default"
 
+# Get Position Dependent Executable (PDE) load address to be used to
+# load static Position Independent Executable (PIE) at a known working
+# non-zero address.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
+printf %s "checking PDE load address... " >&6; }
+if test ${libc_cv_pde_load_address+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+  pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+	    -nostartfiles -nostdlib $no_ssp \
+	    -o conftest conftest.S 1>&5 2>&5; then
+  # Get the load address of the first PT_LOAD segment.
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+			     | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
+fi
+rm -f conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
+printf "%s\n" "$libc_cv_pde_load_address" >&6; }
+config_vars="$config_vars
+pde-load-address = $libc_cv_pde_load_address"
+
+# Get the linker command-line option to load executable at a non-zero
+# address.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
+printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
+libc_linker_feature=no
+cat > conftest.c <<EOF
+int _start (void) { return 42; }
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
+		  -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
+		  -fPIC -shared -o conftest.so conftest.c
+		  1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+then
+  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
+      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
+      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
+    true
+  else
+    libc_linker_feature=yes
+  fi
+fi
+rm -f conftest*
+if test $libc_linker_feature = yes; then
+  libc_cv_load_address_ldflag=-Wl,-Ttext-segment
+else
+  libc_cv_load_address_ldflag=
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
+printf "%s\n" "$libc_linker_feature" >&6; }
+config_vars="$config_vars
+load-address-ldflag = $libc_cv_load_address_ldflag"
+
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
 printf %s "checking if we can build programs as PIE... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff --git a/configure.ac b/configure.ac
index d5a00461ff..8dc7e80ca3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1763,6 +1763,40 @@ fi
 rm -f conftest.*])
 LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
 
+# Get Position Dependent Executable (PDE) load address to be used to
+# load static Position Independent Executable (PIE) at a known working
+# non-zero address.
+AC_CACHE_CHECK([PDE load address],
+	       libc_cv_pde_load_address, [dnl
+cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+  pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+	    -nostartfiles -nostdlib $no_ssp \
+	    -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
+  # Get the load address of the first PT_LOAD segment.
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+			     | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+  AC_MSG_ERROR([${CC-cc} can not create PDE])
+fi
+rm -f conftest*])
+LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
+
+# Get the linker command-line option to load executable at a non-zero
+# address.
+LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
+		    [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
+		    [libc_cv_load_address_ldflag=-Wl,-Ttext-segment],
+		    [libc_cv_load_address_ldflag=])
+LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag])
+
 AC_MSG_CHECKING(if we can build programs as PIE)
 AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
 # error PIE is not supported
diff --git a/elf/Makefile b/elf/Makefile
index 9cfe738919..4eaca7af67 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1091,6 +1091,25 @@ tests-pie += \
   tst-pie1 \
   tst-pie2 \
   # tests-pie
+ifneq (,$(load-address-ldflag))
+tests += \
+  tst-pie-address \
+  # tests
+tests-pie += \
+  tst-pie-address \
+  # tests-pie
+LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
+ifeq (yes,$(enable-static-pie))
+tests += \
+  tst-pie-address-static \
+  # tests
+tests-static += \
+  tst-pie-address-static \
+  # tests-static
+LDFLAGS-tst-pie-address-static += \
+  $(load-address-ldflag)=$(pde-load-address)
+endif
+endif
 ifeq (yes,$(have-protected-data))
 tests += vismain
 tests-pie += vismain
@@ -1937,6 +1956,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
 
 CFLAGS-tst-pie1.c += $(pie-ccflag)
 CFLAGS-tst-pie2.c += $(pie-ccflag)
+CFLAGS-tst-pie-address.c += $(pie-ccflag)
 
 $(objpfx)tst-piemod1.so: $(libsupport)
 $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
index 10c23d0bf0..66fabf5543 100644
--- a/elf/dl-reloc-static-pie.c
+++ b/elf/dl-reloc-static-pie.c
@@ -37,21 +37,37 @@ _dl_relocate_static_pie (void)
 {
   struct link_map *main_map = _dl_get_dl_main_map ();
 
-  /* Figure out the run-time load address of static PIE.  */
-  main_map->l_addr = elf_machine_load_address ();
-
-  /* Read our own dynamic section and fill in the info array.  */
-  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
-
+  /* NB: elf_machine_load_address () returns the run-time load address
+     of static PIE.  The l_addr field contains the difference between the
+     address in the ELF file and the address in memory.  If a static PIE
+     has a non-zero load address, we need to subtract it when computing
+     the l_addr field.  Since static PIE usually doesn't have PT_PHDR
+     segment, use p_vaddr of the PT_LOAD segment which covers the file
+     start as the load address in static PIE.  */
+  ElfW(Addr) file_p_vaddr = 0;
   const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
   size_t phnum = GL(dl_phnum);
   for (ph = phdr; ph < &phdr[phnum]; ++ph)
-    if (ph->p_type == PT_DYNAMIC)
+    switch (ph->p_type)
       {
+      case PT_LOAD:
+	if (ph->p_offset == 0)
+	  file_p_vaddr = ph->p_vaddr;
+	break;
+      case PT_DYNAMIC:
 	main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
 	break;
+      default:
+	break;
       }
 
+  /* Figure out the run-time load address of static PIE.  */
+  ElfW(Addr) l_addr = elf_machine_load_address ();
+  main_map->l_addr = l_addr - file_p_vaddr;
+
+  /* Read our own dynamic section and fill in the info array.  */
+  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
+
   elf_get_dynamic_info (main_map, false, true);
 
 # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
new file mode 100644
index 0000000000..25d27fb962
--- /dev/null
+++ b/elf/tst-pie-address-static.c
@@ -0,0 +1,19 @@
+/* Test static PIE loaded at the specific address.
+   Copyright (C) 2024 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 "tst-pie-address.c"
diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
new file mode 100644
index 0000000000..1f01783631
--- /dev/null
+++ b/elf/tst-pie-address.c
@@ -0,0 +1,28 @@
+/* Test PIE loaded at the specific address.
+   Copyright (C) 2024 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 <stdio.h>
+
+static int
+do_test (void)
+{
+  printf ("Hello\n");
+  return 0;
+}
+
+#include <support/test-driver.c>
-- 
2.47.0


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v6 1/1] elf: Handle static PIE loaded at the non-zero address [BZ #31799]
  2024-10-25 22:18               ` [PATCH v6 1/1] elf: Handle static PIE loaded at the non-zero " H.J. Lu
@ 2024-10-26 18:49                 ` Noah Goldstein
  2024-10-26 22:02                   ` H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: Noah Goldstein @ 2024-10-26 18:49 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

On Fri, Oct 25, 2024 at 5:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Wed, Oct 23, 2024 at 10:30 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
> ...
> > >>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> > >>>> >> +
> > >>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> > >>>> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> > >>>> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
> > >>>> >> +                   [libc_cv_load_address=])
> > >>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> > >>>> >> +
> >
> > IIUC, all of the new conf code is for setting up tests.
> > Can you make that more clear in either comment or var names?
>
> Done.

Hmm? This doesn't seem done. I mean can you make it explicit
these config options are only used for tests internal to glibc.
>
> > >>>> >>  AC_MSG_CHECKING(if we can build programs as PIE)
> > >>>> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> > >>>> >>  # error PIE is not supported
> > >>>> >> diff --git a/elf/Makefile b/elf/Makefile
> > >>>> >> index 57b3a19d36..4e2d123b8e 100644
> > >>>> >> --- a/elf/Makefile
> > >>>> >> +++ b/elf/Makefile
> > >>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
> > >>>> >>    tst-pie1 \
> > >>>> >>    tst-pie2 \
> > >>>> >>    # tests-pie
> > >>>> >> +ifneq (,$(load-address-ldflag))
> > >>>> >> +tests += \
> > >>>> >> +  tst-pie-address \
> > >>>> >> +  # tests
> > >>>> >> +tests-pie += \
> > >>>> >> +  tst-pie-address \
> > >>>> >> +  # tests-pie
> > >>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> > >>>> >> +ifeq (yes,$(enable-static-pie))
> > >>>> >> +tests += \
> > >>>> >> +  tst-pie-address-static \
> > >>>> >> +  # tests
> > >>>> >> +tests-static += \
> > >>>> >> +  tst-pie-address-static \
> > >>>> >> +  # tests-static
> > >>>> >> +LDFLAGS-tst-pie-address-static += \
> > >>>> >> +  $(load-address-ldflag)=$(pde-load-address)
> > >>>> >> +endif
> > >>>> >> +endif
> > >>>> >>  ifeq (yes,$(have-protected-data))
> > >>>> >>  tests += vismain
> > >>>> >>  tests-pie += vismain
> > >>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
> > >>>> >>
> > >>>> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
> > >>>> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
> > >>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> > >>>> >>
> > >>>> >>  $(objpfx)tst-piemod1.so: $(libsupport)
> > >>>> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> > >>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> > >>>> >> index 10c23d0bf0..6286f19f1f 100644
> > >>>> >> --- a/elf/dl-reloc-static-pie.c
> > >>>> >> +++ b/elf/dl-reloc-static-pie.c
> > >>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> > >>>> >>  {
> > >>>> >>    struct link_map *main_map = _dl_get_dl_main_map ();
> > >>>> >>
> > >>>> >> -  /* Figure out the run-time load address of static PIE.  */
> > >>>> >> -  main_map->l_addr = elf_machine_load_address ();
> > >>>> >> -
> > >>>> >> -  /* Read our own dynamic section and fill in the info array.  */
> > >>>> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> > >>>> >> -
> > >>>> >> +  ElfW(Addr) file_p_vaddr = 0;
> > >>>> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> > >>>> >>    size_t phnum = GL(dl_phnum);
> > >>>> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> > >>>> >> -    if (ph->p_type == PT_DYNAMIC)
> > >>>> >> +    switch (ph->p_type)
> > >>>> >>        {
> > >>>> >> +      case PT_LOAD:
> > >>>> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
> > >>>> >> +          start.  */
> > >>>> >> +       if (ph->p_offset == 0)
> > >>>> >> +         file_p_vaddr = ph->p_vaddr;
> > >>>> >> +       break;
> > >>>> >> +      case PT_DYNAMIC:
> > >>>> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> > >>>> >>         break;
> > >>>> >> +      default:
> > >>>> >> +       break;
> > >>>> >>        }
> > >>>> >>
> > >>>> >> +  /* Figure out the run-time load address of static PIE.  */
> > >>>> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
> > >>>> >> +  main_map->l_addr = l_addr - file_p_vaddr;
> >
> > Can you explain this? I though vaddr field was the true virtual-address
> > but you seem to be treating it as an offset here.
>
> The l_addr field contains the difference between the address in the ELF
> file and the address in memory.  file_p_vaddr is used as the address in
> static PIE.  I updated comments in the v6 patch,
>
Okay, I think I understand. We were implicitly assuming vaddr was zero
before by just using l_addr (v_addr + offset == true_addr if v_addr is zero).
Is that correct?

> Here is the v6 patch.  OK to install?
>
> Thanks.
>
> --
> H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v6 1/1] elf: Handle static PIE loaded at the non-zero address [BZ #31799]
  2024-10-26 18:49                 ` Noah Goldstein
@ 2024-10-26 22:02                   ` H.J. Lu
  2024-10-26 22:29                     ` [PATCH v7] elf: Handle static PIE with non-zero load " H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-10-26 22:02 UTC (permalink / raw)
  To: Noah Goldstein; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

On Sun, Oct 27, 2024 at 2:49 AM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>
> On Fri, Oct 25, 2024 at 5:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Wed, Oct 23, 2024 at 10:30 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
> > ...
> > > >>>> >> +LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
> > > >>>> >> +
> > > >>>> >> +LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
> > > >>>> >> +                   [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
> > > >>>> >> +                   [libc_cv_load_address=-Wl,-Ttext-segment],
> > > >>>> >> +                   [libc_cv_load_address=])
> > > >>>> >> +LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address])
> > > >>>> >> +
> > >
> > > IIUC, all of the new conf code is for setting up tests.
> > > Can you make that more clear in either comment or var names?
> >
> > Done.
>
> Hmm? This doesn't seem done. I mean can you make it explicit
> these config options are only used for tests internal to glibc.

Will update.

> >
> > > >>>> >>  AC_MSG_CHECKING(if we can build programs as PIE)
> > > >>>> >>  AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
> > > >>>> >>  # error PIE is not supported
> > > >>>> >> diff --git a/elf/Makefile b/elf/Makefile
> > > >>>> >> index 57b3a19d36..4e2d123b8e 100644
> > > >>>> >> --- a/elf/Makefile
> > > >>>> >> +++ b/elf/Makefile
> > > >>>> >> @@ -1046,6 +1046,25 @@ tests-pie += \
> > > >>>> >>    tst-pie1 \
> > > >>>> >>    tst-pie2 \
> > > >>>> >>    # tests-pie
> > > >>>> >> +ifneq (,$(load-address-ldflag))
> > > >>>> >> +tests += \
> > > >>>> >> +  tst-pie-address \
> > > >>>> >> +  # tests
> > > >>>> >> +tests-pie += \
> > > >>>> >> +  tst-pie-address \
> > > >>>> >> +  # tests-pie
> > > >>>> >> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> > > >>>> >> +ifeq (yes,$(enable-static-pie))
> > > >>>> >> +tests += \
> > > >>>> >> +  tst-pie-address-static \
> > > >>>> >> +  # tests
> > > >>>> >> +tests-static += \
> > > >>>> >> +  tst-pie-address-static \
> > > >>>> >> +  # tests-static
> > > >>>> >> +LDFLAGS-tst-pie-address-static += \
> > > >>>> >> +  $(load-address-ldflag)=$(pde-load-address)
> > > >>>> >> +endif
> > > >>>> >> +endif
> > > >>>> >>  ifeq (yes,$(have-protected-data))
> > > >>>> >>  tests += vismain
> > > >>>> >>  tests-pie += vismain
> > > >>>> >> @@ -1896,6 +1915,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
> > > >>>> >>
> > > >>>> >>  CFLAGS-tst-pie1.c += $(pie-ccflag)
> > > >>>> >>  CFLAGS-tst-pie2.c += $(pie-ccflag)
> > > >>>> >> +CFLAGS-tst-pie-address.c += $(pie-ccflag)
> > > >>>> >>
> > > >>>> >>  $(objpfx)tst-piemod1.so: $(libsupport)
> > > >>>> >>  $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
> > > >>>> >> diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
> > > >>>> >> index 10c23d0bf0..6286f19f1f 100644
> > > >>>> >> --- a/elf/dl-reloc-static-pie.c
> > > >>>> >> +++ b/elf/dl-reloc-static-pie.c
> > > >>>> >> @@ -37,21 +37,32 @@ _dl_relocate_static_pie (void)
> > > >>>> >>  {
> > > >>>> >>    struct link_map *main_map = _dl_get_dl_main_map ();
> > > >>>> >>
> > > >>>> >> -  /* Figure out the run-time load address of static PIE.  */
> > > >>>> >> -  main_map->l_addr = elf_machine_load_address ();
> > > >>>> >> -
> > > >>>> >> -  /* Read our own dynamic section and fill in the info array.  */
> > > >>>> >> -  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
> > > >>>> >> -
> > > >>>> >> +  ElfW(Addr) file_p_vaddr = 0;
> > > >>>> >>    const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
> > > >>>> >>    size_t phnum = GL(dl_phnum);
> > > >>>> >>    for (ph = phdr; ph < &phdr[phnum]; ++ph)
> > > >>>> >> -    if (ph->p_type == PT_DYNAMIC)
> > > >>>> >> +    switch (ph->p_type)
> > > >>>> >>        {
> > > >>>> >> +      case PT_LOAD:
> > > >>>> >> +       /* Get p_vaddr of the PT_LOAD segement which covers the file
> > > >>>> >> +          start.  */
> > > >>>> >> +       if (ph->p_offset == 0)
> > > >>>> >> +         file_p_vaddr = ph->p_vaddr;
> > > >>>> >> +       break;
> > > >>>> >> +      case PT_DYNAMIC:
> > > >>>> >>         main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
> > > >>>> >>         break;
> > > >>>> >> +      default:
> > > >>>> >> +       break;
> > > >>>> >>        }
> > > >>>> >>
> > > >>>> >> +  /* Figure out the run-time load address of static PIE.  */
> > > >>>> >> +  ElfW(Addr) l_addr = elf_machine_load_address ();
> > > >>>> >> +  main_map->l_addr = l_addr - file_p_vaddr;
> > >
> > > Can you explain this? I though vaddr field was the true virtual-address
> > > but you seem to be treating it as an offset here.
> >
> > The l_addr field contains the difference between the address in the ELF
> > file and the address in memory.  file_p_vaddr is used as the address in
> > static PIE.  I updated comments in the v6 patch,
> >
> Okay, I think I understand. We were implicitly assuming vaddr was zero
> before by just using l_addr (v_addr + offset == true_addr if v_addr is zero).
> Is that correct?

offset isn't used explicitly.  l_addr is the difference between the
load address in the
ELF file and the actual address in memory.  The current code assumes that the
load address  in ELF file == 0.  My change computes the load address by using
p_vaddr of PT_LOAD segment at offset == 0.


>
> > Here is the v6 patch.  OK to install?
> >
> > Thanks.
> >
> > --
> > H.J.



--
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-10-26 22:02                   ` H.J. Lu
@ 2024-10-26 22:29                     ` H.J. Lu
  2024-10-28 14:54                       ` Noah Goldstein
  2024-11-29 16:52                       ` Florian Weimer
  0 siblings, 2 replies; 33+ messages in thread
From: H.J. Lu @ 2024-10-26 22:29 UTC (permalink / raw)
  To: Noah Goldstein; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

[-- Attachment #1: Type: text/plain, Size: 452 bytes --]

For a static PIE with non-zero load address, its PT_DYNAMIC segment
entries contain the relocated values for the load address in static PIE.
Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
the PT_LOAD segment with offset == 0 as the load address in static PIE
and adjust the entries of PT_DYNAMIC segment in static PIE by properly
setting the l_addr field for static PIE.  This fixes BZ #31799.

OK to install?

Thanks.

-- 
H.J.

[-- Attachment #2: v7-0001-elf-Handle-static-PIE-with-non-zero-load-address-.patch --]
[-- Type: text/x-patch, Size: 11447 bytes --]

From 7b4be3b7d2667b4dca3516311167788ddf78f580 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Sun, 26 May 2024 04:55:32 -0700
Subject: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ
 #31799]

For a static PIE with non-zero load address, its PT_DYNAMIC segment
entries contain the relocated values for the load address in static PIE.
Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
the PT_LOAD segment with offset == 0 as the load address in static PIE
and adjust the entries of PT_DYNAMIC segment in static PIE by properly
setting the l_addr field for static PIE.  This fixes BZ #31799.

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 configure                    | 74 ++++++++++++++++++++++++++++++++++++
 configure.ac                 | 36 ++++++++++++++++++
 elf/Makefile                 | 20 ++++++++++
 elf/dl-reloc-static-pie.c    | 30 +++++++++++----
 elf/tst-pie-address-static.c | 19 +++++++++
 elf/tst-pie-address.c        | 28 ++++++++++++++
 6 files changed, 200 insertions(+), 7 deletions(-)
 create mode 100644 elf/tst-pie-address-static.c
 create mode 100644 elf/tst-pie-address.c

diff --git a/configure b/configure
index 9c0c0dce03..9bcf62dca5 100755
--- a/configure
+++ b/configure
@@ -8107,6 +8107,80 @@ printf "%s\n" "$libc_cv_cc_pie_default" >&6; }
 config_vars="$config_vars
 cc-pie-default = $libc_cv_cc_pie_default"
 
+# Get Position Dependent Executable (PDE) load address to be used to
+# load static Position Independent Executable (PIE) at a known working
+# non-zero load address.  This is only used by glibc tests to verify
+# that PIE and static PIE with non-zero load address work correctly.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking PDE load address" >&5
+printf %s "checking PDE load address... " >&6; }
+if test ${libc_cv_pde_load_address+y}
+then :
+  printf %s "(cached) " >&6
+else case e in #(
+  e) cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+  pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+	    -nostartfiles -nostdlib $no_ssp \
+	    -o conftest conftest.S 1>&5 2>&5; then
+  # Get the load address of the first PT_LOAD segment.
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+			     | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+  as_fn_error $? "${CC-cc} can not create PDE" "$LINENO" 5
+fi
+rm -f conftest* ;;
+esac
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_cv_pde_load_address" >&5
+printf "%s\n" "$libc_cv_pde_load_address" >&6; }
+config_vars="$config_vars
+pde-load-address = $libc_cv_pde_load_address"
+
+# Get the linker command-line option to load executable at a non-zero
+# load address.  This is only used by glibc tests to verify that PIE and
+# static PIE with non-zero load address work correctly.
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address" >&5
+printf %s "checking for linker that supports -Ttext-segment=$libc_cv_pde_load_address... " >&6; }
+libc_linker_feature=no
+cat > conftest.c <<EOF
+int _start (void) { return 42; }
+EOF
+if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp
+		  -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib -nostartfiles
+		  -fPIC -shared -o conftest.so conftest.c
+		  1>&5'
+  { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+  (eval $ac_try) 2>&5
+  ac_status=$?
+  printf "%s\n" "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+  test $ac_status = 0; }; }
+then
+  if ${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp -Wl,-Ttext-segment=$libc_cv_pde_load_address -nostdlib \
+      -nostartfiles -fPIC -shared -o conftest.so conftest.c 2>&1 \
+      | grep "warning: -Ttext-segment=$libc_cv_pde_load_address ignored" > /dev/null 2>&1; then
+    true
+  else
+    libc_linker_feature=yes
+  fi
+fi
+rm -f conftest*
+if test $libc_linker_feature = yes; then
+  libc_cv_load_address_ldflag=-Wl,-Ttext-segment
+else
+  libc_cv_load_address_ldflag=
+fi
+{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5
+printf "%s\n" "$libc_linker_feature" >&6; }
+config_vars="$config_vars
+load-address-ldflag = $libc_cv_load_address_ldflag"
+
 { printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking if we can build programs as PIE" >&5
 printf %s "checking if we can build programs as PIE... " >&6; }
 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
diff --git a/configure.ac b/configure.ac
index d5a00461ff..895bd5267d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1763,6 +1763,42 @@ fi
 rm -f conftest.*])
 LIBC_CONFIG_VAR([cc-pie-default], [$libc_cv_cc_pie_default])
 
+# Get Position Dependent Executable (PDE) load address to be used to
+# load static Position Independent Executable (PIE) at a known working
+# non-zero load address.  This is only used by glibc tests to verify
+# that PIE and static PIE with non-zero load address work correctly.
+AC_CACHE_CHECK([PDE load address],
+	       libc_cv_pde_load_address, [dnl
+cat > conftest.S <<EOF
+.globl _start
+_start:
+.globl __start
+__start:
+EOF
+if test $libc_cv_cc_pie_default = yes; then
+  pde_ld_flags="-no-pie"
+fi
+if ${CC-cc} $pde_ld_flags $CFLAGS $CPPFLAGS $LDFLAGS \
+	    -nostartfiles -nostdlib $no_ssp \
+	    -o conftest conftest.S 1>&AS_MESSAGE_LOG_FD 2>&AS_MESSAGE_LOG_FD; then
+  # Get the load address of the first PT_LOAD segment.
+  libc_cv_pde_load_address=$(LC_ALL=C $READELF -Wl conftest \
+			     | $AWK '/LOAD/ { print $3; exit 0; }')
+else
+  AC_MSG_ERROR([${CC-cc} can not create PDE])
+fi
+rm -f conftest*])
+LIBC_CONFIG_VAR([pde-load-address], [$libc_cv_pde_load_address])
+
+# Get the linker command-line option to load executable at a non-zero
+# load address.  This is only used by glibc tests to verify that PIE and
+# static PIE with non-zero load address work correctly.
+LIBC_LINKER_FEATURE([-Ttext-segment=$libc_cv_pde_load_address],
+		    [-Wl,-Ttext-segment=$libc_cv_pde_load_address],
+		    [libc_cv_load_address_ldflag=-Wl,-Ttext-segment],
+		    [libc_cv_load_address_ldflag=])
+LIBC_CONFIG_VAR([load-address-ldflag], [$libc_cv_load_address_ldflag])
+
 AC_MSG_CHECKING(if we can build programs as PIE)
 AC_COMPILE_IFELSE([AC_LANG_SOURCE([[#ifdef PIE_UNSUPPORTED
 # error PIE is not supported
diff --git a/elf/Makefile b/elf/Makefile
index 9cfe738919..4eaca7af67 100644
--- a/elf/Makefile
+++ b/elf/Makefile
@@ -1091,6 +1091,25 @@ tests-pie += \
   tst-pie1 \
   tst-pie2 \
   # tests-pie
+ifneq (,$(load-address-ldflag))
+tests += \
+  tst-pie-address \
+  # tests
+tests-pie += \
+  tst-pie-address \
+  # tests-pie
+LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
+ifeq (yes,$(enable-static-pie))
+tests += \
+  tst-pie-address-static \
+  # tests
+tests-static += \
+  tst-pie-address-static \
+  # tests-static
+LDFLAGS-tst-pie-address-static += \
+  $(load-address-ldflag)=$(pde-load-address)
+endif
+endif
 ifeq (yes,$(have-protected-data))
 tests += vismain
 tests-pie += vismain
@@ -1937,6 +1956,7 @@ $(objpfx)tst-array5-static-cmp.out: tst-array5-static.exp \
 
 CFLAGS-tst-pie1.c += $(pie-ccflag)
 CFLAGS-tst-pie2.c += $(pie-ccflag)
+CFLAGS-tst-pie-address.c += $(pie-ccflag)
 
 $(objpfx)tst-piemod1.so: $(libsupport)
 $(objpfx)tst-pie1: $(objpfx)tst-piemod1.so
diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
index 10c23d0bf0..bfee89dfc3 100644
--- a/elf/dl-reloc-static-pie.c
+++ b/elf/dl-reloc-static-pie.c
@@ -37,21 +37,37 @@ _dl_relocate_static_pie (void)
 {
   struct link_map *main_map = _dl_get_dl_main_map ();
 
-  /* Figure out the run-time load address of static PIE.  */
-  main_map->l_addr = elf_machine_load_address ();
-
-  /* Read our own dynamic section and fill in the info array.  */
-  main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
-
+  /* NB: elf_machine_load_address () returns the run-time load address
+     of static PIE.  The l_addr field contains the difference between the
+     link-time load address in the ELF file and the run-time load address
+     in memory.  We must subtract the link-time load address of static PIE,
+     which can be non-zero, when computing the l_addr field.  Since static
+     PIE usually doesn't have PT_PHDR segment, use p_vaddr of the PT_LOAD
+     segment with offset == 0 as the load address of static PIE.  */
+  ElfW(Addr) file_p_vaddr = 0;
   const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
   size_t phnum = GL(dl_phnum);
   for (ph = phdr; ph < &phdr[phnum]; ++ph)
-    if (ph->p_type == PT_DYNAMIC)
+    switch (ph->p_type)
       {
+      case PT_LOAD:
+	if (ph->p_offset == 0)
+	  file_p_vaddr = ph->p_vaddr;
+	break;
+      case PT_DYNAMIC:
 	main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
 	break;
+      default:
+	break;
       }
 
+  /* Figure out the run-time load address of static PIE.  */
+  ElfW(Addr) l_addr = elf_machine_load_address ();
+  main_map->l_addr = l_addr - file_p_vaddr;
+
+  /* Read our own dynamic section and fill in the info array.  */
+  main_map->l_ld = ((void *) l_addr + elf_machine_dynamic ());
+
   elf_get_dynamic_info (main_map, false, true);
 
 # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
diff --git a/elf/tst-pie-address-static.c b/elf/tst-pie-address-static.c
new file mode 100644
index 0000000000..be2831e9d6
--- /dev/null
+++ b/elf/tst-pie-address-static.c
@@ -0,0 +1,19 @@
+/* Test static PIE with non-zero load address.
+   Copyright (C) 2024 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 "tst-pie-address.c"
diff --git a/elf/tst-pie-address.c b/elf/tst-pie-address.c
new file mode 100644
index 0000000000..aa1ca0a9fd
--- /dev/null
+++ b/elf/tst-pie-address.c
@@ -0,0 +1,28 @@
+/* Test PIE with non-zero load address.
+   Copyright (C) 2024 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 <stdio.h>
+
+static int
+do_test (void)
+{
+  printf ("Hello\n");
+  return 0;
+}
+
+#include <support/test-driver.c>
-- 
2.47.0


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-10-26 22:29                     ` [PATCH v7] elf: Handle static PIE with non-zero load " H.J. Lu
@ 2024-10-28 14:54                       ` Noah Goldstein
  2024-10-28 22:12                         ` H.J. Lu
  2024-11-29 16:52                       ` Florian Weimer
  1 sibling, 1 reply; 33+ messages in thread
From: Noah Goldstein @ 2024-10-28 14:54 UTC (permalink / raw)
  To: H.J. Lu; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

On Sat, Oct 26, 2024 at 5:29 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> For a static PIE with non-zero load address, its PT_DYNAMIC segment
> entries contain the relocated values for the load address in static PIE.
> Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
> the PT_LOAD segment with offset == 0 as the load address in static PIE
> and adjust the entries of PT_DYNAMIC segment in static PIE by properly
> setting the l_addr field for static PIE.  This fixes BZ #31799.
>
> OK to install?
>
> Thanks.

Can you post the V7 property instead of as an attachment?
But it looks fine to me.
>
> --
> H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-10-28 14:54                       ` Noah Goldstein
@ 2024-10-28 22:12                         ` H.J. Lu
  0 siblings, 0 replies; 33+ messages in thread
From: H.J. Lu @ 2024-10-28 22:12 UTC (permalink / raw)
  To: Noah Goldstein; +Cc: GNU C Library, Carlos O'Donell, Florian Weimer

On Mon, Oct 28, 2024 at 10:54 PM Noah Goldstein <goldstein.w.n@gmail.com> wrote:
>
> On Sat, Oct 26, 2024 at 5:29 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > For a static PIE with non-zero load address, its PT_DYNAMIC segment
> > entries contain the relocated values for the load address in static PIE.
> > Since static PIE usually doesn't have PT_PHDR segment, use p_vaddr of
> > the PT_LOAD segment with offset == 0 as the load address in static PIE
> > and adjust the entries of PT_DYNAMIC segment in static PIE by properly
> > setting the l_addr field for static PIE.  This fixes BZ #31799.
> >
> > OK to install?
> >
> > Thanks.
>
> Can you post the V7 property instead of as an attachment?

Done.

> But it looks fine to me.
> >
> > --
> > H.J.



-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-10-26 22:29                     ` [PATCH v7] elf: Handle static PIE with non-zero load " H.J. Lu
  2024-10-28 14:54                       ` Noah Goldstein
@ 2024-11-29 16:52                       ` Florian Weimer
  2024-11-30  4:18                         ` H.J. Lu
  1 sibling, 1 reply; 33+ messages in thread
From: Florian Weimer @ 2024-11-29 16:52 UTC (permalink / raw)
  To: H.J. Lu; +Cc: Noah Goldstein, GNU C Library, Carlos O'Donell

* H. J. Lu:

> +ifneq (,$(load-address-ldflag))
> +tests += \
> +  tst-pie-address \
> +  # tests
> +tests-pie += \
> +  tst-pie-address \
> +  # tests-pie
> +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> +ifeq (yes,$(enable-static-pie))
> +tests += \
> +  tst-pie-address-static \
> +  # tests
> +tests-static += \
> +  tst-pie-address-static \
> +  # tests-static
> +LDFLAGS-tst-pie-address-static += \
> +  $(load-address-ldflag)=$(pde-load-address)
> +endif
> +endif

These tests fail on aarch64 and s390x for us:

=====FAIL: elf/tst-pie-address.out=====
=====FAIL: elf/tst-pie-address.test-result=====
FAIL: elf/tst-pie-address
original exit status 139
=====FAIL: elf/tst-pie-address-static.out=====
=====FAIL: elf/tst-pie-address-static.test-result=====
FAIL: elf/tst-pie-address-static
original exit status 132

The configure checks report this 

checking whether -fPIE is default... no
checking PDE load address... 0x0000000001000000
checking for linker that supports -Ttext-segment=0x0000000001000000... yes
checking if we can build programs as PIE... yes
checking if we can build static PIE programs... yes

checking whether -fPIE is default... no
checking PDE load address... 0x0000000000400000
checking for linker that supports -Ttext-segment=0x0000000000400000... yes
checking if we can build programs as PIE... yes
checking if we can build static PIE programs... yes

Thanks,
Florian


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-11-29 16:52                       ` Florian Weimer
@ 2024-11-30  4:18                         ` H.J. Lu
  2024-12-02  1:15                           ` H.J. Lu
  2024-12-02  9:09                           ` [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799] Stefan Liebler
  0 siblings, 2 replies; 33+ messages in thread
From: H.J. Lu @ 2024-11-30  4:18 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Noah Goldstein, GNU C Library, Carlos O'Donell

[-- Attachment #1: Type: text/plain, Size: 1783 bytes --]

On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:

> * H. J. Lu:
>
> > +ifneq (,$(load-address-ldflag))
> > +tests += \
> > +  tst-pie-address \
> > +  # tests
> > +tests-pie += \
> > +  tst-pie-address \
> > +  # tests-pie
> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> > +ifeq (yes,$(enable-static-pie))
> > +tests += \
> > +  tst-pie-address-static \
> > +  # tests
> > +tests-static += \
> > +  tst-pie-address-static \
> > +  # tests-static
> > +LDFLAGS-tst-pie-address-static += \
> > +  $(load-address-ldflag)=$(pde-load-address)
> > +endif
> > +endif
>
> These tests fail on aarch64 and s390x for us:
>
> =====FAIL: elf/tst-pie-address.out=====
> =====FAIL: elf/tst-pie-address.test-result=====
> FAIL: elf/tst-pie-address
> original exit status 139
> =====FAIL: elf/tst-pie-address-static.out=====
> =====FAIL: elf/tst-pie-address-static.test-result=====
> FAIL: elf/tst-pie-address-static
> original exit status 132
>

Do they fail without -Ttext-segment=? My change doesn't
touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.


> The configure checks report this
>
> checking whether -fPIE is default... no
> checking PDE load address... 0x0000000001000000
> checking for linker that supports -Ttext-segment=0x0000000001000000... yes
> checking if we can build programs as PIE... yes
> checking if we can build static PIE programs... yes
>
> checking whether -fPIE is default... no
> checking PDE load address... 0x0000000000400000
> checking for linker that supports -Ttext-segment=0x0000000000400000... yes
> checking if we can build programs as PIE... yes
> checking if we can build static PIE programs... yes
>
> Thanks,
> Florian
>
>
>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-11-30  4:18                         ` H.J. Lu
@ 2024-12-02  1:15                           ` H.J. Lu
  2024-12-02  6:36                             ` [PATCH] elf: Check PDE load address with non-empty text section H.J. Lu
  2024-12-02  9:09                           ` [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799] Stefan Liebler
  1 sibling, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-12-02  1:15 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Noah Goldstein, GNU C Library, Carlos O'Donell

On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
>>
>> * H. J. Lu:
>>
>> > +ifneq (,$(load-address-ldflag))
>> > +tests += \
>> > +  tst-pie-address \
>> > +  # tests
>> > +tests-pie += \
>> > +  tst-pie-address \
>> > +  # tests-pie
>> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>> > +ifeq (yes,$(enable-static-pie))
>> > +tests += \
>> > +  tst-pie-address-static \
>> > +  # tests
>> > +tests-static += \
>> > +  tst-pie-address-static \
>> > +  # tests-static
>> > +LDFLAGS-tst-pie-address-static += \
>> > +  $(load-address-ldflag)=$(pde-load-address)
>> > +endif
>> > +endif
>>
>> These tests fail on aarch64 and s390x for us:
>>
>> =====FAIL: elf/tst-pie-address.out=====
>> =====FAIL: elf/tst-pie-address.test-result=====
>> FAIL: elf/tst-pie-address
>> original exit status 139
>> =====FAIL: elf/tst-pie-address-static.out=====
>> =====FAIL: elf/tst-pie-address-static.test-result=====
>> FAIL: elf/tst-pie-address-static
>> original exit status 132
>
>
> Do they fail without -Ttext-segment=? My change doesn't
> touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
>
>>
>> The configure checks report this
>>
>> checking whether -fPIE is default... no
>> checking PDE load address... 0x0000000001000000

Somehow aarch64 got

pde-load-address =

in config.make.  I will take a look.

>> checking for linker that supports -Ttext-segment=0x0000000001000000... yes
>> checking if we can build programs as PIE... yes
>> checking if we can build static PIE programs... yes
>>
>> checking whether -fPIE is default... no
>> checking PDE load address... 0x0000000000400000
>> checking for linker that supports -Ttext-segment=0x0000000000400000... yes
>> checking if we can build programs as PIE... yes
>> checking if we can build static PIE programs... yes
>>
>> Thanks,
>> Florian
>>
>>


-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-02  1:15                           ` H.J. Lu
@ 2024-12-02  6:36                             ` H.J. Lu
  2024-12-22  0:34                               ` H.J. Lu
                                                 ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: H.J. Lu @ 2024-12-02  6:36 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Noah Goldstein, GNU C Library, Carlos O'Donell

[-- Attachment #1: Type: text/plain, Size: 1821 bytes --]

On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
> >>
> >> * H. J. Lu:
> >>
> >> > +ifneq (,$(load-address-ldflag))
> >> > +tests += \
> >> > +  tst-pie-address \
> >> > +  # tests
> >> > +tests-pie += \
> >> > +  tst-pie-address \
> >> > +  # tests-pie
> >> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> >> > +ifeq (yes,$(enable-static-pie))
> >> > +tests += \
> >> > +  tst-pie-address-static \
> >> > +  # tests
> >> > +tests-static += \
> >> > +  tst-pie-address-static \
> >> > +  # tests-static
> >> > +LDFLAGS-tst-pie-address-static += \
> >> > +  $(load-address-ldflag)=$(pde-load-address)
> >> > +endif
> >> > +endif
> >>
> >> These tests fail on aarch64 and s390x for us:
> >>
> >> =====FAIL: elf/tst-pie-address.out=====
> >> =====FAIL: elf/tst-pie-address.test-result=====
> >> FAIL: elf/tst-pie-address
> >> original exit status 139
> >> =====FAIL: elf/tst-pie-address-static.out=====
> >> =====FAIL: elf/tst-pie-address-static.test-result=====
> >> FAIL: elf/tst-pie-address-static
> >> original exit status 132
> >
> >
> > Do they fail without -Ttext-segment=? My change doesn't
> > touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
> >
> >>
> >> The configure checks report this
> >>
> >> checking whether -fPIE is default... no
> >> checking PDE load address... 0x0000000001000000
>
> Somehow aarch64 got
>
> pde-load-address =
>
> in config.make.  I will take a look.
>

Does this patch it for you?

Check PDE load address with non-empty text section:

.globl _start
_start:
.globl __start
.byte 0

-- 
H.J.

[-- Attachment #2: 0001-elf-Check-PDE-load-address-with-non-empty-text-secti.patch --]
[-- Type: text/x-patch, Size: 1001 bytes --]

From abc2604d98bfcb28fc8fb4095c73140fe48e24e4 Mon Sep 17 00:00:00 2001
From: "H.J. Lu" <hjl.tools@gmail.com>
Date: Mon, 2 Dec 2024 14:22:46 +0800
Subject: [PATCH] elf: Check PDE load address with non-empty text section

Check PDE load address with non-empty text section:

.globl _start
_start:
.globl __start
	.byte 0

Signed-off-by: H.J. Lu <hjl.tools@gmail.com>
---
 configure    | 1 +
 configure.ac | 1 +
 2 files changed, 2 insertions(+)

diff --git a/configure b/configure
index 9bcf62dca5..0e42f21926 100755
--- a/configure
+++ b/configure
@@ -8122,6 +8122,7 @@ else case e in #(
 _start:
 .globl __start
 __start:
+	.byte 0
 EOF
 if test $libc_cv_cc_pie_default = yes; then
   pde_ld_flags="-no-pie"
diff --git a/configure.ac b/configure.ac
index 895bd5267d..02339a0a4c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1774,6 +1774,7 @@ cat > conftest.S <<EOF
 _start:
 .globl __start
 __start:
+	.byte 0
 EOF
 if test $libc_cv_cc_pie_default = yes; then
   pde_ld_flags="-no-pie"
-- 
2.47.1


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799]
  2024-11-30  4:18                         ` H.J. Lu
  2024-12-02  1:15                           ` H.J. Lu
@ 2024-12-02  9:09                           ` Stefan Liebler
  1 sibling, 0 replies; 33+ messages in thread
From: Stefan Liebler @ 2024-12-02  9:09 UTC (permalink / raw)
  To: libc-alpha

On 30.11.24 05:18, H.J. Lu wrote:
> On Sat, Nov 30, 2024, 12: 52 AM Florian Weimer <fweimer@ redhat. com>
> wrote: * H. J. Lu: > +ifneq (,$(load-address-ldflag)) > +tests += \ > +
> tst-pie-address \ > + # tests > +tests-pie += \ > + tst-pie-address \ > + #
> 
> On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com
> <mailto:fweimer@redhat.com>> wrote:
> 
>     * H. J. Lu:
> 
>     > +ifneq (,$(load-address-ldflag))
>     > +tests += \
>     > +  tst-pie-address \
>     > +  # tests
>     > +tests-pie += \
>     > +  tst-pie-address \
>     > +  # tests-pie
>     > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>     > +ifeq (yes,$(enable-static-pie))
>     > +tests += \
>     > +  tst-pie-address-static \
>     > +  # tests
>     > +tests-static += \
>     > +  tst-pie-address-static \
>     > +  # tests-static
>     > +LDFLAGS-tst-pie-address-static += \
>     > +  $(load-address-ldflag)=$(pde-load-address)
>     > +endif
>     > +endif
> 
>     These tests fail on aarch64 and s390x for us:
> 
>     =====FAIL: elf/tst-pie-address.out=====
>     =====FAIL: elf/tst-pie-address.test-result=====
>     FAIL: elf/tst-pie-address
>     original exit status 139
>     =====FAIL: elf/tst-pie-address-static.out=====
>     =====FAIL: elf/tst-pie-address-static.test-result=====
>     FAIL: elf/tst-pie-address-static
>     original exit status 132
> 
> 
> Do they fail without -Ttext-segment=? My change doesn't
> touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
I've also recognized this fail. At least on s390, it segfaults in this
already relocated static PIE case, as elf_machine_load_address() returns
0x0 (The got entry of _dl_start already contains the run-time-address
and thus the diff is zero) and elf_machine_load_address() is also wrong.
I'm already working on a patch relying on __ehdr_start and __DYNAMIC
similar to other architectures. Will do some tests first and then post a
patch for s390x.

Bye,
Stefan
> 
> 
>     The configure checks report this
> 
>     checking whether -fPIE is default... no
>     checking PDE load address... 0x0000000001000000
>     checking for linker that supports -Ttext-
>     segment=0x0000000001000000... yes
>     checking if we can build programs as PIE... yes
>     checking if we can build static PIE programs... yes
> 
>     checking whether -fPIE is default... no
>     checking PDE load address... 0x0000000000400000
>     checking for linker that supports -Ttext-
>     segment=0x0000000000400000... yes
>     checking if we can build programs as PIE... yes
>     checking if we can build static PIE programs... yes
> 
>     Thanks,
>     Florian
> 
> 


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-02  6:36                             ` [PATCH] elf: Check PDE load address with non-empty text section H.J. Lu
@ 2024-12-22  0:34                               ` H.J. Lu
  2024-12-22  6:18                               ` Sam James
  2025-01-05 12:10                               ` Aurelien Jarno
  2 siblings, 0 replies; 33+ messages in thread
From: H.J. Lu @ 2024-12-22  0:34 UTC (permalink / raw)
  To: Florian Weimer, Sam James; +Cc: GNU C Library, Carlos O'Donell

On Mon, Dec 2, 2024 at 2:36 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>
> On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
>
> Check PDE load address with non-empty text section:
>
> .globl _start
> _start:
> .globl __start
> .byte 0
>
> --
> H.J.

PING:

https://sourceware.org/pipermail/libc-alpha/2024-December/162989.html

-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-02  6:36                             ` [PATCH] elf: Check PDE load address with non-empty text section H.J. Lu
  2024-12-22  0:34                               ` H.J. Lu
@ 2024-12-22  6:18                               ` Sam James
  2024-12-22  6:47                                 ` H.J. Lu
  2025-01-05 12:10                               ` Aurelien Jarno
  2 siblings, 1 reply; 33+ messages in thread
From: Sam James @ 2024-12-22  6:18 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Florian Weimer, Noah Goldstein, GNU C Library, Carlos O'Donell

"H.J. Lu" <hjl.tools@gmail.com> writes:

> On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>>
>> On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>> >
>> > On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
>> >>
>> >> * H. J. Lu:
>> >>
>> >> > +ifneq (,$(load-address-ldflag))
>> >> > +tests += \
>> >> > +  tst-pie-address \
>> >> > +  # tests
>> >> > +tests-pie += \
>> >> > +  tst-pie-address \
>> >> > +  # tests-pie
>> >> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>> >> > +ifeq (yes,$(enable-static-pie))
>> >> > +tests += \
>> >> > +  tst-pie-address-static \
>> >> > +  # tests
>> >> > +tests-static += \
>> >> > +  tst-pie-address-static \
>> >> > +  # tests-static
>> >> > +LDFLAGS-tst-pie-address-static += \
>> >> > +  $(load-address-ldflag)=$(pde-load-address)
>> >> > +endif
>> >> > +endif
>> >>
>> >> These tests fail on aarch64 and s390x for us:
>> >>
>> >> =====FAIL: elf/tst-pie-address.out=====
>> >> =====FAIL: elf/tst-pie-address.test-result=====
>> >> FAIL: elf/tst-pie-address
>> >> original exit status 139
>> >> =====FAIL: elf/tst-pie-address-static.out=====
>> >> =====FAIL: elf/tst-pie-address-static.test-result=====
>> >> FAIL: elf/tst-pie-address-static
>> >> original exit status 132
>> >
>> >
>> > Do they fail without -Ttext-segment=? My change doesn't
>> > touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
>> >
>> >>
>> >> The configure checks report this
>> >>
>> >> checking whether -fPIE is default... no
>> >> checking PDE load address... 0x0000000001000000
>>
>> Somehow aarch64 got
>>
>> pde-load-address =
>>
>> in config.make.  I will take a look.
>>
>
> Does this patch it for you?
>
> Check PDE load address with non-empty text section:
>
> .globl _start
> _start:
> .globl __start
> .byte 0

LGTM, but I didn't check it on arm64. I can if you need.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-22  6:18                               ` Sam James
@ 2024-12-22  6:47                                 ` H.J. Lu
  2024-12-22  8:12                                   ` Sam James
  0 siblings, 1 reply; 33+ messages in thread
From: H.J. Lu @ 2024-12-22  6:47 UTC (permalink / raw)
  To: Sam James
  Cc: Florian Weimer, Noah Goldstein, GNU C Library, Carlos O'Donell

[-- Attachment #1: Type: text/plain, Size: 2228 bytes --]

On Sun, Dec 22, 2024, 2:19 PM Sam James <sam@gentoo.org> wrote:

> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
> > On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >>
> >> On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >> >
> >> > On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com>
> wrote:
> >> >>
> >> >> * H. J. Lu:
> >> >>
> >> >> > +ifneq (,$(load-address-ldflag))
> >> >> > +tests += \
> >> >> > +  tst-pie-address \
> >> >> > +  # tests
> >> >> > +tests-pie += \
> >> >> > +  tst-pie-address \
> >> >> > +  # tests-pie
> >> >> > +LDFLAGS-tst-pie-address +=
> $(load-address-ldflag)=$(pde-load-address)
> >> >> > +ifeq (yes,$(enable-static-pie))
> >> >> > +tests += \
> >> >> > +  tst-pie-address-static \
> >> >> > +  # tests
> >> >> > +tests-static += \
> >> >> > +  tst-pie-address-static \
> >> >> > +  # tests-static
> >> >> > +LDFLAGS-tst-pie-address-static += \
> >> >> > +  $(load-address-ldflag)=$(pde-load-address)
> >> >> > +endif
> >> >> > +endif
> >> >>
> >> >> These tests fail on aarch64 and s390x for us:
> >> >>
> >> >> =====FAIL: elf/tst-pie-address.out=====
> >> >> =====FAIL: elf/tst-pie-address.test-result=====
> >> >> FAIL: elf/tst-pie-address
> >> >> original exit status 139
> >> >> =====FAIL: elf/tst-pie-address-static.out=====
> >> >> =====FAIL: elf/tst-pie-address-static.test-result=====
> >> >> FAIL: elf/tst-pie-address-static
> >> >> original exit status 132
> >> >
> >> >
> >> > Do they fail without -Ttext-segment=? My change doesn't
> >> > touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
> >> >
> >> >>
> >> >> The configure checks report this
> >> >>
> >> >> checking whether -fPIE is default... no
> >> >> checking PDE load address... 0x0000000001000000
> >>
> >> Somehow aarch64 got
> >>
> >> pde-load-address =
> >>
> >> in config.make.  I will take a look.
> >>
> >
> > Does this patch it for you?
> >
> > Check PDE load address with non-empty text section:
> >
> > .globl _start
> > _start:
> > .globl __start
> > .byte 0
>
> LGTM, but I didn't check it on arm64. I can if you need.
>

Yes, please.

Thanks.


>

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-22  6:47                                 ` H.J. Lu
@ 2024-12-22  8:12                                   ` Sam James
  2024-12-22  8:15                                     ` H.J. Lu
  0 siblings, 1 reply; 33+ messages in thread
From: Sam James @ 2024-12-22  8:12 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Florian Weimer, Noah Goldstein, GNU C Library, Carlos O'Donell

"H.J. Lu" <hjl.tools@gmail.com> writes:

> On Sun, Dec 22, 2024, 2:19 PM Sam James <sam@gentoo.org> wrote:
>
>  "H.J. Lu" <hjl.tools@gmail.com> writes:
>
>  > On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
>  >>
>  >> On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
>  >> >
>  >> > On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
>  >> >>
>  >> >> * H. J. Lu:
>  >> >>
>  >> >> > +ifneq (,$(load-address-ldflag))
>  >> >> > +tests += \
>  >> >> > +  tst-pie-address \
>  >> >> > +  # tests
>  >> >> > +tests-pie += \
>  >> >> > +  tst-pie-address \
>  >> >> > +  # tests-pie
>  >> >> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
>  >> >> > +ifeq (yes,$(enable-static-pie))
>  >> >> > +tests += \
>  >> >> > +  tst-pie-address-static \
>  >> >> > +  # tests
>  >> >> > +tests-static += \
>  >> >> > +  tst-pie-address-static \
>  >> >> > +  # tests-static
>  >> >> > +LDFLAGS-tst-pie-address-static += \
>  >> >> > +  $(load-address-ldflag)=$(pde-load-address)
>  >> >> > +endif
>  >> >> > +endif
>  >> >>
>  >> >> These tests fail on aarch64 and s390x for us:
>  >> >>
>  >> >> =====FAIL: elf/tst-pie-address.out=====
>  >> >> =====FAIL: elf/tst-pie-address.test-result=====
>  >> >> FAIL: elf/tst-pie-address
>  >> >> original exit status 139
>  >> >> =====FAIL: elf/tst-pie-address-static.out=====
>  >> >> =====FAIL: elf/tst-pie-address-static.test-result=====
>  >> >> FAIL: elf/tst-pie-address-static
>  >> >> original exit status 132
>  >> >
>  >> >
>  >> > Do they fail without -Ttext-segment=? My change doesn't
>  >> > touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
>  >> >
>  >> >>
>  >> >> The configure checks report this
>  >> >>
>  >> >> checking whether -fPIE is default... no
>  >> >> checking PDE load address... 0x0000000001000000
>  >>
>  >> Somehow aarch64 got
>  >>
>  >> pde-load-address =
>  >>
>  >> in config.make.  I will take a look.
>  >>
>  >
>  > Does this patch it for you?
>  >
>  > Check PDE load address with non-empty text section:
>  >
>  > .globl _start
>  > _start:
>  > .globl __start
>  > .byte 0
>
>  LGTM, but I didn't check it on arm64. I can if you need.
>
> Yes, please.

On trunk, I see:

checking whether -fPIC is default... yes
checking whether -fPIE is default... yes
checking PDE load address...
checking for linker that supports -Ttext-segment=... yes
checking if we can build programs as PIE... yes
checking if we can build static PIE programs... yes

With your patch, I see:

checking whether -fPIC is default... yes
checking whether -fPIE is default... yes
checking PDE load address... 0x0000000000400000
checking for linker that supports -Ttext-segment=0x0000000000400000... yes
checking if we can build programs as PIE... yes
checking if we can build static PIE programs... yes

But I couldn't reproduce the original failure (I assume because default
PIE and some hacks to try repro it didn't work either). No new test
failures.

>
> Thanks.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-22  8:12                                   ` Sam James
@ 2024-12-22  8:15                                     ` H.J. Lu
  0 siblings, 0 replies; 33+ messages in thread
From: H.J. Lu @ 2024-12-22  8:15 UTC (permalink / raw)
  To: Sam James
  Cc: Florian Weimer, Noah Goldstein, GNU C Library, Carlos O'Donell

On Sun, Dec 22, 2024 at 4:12 PM Sam James <sam@gentoo.org> wrote:
>
> "H.J. Lu" <hjl.tools@gmail.com> writes:
>
> > On Sun, Dec 22, 2024, 2:19 PM Sam James <sam@gentoo.org> wrote:
> >
> >  "H.J. Lu" <hjl.tools@gmail.com> writes:
> >
> >  > On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >  >>
> >  >> On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> >  >> >
> >  >> > On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
> >  >> >>
> >  >> >> * H. J. Lu:
> >  >> >>
> >  >> >> > +ifneq (,$(load-address-ldflag))
> >  >> >> > +tests += \
> >  >> >> > +  tst-pie-address \
> >  >> >> > +  # tests
> >  >> >> > +tests-pie += \
> >  >> >> > +  tst-pie-address \
> >  >> >> > +  # tests-pie
> >  >> >> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> >  >> >> > +ifeq (yes,$(enable-static-pie))
> >  >> >> > +tests += \
> >  >> >> > +  tst-pie-address-static \
> >  >> >> > +  # tests
> >  >> >> > +tests-static += \
> >  >> >> > +  tst-pie-address-static \
> >  >> >> > +  # tests-static
> >  >> >> > +LDFLAGS-tst-pie-address-static += \
> >  >> >> > +  $(load-address-ldflag)=$(pde-load-address)
> >  >> >> > +endif
> >  >> >> > +endif
> >  >> >>
> >  >> >> These tests fail on aarch64 and s390x for us:
> >  >> >>
> >  >> >> =====FAIL: elf/tst-pie-address.out=====
> >  >> >> =====FAIL: elf/tst-pie-address.test-result=====
> >  >> >> FAIL: elf/tst-pie-address
> >  >> >> original exit status 139
> >  >> >> =====FAIL: elf/tst-pie-address-static.out=====
> >  >> >> =====FAIL: elf/tst-pie-address-static.test-result=====
> >  >> >> FAIL: elf/tst-pie-address-static
> >  >> >> original exit status 132
> >  >> >
> >  >> >
> >  >> > Do they fail without -Ttext-segment=? My change doesn't
> >  >> > touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
> >  >> >
> >  >> >>
> >  >> >> The configure checks report this
> >  >> >>
> >  >> >> checking whether -fPIE is default... no
> >  >> >> checking PDE load address... 0x0000000001000000
> >  >>
> >  >> Somehow aarch64 got
> >  >>
> >  >> pde-load-address =
> >  >>
> >  >> in config.make.  I will take a look.
> >  >>
> >  >
> >  > Does this patch it for you?
> >  >
> >  > Check PDE load address with non-empty text section:
> >  >
> >  > .globl _start
> >  > _start:
> >  > .globl __start
> >  > .byte 0
> >
> >  LGTM, but I didn't check it on arm64. I can if you need.
> >
> > Yes, please.
>
> On trunk, I see:
>
> checking whether -fPIC is default... yes
> checking whether -fPIE is default... yes
> checking PDE load address...
> checking for linker that supports -Ttext-segment=... yes
> checking if we can build programs as PIE... yes
> checking if we can build static PIE programs... yes
>
> With your patch, I see:
>
> checking whether -fPIC is default... yes
> checking whether -fPIE is default... yes
> checking PDE load address... 0x0000000000400000
> checking for linker that supports -Ttext-segment=0x0000000000400000... yes
> checking if we can build programs as PIE... yes
> checking if we can build static PIE programs... yes
>
> But I couldn't reproduce the original failure (I assume because default
> PIE and some hacks to try repro it didn't work either). No new test
> failures.
>

Yes, the configure log looks good. I am checking it in.

Thanks.

-- 
H.J.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: [PATCH] elf: Check PDE load address with non-empty text section
  2024-12-02  6:36                             ` [PATCH] elf: Check PDE load address with non-empty text section H.J. Lu
  2024-12-22  0:34                               ` H.J. Lu
  2024-12-22  6:18                               ` Sam James
@ 2025-01-05 12:10                               ` Aurelien Jarno
  2 siblings, 0 replies; 33+ messages in thread
From: Aurelien Jarno @ 2025-01-05 12:10 UTC (permalink / raw)
  To: H.J. Lu
  Cc: Florian Weimer, Noah Goldstein, GNU C Library, Carlos O'Donell

On 2024-12-02 14:36, H.J. Lu wrote:
> On Mon, Dec 2, 2024 at 9:15 AM H.J. Lu <hjl.tools@gmail.com> wrote:
> >
> > On Sat, Nov 30, 2024 at 12:18 PM H.J. Lu <hjl.tools@gmail.com> wrote:
> > >
> > > On Sat, Nov 30, 2024, 12:52 AM Florian Weimer <fweimer@redhat.com> wrote:
> > >>
> > >> * H. J. Lu:
> > >>
> > >> > +ifneq (,$(load-address-ldflag))
> > >> > +tests += \
> > >> > +  tst-pie-address \
> > >> > +  # tests
> > >> > +tests-pie += \
> > >> > +  tst-pie-address \
> > >> > +  # tests-pie
> > >> > +LDFLAGS-tst-pie-address += $(load-address-ldflag)=$(pde-load-address)
> > >> > +ifeq (yes,$(enable-static-pie))
> > >> > +tests += \
> > >> > +  tst-pie-address-static \
> > >> > +  # tests
> > >> > +tests-static += \
> > >> > +  tst-pie-address-static \
> > >> > +  # tests-static
> > >> > +LDFLAGS-tst-pie-address-static += \
> > >> > +  $(load-address-ldflag)=$(pde-load-address)
> > >> > +endif
> > >> > +endif
> > >>
> > >> These tests fail on aarch64 and s390x for us:
> > >>
> > >> =====FAIL: elf/tst-pie-address.out=====
> > >> =====FAIL: elf/tst-pie-address.test-result=====
> > >> FAIL: elf/tst-pie-address
> > >> original exit status 139
> > >> =====FAIL: elf/tst-pie-address-static.out=====
> > >> =====FAIL: elf/tst-pie-address-static.test-result=====
> > >> FAIL: elf/tst-pie-address-static
> > >> original exit status 132
> > >
> > >
> > > Do they fail without -Ttext-segment=? My change doesn't
> > > touch dynamic PIE.  If it fails, it may be due to glibc or ld bugs.
> > >
> > >>
> > >> The configure checks report this
> > >>
> > >> checking whether -fPIE is default... no
> > >> checking PDE load address... 0x0000000001000000
> >
> > Somehow aarch64 got
> >
> > pde-load-address =
> >
> > in config.make.  I will take a look.
> >
> 
> Does this patch it for you?
> 

Unfortunately those tests still fail here on aarch64, even with that
patch installed, even if the PDE load address seems correctly detected:

| checking whether -fPIE is default... yes
| checking PDE load address... 0x0000000000400000
| checking for linker that supports -Ttext-segment=0x0000000000400000... yes
| checking if we can build programs as PIE... yes

I have found that they only fail with a compiler defaulting to
-mbranch-protection=standard. This can also be reproduced by
running:

CC="gcc -mbranch-protection=standard" CXX="g++ -mbranch-protection=standard" ../glibc/configure --prefix=/usr && make -j4 && make -j4 check

-- 
Aurelien Jarno                          GPG: 4096R/1DDD8C9B
aurelien@aurel32.net                     http://aurel32.net

^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2025-01-05 12:11 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-27 14:38 [PATCH v5 0/1] elf: Handle static PIE loaded at the specific address H.J. Lu
2024-05-27 14:38 ` [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799] H.J. Lu
2024-05-28  6:05   ` Florian Weimer
2024-05-28 12:21     ` H.J. Lu
2024-06-14 10:36       ` Florian Weimer
2024-06-15  1:59         ` H.J. Lu
2024-07-01 17:22           ` Florian Weimer
2024-07-01 21:26             ` H.J. Lu
2024-05-28 14:28   ` Adhemerval Zanella Netto
2024-05-28 14:45     ` H.J. Lu
2024-06-30 20:47   ` PING: " H.J. Lu
2024-09-21 23:36     ` PING^2: " H.J. Lu
2024-10-02  9:45       ` PING^3: " H.J. Lu
2024-10-07 22:41         ` PING^4: " H.J. Lu
2024-10-21 21:51           ` PING^5: " H.J. Lu
2024-10-23 14:30             ` Noah Goldstein
2024-10-25 22:18               ` [PATCH v6 1/1] elf: Handle static PIE loaded at the non-zero " H.J. Lu
2024-10-26 18:49                 ` Noah Goldstein
2024-10-26 22:02                   ` H.J. Lu
2024-10-26 22:29                     ` [PATCH v7] elf: Handle static PIE with non-zero load " H.J. Lu
2024-10-28 14:54                       ` Noah Goldstein
2024-10-28 22:12                         ` H.J. Lu
2024-11-29 16:52                       ` Florian Weimer
2024-11-30  4:18                         ` H.J. Lu
2024-12-02  1:15                           ` H.J. Lu
2024-12-02  6:36                             ` [PATCH] elf: Check PDE load address with non-empty text section H.J. Lu
2024-12-22  0:34                               ` H.J. Lu
2024-12-22  6:18                               ` Sam James
2024-12-22  6:47                                 ` H.J. Lu
2024-12-22  8:12                                   ` Sam James
2024-12-22  8:15                                     ` H.J. Lu
2025-01-05 12:10                               ` Aurelien Jarno
2024-12-02  9:09                           ` [PATCH v7] elf: Handle static PIE with non-zero load address [BZ #31799] Stefan Liebler

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