git: 2c7a6dad4de1 - main - ldd: do not use dlopen(RTLD_TRACE) for dso when format is specified

From: Konstantin Belousov <kib_at_FreeBSD.org>
Date: Thu, 21 Oct 2021 00:10:56 UTC
The branch main has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=2c7a6dad4de17c357eb91c723bad860c6512a598

commit 2c7a6dad4de17c357eb91c723bad860c6512a598
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-10-11 22:35:56 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-10-21 00:09:14 +0000

    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
---
 usr.bin/ldd/Makefile |  1 +
 usr.bin/ldd/ldd.c    | 12 +++++++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

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);
 		}