You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
224 lines
8.4 KiB
224 lines
8.4 KiB
commit 78ca44da0160a0b442f0ca1f253e3360f044b2ec |
|
Author: Florian Weimer <fweimer@redhat.com> |
|
Date: Mon Nov 27 11:28:13 2023 +0100 |
|
|
|
elf: Relocate libc.so early during startup and dlmopen (bug 31083) |
|
|
|
This makes it more likely that objects without dependencies can |
|
use IFUNC resolvers in libc.so. |
|
|
|
Reviewed-by: Carlos O'Donell <carlos@redhat.com> |
|
|
|
Conflicts: |
|
elf/Makefile |
|
(test backport differences) |
|
elf/rtld.c |
|
(prelink support was removed upstream) |
|
|
|
diff --git a/elf/Makefile b/elf/Makefile |
|
index 8e1f91bcd917fd4e..7b7c6c171ce23247 100644 |
|
--- a/elf/Makefile |
|
+++ b/elf/Makefile |
|
@@ -419,6 +419,8 @@ tests += \ |
|
tst-nodelete2 \ |
|
tst-nodelete-dlclose \ |
|
tst-nodelete-opened \ |
|
+ tst-nodeps1 \ |
|
+ tst-nodeps2 \ |
|
tst-noload \ |
|
tst-null-argv \ |
|
tst-relsort1 \ |
|
@@ -777,6 +779,8 @@ modules-names = \ |
|
tst-nodelete-dlclose-dso \ |
|
tst-nodelete-dlclose-plugin \ |
|
tst-nodelete-opened-lib \ |
|
+ tst-nodeps1-mod \ |
|
+ tst-nodeps2-mod \ |
|
tst-null-argv-lib \ |
|
tst-relsort1mod1 \ |
|
tst-relsort1mod2 \ |
|
@@ -931,8 +935,15 @@ extra-test-objs += $(addsuffix .os,$(strip $(modules-names))) |
|
|
|
# filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special |
|
# rules. |
|
-modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod \ |
|
- tst-audit24bmod1 tst-audit24bmod2 |
|
+modules-names-nobuild += \ |
|
+ filtmod1 \ |
|
+ tst-audit24bmod1 \ |
|
+ tst-audit24bmod2 \ |
|
+ tst-big-note-lib \ |
|
+ tst-nodeps1-mod \ |
|
+ tst-nodeps2-mod \ |
|
+ tst-ro-dynamic-mod \ |
|
+ # modules-names-nobuild |
|
|
|
tests += $(tests-static) |
|
|
|
@@ -2684,3 +2695,18 @@ LDFLAGS-tst-dlclose-lazy-mod1.so = -Wl,-z,lazy,--no-as-needed |
|
$(objpfx)tst-dlclose-lazy-mod1.so: $(objpfx)tst-dlclose-lazy-mod2.so |
|
$(objpfx)tst-dlclose-lazy.out: \ |
|
$(objpfx)tst-dlclose-lazy-mod1.so $(objpfx)tst-dlclose-lazy-mod2.so |
|
+ |
|
+# The object tst-nodeps1-mod.so has no explicit dependencies on libc.so. |
|
+$(objpfx)tst-nodeps1-mod.so: $(objpfx)tst-nodeps1-mod.os |
|
+ $(LINK.o) -nostartfiles -nostdlib -shared -o $@ $^ |
|
+tst-nodeps1.so-no-z-defs = yes |
|
+# Link libc.so before the test module with the IFUNC resolver reference. |
|
+LDFLAGS-tst-nodeps1 = $(common-objpfx)libc.so $(objpfx)tst-nodeps1-mod.so |
|
+$(objpfx)tst-nodeps1: $(objpfx)tst-nodeps1-mod.so |
|
+# Reuse the tst-nodeps1 module. Link libc.so before the test module |
|
+# with the IFUNC resolver reference. |
|
+$(objpfx)tst-nodeps2-mod.so: $(common-objpfx)libc.so \ |
|
+ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.os |
|
+ $(LINK.o) -Wl,--no-as-needed -nostartfiles -nostdlib -shared -o $@ $^ |
|
+$(objpfx)tst-nodeps2.out: \ |
|
+ $(objpfx)tst-nodeps1-mod.so $(objpfx)tst-nodeps2-mod.so |
|
diff --git a/elf/dl-open.c b/elf/dl-open.c |
|
index cf3baccccb461878..4b58bdd668634130 100644 |
|
--- a/elf/dl-open.c |
|
+++ b/elf/dl-open.c |
|
@@ -705,6 +705,17 @@ dl_open_worker_begin (void *a) |
|
them. However, such relocation dependencies in IFUNC resolvers |
|
are undefined anyway, so this is not a problem. */ |
|
|
|
+ /* Ensure that libc is relocated first. This helps with the |
|
+ execution of IFUNC resolvers in libc, and matters only to newly |
|
+ created dlmopen namespaces. Do not do this for static dlopen |
|
+ because libc has relocations against ld.so, which may not have |
|
+ been relocated at this point. */ |
|
+#ifdef SHARED |
|
+ if (GL(dl_ns)[args->nsid].libc_map != NULL) |
|
+ _dl_open_relocate_one_object (args, r, GL(dl_ns)[args->nsid].libc_map, |
|
+ reloc_mode, &relocation_in_progress); |
|
+#endif |
|
+ |
|
for (unsigned int i = last; i-- > first; ) |
|
_dl_open_relocate_one_object (args, r, new->l_initfini[i], reloc_mode, |
|
&relocation_in_progress); |
|
diff --git a/elf/rtld.c b/elf/rtld.c |
|
index 9de53ccaed420a57..a638d14e77745baa 100644 |
|
--- a/elf/rtld.c |
|
+++ b/elf/rtld.c |
|
@@ -2421,11 +2421,17 @@ dl_main (const ElfW(Phdr) *phdr, |
|
objects. We do not re-relocate the dynamic linker itself in this |
|
loop because that could result in the GOT entries for functions we |
|
call being changed, and that would break us. It is safe to relocate |
|
- the dynamic linker out of order because it has no copy relocs (we |
|
- know that because it is self-contained). */ |
|
+ the dynamic linker out of order because it has no copy relocations. |
|
+ Likewise for libc, which is relocated early to ensure that IFUNC |
|
+ resolvers in libc work. */ |
|
|
|
int consider_profiling = GLRO(dl_profile) != NULL; |
|
|
|
+ if (GL(dl_ns)[LM_ID_BASE].libc_map != NULL) |
|
+ _dl_relocate_object (GL(dl_ns)[LM_ID_BASE].libc_map, |
|
+ GL(dl_ns)[LM_ID_BASE].libc_map->l_scope, |
|
+ GLRO(dl_lazy) ? RTLD_LAZY : 0, consider_profiling); |
|
+ |
|
/* If we are profiling we also must do lazy reloaction. */ |
|
GLRO(dl_lazy) |= consider_profiling; |
|
|
|
diff --git a/elf/tst-nodeps1-mod.c b/elf/tst-nodeps1-mod.c |
|
new file mode 100644 |
|
index 0000000000000000..45c8e3c631251a89 |
|
--- /dev/null |
|
+++ b/elf/tst-nodeps1-mod.c |
|
@@ -0,0 +1,25 @@ |
|
+/* Test module with no libc.so dependency and string function references. |
|
+ Copyright (C) 2023 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> |
|
+ |
|
+/* Some references to libc symbols which are likely to have IFUNC |
|
+ resolvers. If they do not, this module does not exercise bug 31083. */ |
|
+void *memcpy_pointer = memcpy; |
|
+void *memmove_pointer = memmove; |
|
+void *memset_pointer = memset; |
|
diff --git a/elf/tst-nodeps1.c b/elf/tst-nodeps1.c |
|
new file mode 100644 |
|
index 0000000000000000..1a8bde36cdb71446 |
|
--- /dev/null |
|
+++ b/elf/tst-nodeps1.c |
|
@@ -0,0 +1,23 @@ |
|
+/* Test initially loaded module with implicit libc.so dependency (bug 31083). |
|
+ Copyright (C) 2023 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/>. */ |
|
+ |
|
+/* Testing happens before main. */ |
|
+int |
|
+main (void) |
|
+{ |
|
+} |
|
diff --git a/elf/tst-nodeps2-mod.c b/elf/tst-nodeps2-mod.c |
|
new file mode 100644 |
|
index 0000000000000000..4913feee9b56e0e1 |
|
--- /dev/null |
|
+++ b/elf/tst-nodeps2-mod.c |
|
@@ -0,0 +1 @@ |
|
+/* Empty test module which depends on tst-nodeps1-mod.so. */ |
|
diff --git a/elf/tst-nodeps2.c b/elf/tst-nodeps2.c |
|
new file mode 100644 |
|
index 0000000000000000..0bdc8eeb8cba3a99 |
|
--- /dev/null |
|
+++ b/elf/tst-nodeps2.c |
|
@@ -0,0 +1,29 @@ |
|
+/* Test dlmopen with implicit libc.so dependency (bug 31083). |
|
+ Copyright (C) 2023 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 <support/xdlfcn.h> |
|
+ |
|
+static int |
|
+do_test (void) |
|
+{ |
|
+ void *handle = xdlmopen (LM_ID_NEWLM, "tst-nodeps2-mod.so", RTLD_NOW); |
|
+ xdlclose (handle); |
|
+ return 0; |
|
+} |
|
+ |
|
+#include <support/test-driver.c>
|
|
|