git: 708106fb8086 - stable/14 - rtld: implement _dl_iterate_phdr_locked
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 27 Nov 2024 01:16:19 UTC
The branch stable/14 has been updated by kevans:
URL: https://cgit.FreeBSD.org/src/commit/?id=708106fb8086e85afa4a9aed3872a329c702797b
commit 708106fb8086e85afa4a9aed3872a329c702797b
Author: Kyle Evans <kevans@FreeBSD.org>
AuthorDate: 2024-11-14 01:33:59 +0000
Commit: Kyle Evans <kevans@FreeBSD.org>
CommitDate: 2024-11-27 01:15:56 +0000
rtld: implement _dl_iterate_phdr_locked
Some sanitizers need to be able to use dl_iterate_phdr() after stopping
the rest of the process, but it's very hard to do so reliably as a
non-participant in the main logic of the program.
Introduce _dl_iterate_phdr_locked to bypass the locking that's normally
required for dl_iterate_phdr() and slap some scary warning on it. It
will remain undocumented and probably shouldn't be used for anything
else.
Reviewed by: kib
(cherry picked from commit 1426fd6cff0603f0ee275b99f2ba35dc36f3d0c2)
---
lib/libc/gen/Symbol.map | 1 +
lib/libc/gen/dlfcn.c | 24 ++++++++++++++++++++----
libexec/rtld-elf/Symbol.map | 1 +
libexec/rtld-elf/rtld.c | 24 ++++++++++++++++++++++++
4 files changed, 46 insertions(+), 4 deletions(-)
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
index 8e4a26df8f08..5178ce56da33 100644
--- a/lib/libc/gen/Symbol.map
+++ b/lib/libc/gen/Symbol.map
@@ -469,6 +469,7 @@ FBSDprivate_1.0 {
/* needed by thread libraries */
__thr_jtable;
+ _dl_iterate_phdr_locked;
_pthread_atfork;
_pthread_attr_destroy;
_pthread_attr_getdetachstate;
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
index b30cb82e5e43..b814fdc845c4 100644
--- a/lib/libc/gen/dlfcn.c
+++ b/lib/libc/gen/dlfcn.c
@@ -203,9 +203,10 @@ dl_init_phdr_info(void)
}
#endif
-#pragma weak dl_iterate_phdr
+#pragma weak _dl_iterate_phdr_locked
int
-dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *) __unused,
+_dl_iterate_phdr_locked(
+ int (*callback)(struct dl_phdr_info *, size_t, void *) __unused,
void *data __unused)
{
#if defined IN_LIBDL
@@ -227,14 +228,29 @@ dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *) __unused,
_once(&dl_phdr_info_once, dl_init_phdr_info);
ti.ti_module = 1;
ti.ti_offset = 0;
- mutex_lock(&dl_phdr_info_lock);
phdr_info.dlpi_tls_data = __tls_get_addr(&ti);
ret = callback(&phdr_info, sizeof(phdr_info), data);
- mutex_unlock(&dl_phdr_info_lock);
return (ret);
#endif
}
+#pragma weak dl_iterate_phdr
+int
+dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *) __unused,
+ void *data __unused)
+{
+ int error;
+
+#if !defined(IN_LIBDL) && !defined(PIC)
+ mutex_lock(&dl_phdr_info_lock);
+#endif
+ error = _dl_iterate_phdr_locked(callback, data);
+#if !defined(IN_LIBDL) && !defined(PIC)
+ mutex_unlock(&dl_phdr_info_lock);
+#endif
+ return (error);
+}
+
#pragma weak fdlopen
void *
fdlopen(int fd __unused, int mode __unused)
diff --git a/libexec/rtld-elf/Symbol.map b/libexec/rtld-elf/Symbol.map
index 3cdbb30d04a0..9e9e702a1261 100644
--- a/libexec/rtld-elf/Symbol.map
+++ b/libexec/rtld-elf/Symbol.map
@@ -27,6 +27,7 @@ FBSD_1.8 {
};
FBSDprivate_1.0 {
+ _dl_iterate_phdr_locked;
_rtld_thread_init;
_rtld_allocate_tls;
_rtld_free_tls;
diff --git a/libexec/rtld-elf/rtld.c b/libexec/rtld-elf/rtld.c
index 32d0b879c5bc..e1813217a854 100644
--- a/libexec/rtld-elf/rtld.c
+++ b/libexec/rtld-elf/rtld.c
@@ -253,6 +253,7 @@ int dladdr(const void *, Dl_info *) __exported;
void dllockinit(void *, void *(*)(void *), void (*)(void *), void (*)(void *),
void (*)(void *), void (*)(void *), void (*)(void *)) __exported;
int dlinfo(void *, int , void *) __exported;
+int _dl_iterate_phdr_locked(__dl_iterate_hdr_callback, void *) __exported;
int dl_iterate_phdr(__dl_iterate_hdr_callback, void *) __exported;
int _rtld_addr_phdr(const void *, struct dl_phdr_info *) __exported;
int _rtld_get_stack_prot(void) __exported;
@@ -4208,6 +4209,29 @@ rtld_fill_dl_phdr_info(const Obj_Entry *obj, struct dl_phdr_info *phdr_info)
phdr_info->dlpi_subs = obj_loads - obj_count;
}
+/*
+ * It's completely UB to actually use this, so extreme caution is advised. It's
+ * probably not what you want.
+ */
+int
+_dl_iterate_phdr_locked(__dl_iterate_hdr_callback callback, void *param)
+{
+ struct dl_phdr_info phdr_info;
+ Obj_Entry *obj;
+ int error;
+
+ for (obj = globallist_curr(TAILQ_FIRST(&obj_list)); obj != NULL;
+ obj = globallist_next(obj)) {
+ rtld_fill_dl_phdr_info(obj, &phdr_info);
+ error = callback(&phdr_info, sizeof(phdr_info), param);
+ if (error != 0)
+ return (error);
+ }
+
+ rtld_fill_dl_phdr_info(&obj_rtld, &phdr_info);
+ return (callback(&phdr_info, sizeof(phdr_info), param));
+}
+
int
dl_iterate_phdr(__dl_iterate_hdr_callback callback, void *param)
{