mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-18 15:30:21 +00:00
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 Differential Revision: https://reviews.freebsd.org/D47558
This commit is contained in:
parent
4b202f4faf
commit
1426fd6cff
@ -464,6 +464,7 @@ FBSDprivate_1.0 {
|
||||
/* needed by thread libraries */
|
||||
__thr_jtable;
|
||||
|
||||
_dl_iterate_phdr_locked;
|
||||
_pthread_atfork;
|
||||
_pthread_attr_destroy;
|
||||
_pthread_attr_getdetachstate;
|
||||
|
@ -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)
|
||||
|
@ -27,6 +27,7 @@ FBSD_1.8 {
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
_dl_iterate_phdr_locked;
|
||||
_rtld_thread_init;
|
||||
_rtld_allocate_tls;
|
||||
_rtld_free_tls;
|
||||
|
@ -252,6 +252,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;
|
||||
@ -4201,6 +4202,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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user