If libthr.so is dlopened without RTLD_GLOBAL flag, the libthr symbols
do not participate in the global symbols namespace, but rtld locks are still replaced and functions are interposed. In particular, __pthread_map_stacks_exec is resolved to the libc version. If a library is loaded later, which requires adjustment of the stack protection mode, rtld calls into libc __pthread_map_stacks_exec due to the symbols scope. The libc version might recurse into binder and recursively acquire rtld bind lock, causing the hang. Make libc __pthread_map_stacks_exec() interposed, which synchronizes rtld locks and version of the stack exec hook when libthr loaded, regardless of the symbol scope control or symbol resolution order. The __pthread_map_stacks_exec() symbol is removed from the private version in libthr since libc symbol now operates correctly in presence of libthr. Reported and tested by: markj Sponsored by: The FreeBSD Foundation MFC after: 2 weeks
This commit is contained in:
parent
42bcd86bfb
commit
42e09be9c2
lib
libc
libthr
@ -32,6 +32,7 @@
|
||||
#include <sys/sysctl.h>
|
||||
#include <link.h>
|
||||
#include <stddef.h>
|
||||
#include "libc_private.h"
|
||||
|
||||
int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
|
||||
void __pthread_map_stacks_exec(void);
|
||||
@ -54,9 +55,8 @@ __elf_phdr_match_addr(struct dl_phdr_info *phdr_info, void *addr)
|
||||
return (i != phdr_info->dlpi_phnum);
|
||||
}
|
||||
|
||||
#pragma weak __pthread_map_stacks_exec
|
||||
void
|
||||
__pthread_map_stacks_exec(void)
|
||||
__libc_map_stacks_exec(void)
|
||||
{
|
||||
int mib[2];
|
||||
struct rlimit rlim;
|
||||
@ -75,3 +75,10 @@ __pthread_map_stacks_exec(void)
|
||||
rlim.rlim_cur, _rtld_get_stack_prot());
|
||||
}
|
||||
|
||||
#pragma weak __pthread_map_stacks_exec
|
||||
void
|
||||
__pthread_map_stacks_exec(void)
|
||||
{
|
||||
|
||||
((void (*)(void))__libc_interposing[INTERPOS_map_stacks_exec])();
|
||||
}
|
||||
|
@ -224,6 +224,7 @@ enum {
|
||||
INTERPOS_kevent,
|
||||
INTERPOS_wait6,
|
||||
INTERPOS_ppoll,
|
||||
INTERPOS_map_stacks_exec,
|
||||
INTERPOS_MAX
|
||||
};
|
||||
|
||||
@ -381,6 +382,7 @@ int _elf_aux_info(int aux, void *buf, int buflen);
|
||||
struct dl_phdr_info;
|
||||
int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
|
||||
void __init_elf_aux_vector(void);
|
||||
void __libc_map_stacks_exec();
|
||||
|
||||
void _pthread_cancel_enter(int);
|
||||
void _pthread_cancel_leave(int);
|
||||
|
@ -78,6 +78,7 @@ interpos_func_t __libc_interposing[INTERPOS_MAX] = {
|
||||
SLOT(kevent, __sys_kevent),
|
||||
SLOT(wait6, __sys_wait6),
|
||||
SLOT(ppoll, __sys_ppoll),
|
||||
SLOT(map_stacks_exec, __libc_map_stacks_exec),
|
||||
};
|
||||
#undef SLOT
|
||||
|
||||
|
@ -295,8 +295,6 @@ FBSDprivate_1.0 {
|
||||
_thread_size_key;
|
||||
_thread_state_running;
|
||||
_thread_state_zoombie;
|
||||
|
||||
__pthread_map_stacks_exec;
|
||||
};
|
||||
|
||||
FBSD_1.1 {
|
||||
|
@ -927,6 +927,8 @@ int __thr_sigwait(const sigset_t *set, int *sig);
|
||||
int __thr_sigwaitinfo(const sigset_t *set, siginfo_t *info);
|
||||
int __thr_swapcontext(ucontext_t *oucp, const ucontext_t *ucp);
|
||||
|
||||
void __thr_map_stacks_exec(void);
|
||||
|
||||
struct _spinlock;
|
||||
void __thr_spinunlock(struct _spinlock *lck);
|
||||
void __thr_spinlock(struct _spinlock *lck);
|
||||
|
@ -161,9 +161,8 @@ singlethread_map_stacks_exec(void)
|
||||
rlim.rlim_cur, _rtld_get_stack_prot());
|
||||
}
|
||||
|
||||
void __pthread_map_stacks_exec(void);
|
||||
void
|
||||
__pthread_map_stacks_exec(void)
|
||||
__thr_map_stacks_exec(void)
|
||||
{
|
||||
struct pthread *curthread, *thrd;
|
||||
struct stack *st;
|
||||
|
@ -652,6 +652,7 @@ __thr_interpose_libc(void)
|
||||
SLOT(kevent);
|
||||
SLOT(wait6);
|
||||
SLOT(ppoll);
|
||||
SLOT(map_stacks_exec);
|
||||
#undef SLOT
|
||||
*(__libc_interposing_slot(
|
||||
INTERPOS__pthread_mutex_init_calloc_cb)) =
|
||||
|
Loading…
x
Reference in New Issue
Block a user