sync some patches for elf
details: elf: Handle static PIE with non-zero load address elf: Introduce _dl_relocate_object_no_relro elf: Switch to main malloc after final ld.so self-relocation (cherry picked from commit 839e7c9f5f823e8b4e7c22ca5e13d2745399dcd7)
This commit is contained in:
parent
74c1f0f4f2
commit
c0bdb30991
@ -0,0 +1,308 @@
|
|||||||
|
From e7b553272196e6175b8a15f807cb59217ba2843a Mon Sep 17 00:00:00 2001
|
||||||
|
From: "H.J. Lu" <hjl.tools@gmail.com>
|
||||||
|
Date: Tue, 29 Oct 2024 06:01:14 +0800
|
||||||
|
Subject: [PATCH] elf: Handle static PIE with non-zero load address [BZ #31799]
|
||||||
|
|
||||||
|
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=e7b553272196e6175b8a15f807cb59217ba2843a
|
||||||
|
Conflict:The context of the modified content is slightly different.
|
||||||
|
|
||||||
|
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>
|
||||||
|
Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
|
||||||
|
---
|
||||||
|
configure | 73 ++++++++++++++++++++++++++++++++++++
|
||||||
|
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, 199 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 be2277b1..ae83d509 100755
|
||||||
|
--- a/configure
|
||||||
|
+++ b/configure
|
||||||
|
@@ -6925,6 +6925,79 @@ $as_echo "$libc_cv_cc_pie_default" >&6; }
|
||||||
|
libc_cv_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"
|
||||||
|
|
||||||
|
# Set the `multidir' variable by grabbing the variable from the compiler.
|
||||||
|
# We do it once and save the result in a generated makefile.
|
||||||
|
diff --git a/configure.ac b/configure.ac
|
||||||
|
index fa34af26..0ea4cbe9 100644
|
||||||
|
--- a/configure.ac
|
||||||
|
+++ b/configure.ac
|
||||||
|
@@ -1853,6 +1853,42 @@ libc_cv_pie_default=$libc_cv_cc_pie_default
|
||||||
|
AC_SUBST(libc_cv_cc_pie_default)
|
||||||
|
AC_SUBST(libc_cv_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])
|
||||||
|
+
|
||||||
|
# Set the `multidir' variable by grabbing the variable from the compiler.
|
||||||
|
# We do it once and save the result in a generated makefile.
|
||||||
|
libc_cv_multidir=`${CC-cc} $CFLAGS $CPPFLAGS -print-multi-directory`
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index 89ab30cd..e6f78d7f 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -844,6 +844,25 @@ modules-names += tst-piemod1
|
||||||
|
tests += tst-pie1 tst-pie2 tst-dlopen-pie tst-dlopen-tlsmodid-pie \
|
||||||
|
tst-dlopen-self-pie
|
||||||
|
tests-pie += tst-pie1 tst-pie2 tst-dlopen-tlsmodid-pie tst-dlopen-self-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
|
||||||
|
@@ -1622,6 +1641,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 2fb02d72..f4013e55 100644
|
||||||
|
--- a/elf/dl-reloc-static-pie.c
|
||||||
|
+++ b/elf/dl-reloc-static-pie.c
|
||||||
|
@@ -35,21 +35,37 @@ _dl_relocate_static_pie (void)
|
||||||
|
# define RESOLVE_MAP(sym, version, flags) BOOTSTRAP_MAP
|
||||||
|
# include "dynamic-link.h"
|
||||||
|
|
||||||
|
- /* 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);
|
||||||
|
|
||||||
|
# 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 00000000..be2831e9
|
||||||
|
--- /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 00000000..aa1ca0a9
|
||||||
|
--- /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.27.0
|
||||||
|
|
||||||
93
backport-elf-Introduce-_dl_relocate_object_no_relro.patch
Normal file
93
backport-elf-Introduce-_dl_relocate_object_no_relro.patch
Normal file
@ -0,0 +1,93 @@
|
|||||||
|
From f2326c2ec0a0a8db7bc7f4db8cce3002768fc3b6 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed, 6 Nov 2024 10:33:44 +0100
|
||||||
|
Subject: [PATCH] elf: Introduce _dl_relocate_object_no_relro
|
||||||
|
|
||||||
|
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=f2326c2ec0a0a8db7bc7f4db8cce3002768fc3b6
|
||||||
|
Conflict:The context of the modified content is slightly different.
|
||||||
|
|
||||||
|
And make _dl_protect_relro apply RELRO conditionally.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
---
|
||||||
|
elf/dl-reloc.c | 24 ++++++++++++++----------
|
||||||
|
sysdeps/generic/ldsodefs.h | 7 +++++++
|
||||||
|
2 files changed, 21 insertions(+), 10 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/elf/dl-reloc.c b/elf/dl-reloc.c
|
||||||
|
index e13a672a..971a9776 100644
|
||||||
|
--- a/elf/dl-reloc.c
|
||||||
|
+++ b/elf/dl-reloc.c
|
||||||
|
@@ -163,8 +163,8 @@ _dl_nothread_init_static_tls (struct link_map *map)
|
||||||
|
#endif /* !THREAD_GSCOPE_IN_TCB */
|
||||||
|
|
||||||
|
void
|
||||||
|
-_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
- int reloc_mode, int consider_profiling)
|
||||||
|
+_dl_relocate_object_no_relro (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
+ int reloc_mode, int consider_profiling)
|
||||||
|
{
|
||||||
|
struct textrels
|
||||||
|
{
|
||||||
|
@@ -187,9 +187,6 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
# define consider_profiling 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
- if (l->l_relocated)
|
||||||
|
- return;
|
||||||
|
-
|
||||||
|
/* If DT_BIND_NOW is set relocate all references in this object. We
|
||||||
|
do not do this if we are profiling, of course. */
|
||||||
|
// XXX Correct for auditing?
|
||||||
|
@@ -316,17 +313,24 @@ _dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
|
||||||
|
textrels = textrels->next;
|
||||||
|
}
|
||||||
|
-
|
||||||
|
- /* In case we can protect the data now that the relocations are
|
||||||
|
- done, do it. */
|
||||||
|
- if (l->l_relro_size != 0)
|
||||||
|
- _dl_protect_relro (l);
|
||||||
|
}
|
||||||
|
|
||||||
|
+void
|
||||||
|
+_dl_relocate_object (struct link_map *l, struct r_scope_elem *scope[],
|
||||||
|
+ int reloc_mode, int consider_profiling)
|
||||||
|
+{
|
||||||
|
+ if (l->l_relocated)
|
||||||
|
+ return;
|
||||||
|
+ _dl_relocate_object_no_relro (l, scope, reloc_mode, consider_profiling);
|
||||||
|
+ _dl_protect_relro (l);
|
||||||
|
+}
|
||||||
|
|
||||||
|
void
|
||||||
|
_dl_protect_relro (struct link_map *l)
|
||||||
|
{
|
||||||
|
+ if (l->l_relro_size == 0)
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
ElfW(Addr) start = ALIGN_DOWN((l->l_addr
|
||||||
|
+ l->l_relro_addr),
|
||||||
|
GLRO(dl_pagesize));
|
||||||
|
diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
|
||||||
|
index a9fffd66..a4c06c15 100644
|
||||||
|
--- a/sysdeps/generic/ldsodefs.h
|
||||||
|
+++ b/sysdeps/generic/ldsodefs.h
|
||||||
|
@@ -1058,6 +1058,13 @@ extern void _dl_relocate_object (struct link_map *map,
|
||||||
|
int reloc_mode, int consider_profiling)
|
||||||
|
attribute_hidden;
|
||||||
|
|
||||||
|
+/* Perform relocation, but do not apply RELRO. Does not check
|
||||||
|
+ L->relocated. Otherwise the same as _dl_relocate_object. */
|
||||||
|
+void _dl_relocate_object_no_relro (struct link_map *map,
|
||||||
|
+ struct r_scope_elem *scope[],
|
||||||
|
+ int reloc_mode, int consider_profiling)
|
||||||
|
+ attribute_hidden;
|
||||||
|
+
|
||||||
|
/* Protect PT_GNU_RELRO area. */
|
||||||
|
extern void _dl_protect_relro (struct link_map *map) attribute_hidden;
|
||||||
|
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
|
|
||||||
@ -0,0 +1,216 @@
|
|||||||
|
From c1560f3f75c0e892b5522c16f91b4e303f677094 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Florian Weimer <fweimer@redhat.com>
|
||||||
|
Date: Wed, 6 Nov 2024 10:33:44 +0100
|
||||||
|
Subject: [PATCH] elf: Switch to main malloc after final ld.so self-relocation
|
||||||
|
|
||||||
|
Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c1560f3f75c0e892b5522c16f91b4e303f677094
|
||||||
|
Conflict:The context of the modified content is slightly different.
|
||||||
|
|
||||||
|
Before commit ee1ada1bdb8074de6e1bdc956ab19aef7b6a7872
|
||||||
|
("elf: Rework exception handling in the dynamic loader
|
||||||
|
[BZ #25486]"), the previous order called the main calloc
|
||||||
|
to allocate a shadow GOT/PLT array for auditing support.
|
||||||
|
This happened before libc.so.6 ELF constructors were run, so
|
||||||
|
a user malloc could run without libc.so.6 having been
|
||||||
|
initialized fully. One observable effect was that
|
||||||
|
environ was NULL at this point.
|
||||||
|
|
||||||
|
It does not seem to be possible at present to trigger such
|
||||||
|
an allocation, but it seems more robust to delay switching
|
||||||
|
to main malloc after ld.so self-relocation is complete.
|
||||||
|
The elf/tst-rtld-no-malloc-audit test case fails with a
|
||||||
|
2.34-era glibc that does not have this fix.
|
||||||
|
|
||||||
|
Reviewed-by: DJ Delorie <dj@redhat.com>
|
||||||
|
---
|
||||||
|
elf/Makefile | 9 ++++
|
||||||
|
elf/dl-support.c | 3 +-
|
||||||
|
elf/rtld.c | 25 +++++------
|
||||||
|
elf/tst-rtld-no-malloc-audit.c | 1 +
|
||||||
|
elf/tst-rtld-no-malloc-preload.c | 1 +
|
||||||
|
elf/tst-rtld-no-malloc.c | 76 ++++++++++++++++++++++++++++++++
|
||||||
|
6 files changed, 99 insertions(+), 16 deletions(-)
|
||||||
|
create mode 100644 elf/tst-rtld-no-malloc-audit.c
|
||||||
|
create mode 100644 elf/tst-rtld-no-malloc-preload.c
|
||||||
|
create mode 100644 elf/tst-rtld-no-malloc.c
|
||||||
|
|
||||||
|
diff --git a/elf/Makefile b/elf/Makefile
|
||||||
|
index d73f78bd..a178a222 100644
|
||||||
|
--- a/elf/Makefile
|
||||||
|
+++ b/elf/Makefile
|
||||||
|
@@ -407,6 +407,9 @@ tests += \
|
||||||
|
tst-null-argv \
|
||||||
|
tst-relsort1 \
|
||||||
|
tst-ro-dynamic \
|
||||||
|
+ tst-rtld-no-malloc \
|
||||||
|
+ tst-rtld-no-malloc-audit \
|
||||||
|
+ tst-rtld-no-malloc-preload \
|
||||||
|
tst-single_threaded \
|
||||||
|
tst-single_threaded-pthread \
|
||||||
|
tst-sonamemove-dlopen \
|
||||||
|
@@ -2519,3 +2522,9 @@ CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
|
||||||
|
endif
|
||||||
|
|
||||||
|
$(objpfx)tst-rtld-run-static.out: $(objpfx)/ldconfig
|
||||||
|
+
|
||||||
|
+# Reuse an audit module which provides ample debug logging.
|
||||||
|
+tst-rtld-no-malloc-audit-ENV = LD_AUDIT=$(objpfx)tst-auditmod1.so
|
||||||
|
+
|
||||||
|
+# Any shared object should do.
|
||||||
|
+tst-rtld-no-malloc-preload-ENV = LD_PRELOAD=$(objpfx)tst-auditmod1.so
|
||||||
|
diff --git a/elf/dl-support.c b/elf/dl-support.c
|
||||||
|
index f6ab2627..ec75d851 100644
|
||||||
|
--- a/elf/dl-support.c
|
||||||
|
+++ b/elf/dl-support.c
|
||||||
|
@@ -421,8 +421,7 @@ _dl_non_dynamic_init (void)
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup relro on the binary itself. */
|
||||||
|
- if (_dl_main_map.l_relro_size != 0)
|
||||||
|
- _dl_protect_relro (&_dl_main_map);
|
||||||
|
+ _dl_protect_relro (&_dl_main_map);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DL_SYSINFO_IMPLEMENTATION
|
||||||
|
diff --git a/elf/rtld.c b/elf/rtld.c
|
||||||
|
index 5a82c1ab..ebfe6713 100644
|
||||||
|
--- a/elf/rtld.c
|
||||||
|
+++ b/elf/rtld.c
|
||||||
|
@@ -2505,27 +2505,24 @@ dl_main (const ElfW(Phdr) *phdr,
|
||||||
|
|
||||||
|
if (! prelinked && rtld_multiple_ref)
|
||||||
|
{
|
||||||
|
- /* There was an explicit ref to the dynamic linker as a shared lib.
|
||||||
|
- Re-relocate ourselves with user-controlled symbol definitions.
|
||||||
|
-
|
||||||
|
- We must do this after TLS initialization in case after this
|
||||||
|
- re-relocation, we might call a user-supplied function
|
||||||
|
- (e.g. calloc from _dl_relocate_object) that uses TLS data. */
|
||||||
|
-
|
||||||
|
- /* The malloc implementation has been relocated, so resolving
|
||||||
|
- its symbols (and potentially calling IFUNC resolvers) is safe
|
||||||
|
- at this point. */
|
||||||
|
- __rtld_malloc_init_real (main_map);
|
||||||
|
|
||||||
|
/* Likewise for the locking implementation. */
|
||||||
|
__rtld_mutex_init ();
|
||||||
|
|
||||||
|
+ /* Re-relocate ourselves with user-controlled symbol definitions. */
|
||||||
|
+
|
||||||
|
RTLD_TIMING_VAR (start);
|
||||||
|
rtld_timer_start (&start);
|
||||||
|
|
||||||
|
- /* Mark the link map as not yet relocated again. */
|
||||||
|
- GL(dl_rtld_map).l_relocated = 0;
|
||||||
|
- _dl_relocate_object (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
|
||||||
|
+ _dl_relocate_object_no_relro (&GL(dl_rtld_map), main_map->l_scope, 0, 0);
|
||||||
|
+
|
||||||
|
+ /* The malloc implementation has been relocated, so resolving
|
||||||
|
+ its symbols (and potentially calling IFUNC resolvers) is safe
|
||||||
|
+ at this point. */
|
||||||
|
+ __rtld_malloc_init_real (main_map);
|
||||||
|
+
|
||||||
|
+ if (GL(dl_rtld_map).l_relro_size != 0)
|
||||||
|
+ _dl_protect_relro (&GL(dl_rtld_map));
|
||||||
|
|
||||||
|
rtld_timer_accum (&relocate_time, start);
|
||||||
|
}
|
||||||
|
diff --git a/elf/tst-rtld-no-malloc-audit.c b/elf/tst-rtld-no-malloc-audit.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..a028377a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-rtld-no-malloc-audit.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-rtld-no-malloc.c"
|
||||||
|
diff --git a/elf/tst-rtld-no-malloc-preload.c b/elf/tst-rtld-no-malloc-preload.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..a028377a
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-rtld-no-malloc-preload.c
|
||||||
|
@@ -0,0 +1 @@
|
||||||
|
+#include "tst-rtld-no-malloc.c"
|
||||||
|
diff --git a/elf/tst-rtld-no-malloc.c b/elf/tst-rtld-no-malloc.c
|
||||||
|
new file mode 100644
|
||||||
|
index 00000000..5f24d4bd
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/elf/tst-rtld-no-malloc.c
|
||||||
|
@@ -0,0 +1,76 @@
|
||||||
|
+/* Test that program loading does not call malloc.
|
||||||
|
+ 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 <string.h>
|
||||||
|
+#include <unistd.h>
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+print (const char *s)
|
||||||
|
+{
|
||||||
|
+ const char *end = s + strlen (s);
|
||||||
|
+ while (s < end)
|
||||||
|
+ {
|
||||||
|
+ ssize_t ret = write (STDOUT_FILENO, s, end - s);
|
||||||
|
+ if (ret <= 0)
|
||||||
|
+ _exit (2);
|
||||||
|
+ s += ret;
|
||||||
|
+ }
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void __attribute__ ((noreturn))
|
||||||
|
+unexpected_call (const char *function)
|
||||||
|
+{
|
||||||
|
+ print ("error: unexpected call to ");
|
||||||
|
+ print (function);
|
||||||
|
+ print ("\n");
|
||||||
|
+ _exit (1);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+/* These are the malloc functions implement in elf/dl-minimal.c. */
|
||||||
|
+
|
||||||
|
+void
|
||||||
|
+free (void *ignored)
|
||||||
|
+{
|
||||||
|
+ unexpected_call ("free");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+calloc (size_t ignored1, size_t ignored2)
|
||||||
|
+{
|
||||||
|
+ unexpected_call ("calloc");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+malloc (size_t ignored)
|
||||||
|
+{
|
||||||
|
+ unexpected_call ("malloc");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+void *
|
||||||
|
+realloc (void *ignored1, size_t ignored2)
|
||||||
|
+{
|
||||||
|
+ unexpected_call ("realloc");
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+int
|
||||||
|
+main (void)
|
||||||
|
+{
|
||||||
|
+ /* Do not use the test wrapper, to avoid spurious malloc calls from it. */
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
--
|
||||||
|
2.43.0
|
||||||
|
|
||||||
13
glibc.spec
13
glibc.spec
@ -71,7 +71,7 @@
|
|||||||
##############################################################################
|
##############################################################################
|
||||||
Name: glibc
|
Name: glibc
|
||||||
Version: 2.34
|
Version: 2.34
|
||||||
Release: 162
|
Release: 163
|
||||||
Summary: The GNU libc libraries
|
Summary: The GNU libc libraries
|
||||||
License: %{all_license}
|
License: %{all_license}
|
||||||
URL: http://www.gnu.org/software/glibc/
|
URL: http://www.gnu.org/software/glibc/
|
||||||
@ -313,6 +313,9 @@ Patch221: backport-resolv-track-single-request-fallback-flags.patch
|
|||||||
Patch222: backport-resolv-allow-short-error-response-to-match-any-query.patch
|
Patch222: backport-resolv-allow-short-error-response-to-match-any-query.patch
|
||||||
Patch223: backport-elf-avoid-jumping-over-a-needed-declaration.patch
|
Patch223: backport-elf-avoid-jumping-over-a-needed-declaration.patch
|
||||||
Patch224: backport-elf-Move-__rtld_malloc_init_stubs-call-into-_dl_star.patch
|
Patch224: backport-elf-Move-__rtld_malloc_init_stubs-call-into-_dl_star.patch
|
||||||
|
Patch225: backport-elf-Handle-static-PIE-with-non-zero-load-address-BZ-.patch
|
||||||
|
Patch226: backport-elf-Introduce-_dl_relocate_object_no_relro.patch
|
||||||
|
Patch227: backport-elf-Switch-to-main-malloc-after-final-ld.so-self-rel.patch
|
||||||
|
|
||||||
Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
|
Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
|
||||||
Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch
|
Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch
|
||||||
@ -1543,6 +1546,14 @@ fi
|
|||||||
%endif
|
%endif
|
||||||
|
|
||||||
%changelog
|
%changelog
|
||||||
|
* Fri Dec 06 2024 shixuantong <shixuantong1@huawei.com> - 2.34-163
|
||||||
|
- Type:bugfix
|
||||||
|
- CVE:NA
|
||||||
|
- SUG:NA
|
||||||
|
- DESC:elf: Handle static PIE with non-zero load address
|
||||||
|
elf: Introduce _dl_relocate_object_no_relro
|
||||||
|
elf: Switch to main malloc after final ld.so self-relocation
|
||||||
|
|
||||||
* Fri Nov 29 2024 shixuantong <shixuantong1@huawei.com> - 2.34-162
|
* Fri Nov 29 2024 shixuantong <shixuantong1@huawei.com> - 2.34-162
|
||||||
- Type:bugfix
|
- Type:bugfix
|
||||||
- CVE:NA
|
- CVE:NA
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user