diff options
author | Florian Weimer <fweimer@redhat.com> | 2025-01-07 09:18:07 +0100 |
---|---|---|
committer | Florian Weimer <fweimer@redhat.com> | 2025-01-07 09:19:01 +0100 |
commit | 706209867f1ba89c458033408d419e92d8055f58 (patch) | |
tree | 786259a1ec9b4d8c8de81b08da4b0e5d3b01ba8c /sysdeps/unix/sysv | |
parent | a257f201dd557aa82c7efb7528277afe675c0468 (diff) | |
download | glibc-706209867f1ba89c458033408d419e92d8055f58.zip glibc-706209867f1ba89c458033408d419e92d8055f58.tar.gz glibc-706209867f1ba89c458033408d419e92d8055f58.tar.bz2 |
elf: Second ld.so relocation only if libc.so has been loaded
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 <adhemerval.zanella@linaro.org>
Diffstat (limited to 'sysdeps/unix/sysv')
-rw-r--r-- | sysdeps/unix/sysv/linux/Makefile | 8 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/arm/Makefile | 3 | ||||
-rw-r--r-- | sysdeps/unix/sysv/linux/tst-nolink-libc.c | 25 |
3 files changed, 36 insertions, 0 deletions
diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile index eb9c697..4e7044f 100644 --- a/sysdeps/unix/sysv/linux/Makefile +++ b/sysdeps/unix/sysv/linux/Makefile @@ -652,7 +652,15 @@ install-bin += \ # install-bin $(objpfx)pldd: $(objpfx)xmalloc.o + +test-internal-extras += tst-nolink-libc +ifeq ($(run-built-tests),yes) +tests-special += \ + $(objpfx)tst-nolink-libc-1.out \ + $(objpfx)tst-nolink-libc-2.out \ + # tests-special endif +endif # $(subdir) == elf ifeq ($(subdir),rt) CFLAGS-mq_send.c += -fexceptions diff --git a/sysdeps/unix/sysv/linux/arm/Makefile b/sysdeps/unix/sysv/linux/arm/Makefile index a73c897..e73ce4f 100644 --- a/sysdeps/unix/sysv/linux/arm/Makefile +++ b/sysdeps/unix/sysv/linux/arm/Makefile @@ -1,5 +1,8 @@ ifeq ($(subdir),elf) sysdep-rtld-routines += aeabi_read_tp libc-do-syscall +# The test uses INTERNAL_SYSCALL_CALL. In thumb mode, this uses +# an undefined reference to __libc_do_syscall. +CFLAGS-tst-nolink-libc.c += -marm endif ifeq ($(subdir),misc) diff --git a/sysdeps/unix/sysv/linux/tst-nolink-libc.c b/sysdeps/unix/sysv/linux/tst-nolink-libc.c new file mode 100644 index 0000000..817f377 --- /dev/null +++ b/sysdeps/unix/sysv/linux/tst-nolink-libc.c @@ -0,0 +1,25 @@ +/* Test program not linked against libc.so and not using any glibc functions. + 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 <sysdep.h> + +void +_start (void) +{ + INTERNAL_SYSCALL_CALL (exit_group, 0); +} |