From 706209867f1ba89c458033408d419e92d8055f58 Mon Sep 17 00:00:00 2001 From: Florian Weimer Date: Tue, 7 Jan 2025 09:18:07 +0100 Subject: elf: Second ld.so relocation only if libc.so has been loaded MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit 8f8dd904c4a2207699bb666f30acceb5209c8d3f (“elf: rtld_multiple_ref is always true”) removed some code that happened to enable compatibility with programs that do not link against libc.so. Such programs cannot call dlopen or any dynamic linker functions (except __tls_get_addr), so this is not really useful. Still ld.so should not crash with a null-pointer dereference or undefined symbol reference in these cases. In the main relocation loop, call _dl_relocate_object unconditionally because it already checks if the object has been relocated. If libc.so was loaded, self-relocate ld.so against it and call __rtld_mutex_init and __rtld_malloc_init_real to activate the full implementations. Those are available only if libc.so is there, so skip these initialization steps if libc.so is absent. Without libc.so, the global scope can be completely empty. This can cause ld.so self-relocation to fail because if it uses symbol-based relocations, which is why the second ld.so self-relocation is not performed if libc.so is missing. The previous concern regarding GOT updates through self-relocation no longer applies because function pointers are updated explicitly through __rtld_mutex_init and __rtld_malloc_init_real, and not through relocation. However, the second ld.so self-relocation is still delayed, in case there are other symbols being used. Fixes commit 8f8dd904c4a2207699bb666f30acceb5209c8d3f (“elf: rtld_multiple_ref is always true”). Reviewed-by: Adhemerval Zanella --- elf/Makefile | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'elf/Makefile') diff --git a/elf/Makefile b/elf/Makefile index e3db643..8f11c04 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -3372,3 +3372,20 @@ endef $(foreach m,$(modules-semantic-interposition),\ $(eval $(call enable-semantic-interposition,$(m)))) endif + +# These rules link and run the special elf/tst-nolink-libc-* tests if +# a port adds them to the tests variables. Neither test variant is +# linked against libc.so, but tst-nolink-libc-1 is linked against +# ld.so. The test is always run directly, not under the dynamic +# linker. +CFLAGS-tst-nolink-libc.c += $(no-stack-protector) +$(objpfx)tst-nolink-libc-1: $(objpfx)tst-nolink-libc.o $(objpfx)ld.so + $(LINK.o) -nostdlib -nostartfiles -o $@ $< \ + -Wl,--dynamic-linker=$(objpfx)ld.so,--no-as-needed $(objpfx)ld.so +$(objpfx)tst-nolink-libc-1.out: $(objpfx)tst-nolink-libc-1 $(objpfx)ld.so + $< > $@ 2>&1; $(evaluate-test) +$(objpfx)tst-nolink-libc-2: $(objpfx)tst-nolink-libc.o + $(LINK.o) -nostdlib -nostartfiles -o $@ $< \ + -Wl,--dynamic-linker=$(objpfx)ld.so +$(objpfx)tst-nolink-libc-2.out: $(objpfx)tst-nolink-libc-2 $(objpfx)ld.so + $< > $@ 2>&1; $(evaluate-test) -- cgit v1.1