PING^2: [PATCH v5 1/1] elf: Handle static PIE loaded at the specific address [BZ #31799]
H.J. Lu
hjl.tools@gmail.com
Sat Sep 21 23:36:24 GMT 2024
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.
More information about the Libc-alpha
mailing list