aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Belousov <kib@FreeBSD.org>2021-10-11 22:35:56 +0000
committerKonstantin Belousov <kib@FreeBSD.org>2021-10-21 00:09:14 +0000
commit2c7a6dad4de17c357eb91c723bad860c6512a598 (patch)
treea4a76cbf2bfceb10dcabca836da349f849521e9b
parentca8c576d10e22830d0c7ac865af21aad9ae44181 (diff)
downloadsrc-2c7a6dad4de17c357eb91c723bad860c6512a598.tar.gz
src-2c7a6dad4de17c357eb91c723bad860c6512a598.zip
ldd: do not use dlopen(RTLD_TRACE) for dso when format is specified
Problem is that rtld cannot reliably access updated environment. This was made more obvious by bfd4c875a10560aaa2. The application environment can be in arbitrary state and place, system components can observe it only during execve(2), or in case of rtld, right after execve, when environment is still at know location and format. Instead spawn ld-elf.so.1 in direct exec mode which can correctly read all inherited updates to the environment. PR: 259069 Reviewed by: arichardson, jhb Sponsored by: The FreeBSD Foundation MFC after: 1 week Differential revision: https://reviews.freebsd.org/D32464
-rw-r--r--usr.bin/ldd/Makefile1
-rw-r--r--usr.bin/ldd/ldd.c12
2 files changed, 12 insertions, 1 deletions
diff --git a/usr.bin/ldd/Makefile b/usr.bin/ldd/Makefile
index 78e551d80a33..1a671bc9f402 100644
--- a/usr.bin/ldd/Makefile
+++ b/usr.bin/ldd/Makefile
@@ -3,6 +3,7 @@
PROG?= ldd
SRCS= ldd.c
+CFLAGS+= -I${SRCTOP}/libexec/rtld-elf
LIBADD= elf
.include <bsd.prog.mk>
diff --git a/usr.bin/ldd/ldd.c b/usr.bin/ldd/ldd.c
index ee3f2070598d..492e29dff211 100644
--- a/usr.bin/ldd/ldd.c
+++ b/usr.bin/ldd/ldd.c
@@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$");
#include <fcntl.h>
#include <gelf.h>
#include <libelf.h>
+#include <rtld_paths.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
@@ -134,6 +135,7 @@ int
main(int argc, char *argv[])
{
char *fmt1, *fmt2;
+ const char *rtld;
int aflag, c, fd, rval, status, is_shlib, rv, type;
aflag = 0;
@@ -234,9 +236,17 @@ main(int argc, char *argv[])
if (is_shlib == 0) {
execl(*argv, *argv, (char *)NULL);
warn("%s", *argv);
- } else {
+ } else if (fmt1 == NULL && fmt2 == NULL) {
dlopen(*argv, RTLD_TRACE);
warnx("%s: %s", *argv, dlerror());
+ } else {
+ rtld = _PATH_RTLD;
+#if __ELF_WORD_SIZE > 32 && defined(ELF32_SUPPORTED)
+ if (type == TYPE_ELF32)
+ rtld = _COMPAT32_PATH_RTLD;
+#endif
+ execl(rtld, rtld, "-d", "--",
+ *argv, (char *)NULL);
}
_exit(1);
}