summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkib <kib@FreeBSD.org>2016-02-08 19:24:13 +0000
committerkib <kib@FreeBSD.org>2016-02-08 19:24:13 +0000
commit42e09be9c23e730d42b331384d128dbba8719c04 (patch)
treec91cbb77944f06638bce887f736eaeafed34a388
parent42bcd86bfbff24f6d52e96805b6d8d535c7db051 (diff)
downloadFreeBSD-src-42e09be9c23e730d42b331384d128dbba8719c04.zip
FreeBSD-src-42e09be9c23e730d42b331384d128dbba8719c04.tar.gz
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
-rw-r--r--lib/libc/gen/elf_utils.c11
-rw-r--r--lib/libc/include/libc_private.h2
-rw-r--r--lib/libc/sys/interposing_table.c1
-rw-r--r--lib/libthr/pthread.map2
-rw-r--r--lib/libthr/thread/thr_private.h2
-rw-r--r--lib/libthr/thread/thr_stack.c3
-rw-r--r--lib/libthr/thread/thr_syscalls.c1
7 files changed, 16 insertions, 6 deletions
diff --git a/lib/libc/gen/elf_utils.c b/lib/libc/gen/elf_utils.c
index 069f62e..80ab013 100644
--- a/lib/libc/gen/elf_utils.c
+++ b/lib/libc/gen/elf_utils.c
@@ -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])();
+}
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
index 5caf9a3..554f3a2 100644
--- a/lib/libc/include/libc_private.h
+++ b/lib/libc/include/libc_private.h
@@ -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);
diff --git a/lib/libc/sys/interposing_table.c b/lib/libc/sys/interposing_table.c
index 08dfbb1..75bb280 100644
--- a/lib/libc/sys/interposing_table.c
+++ b/lib/libc/sys/interposing_table.c
@@ -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
diff --git a/lib/libthr/pthread.map b/lib/libthr/pthread.map
index 0903989..9fb72eb 100644
--- a/lib/libthr/pthread.map
+++ b/lib/libthr/pthread.map
@@ -295,8 +295,6 @@ FBSDprivate_1.0 {
_thread_size_key;
_thread_state_running;
_thread_state_zoombie;
-
- __pthread_map_stacks_exec;
};
FBSD_1.1 {
diff --git a/lib/libthr/thread/thr_private.h b/lib/libthr/thread/thr_private.h
index 0ba123d..6020e07 100644
--- a/lib/libthr/thread/thr_private.h
+++ b/lib/libthr/thread/thr_private.h
@@ -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);
diff --git a/lib/libthr/thread/thr_stack.c b/lib/libthr/thread/thr_stack.c
index e5d149e..74e1329 100644
--- a/lib/libthr/thread/thr_stack.c
+++ b/lib/libthr/thread/thr_stack.c
@@ -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;
diff --git a/lib/libthr/thread/thr_syscalls.c b/lib/libthr/thread/thr_syscalls.c
index 7c05697..712249b 100644
--- a/lib/libthr/thread/thr_syscalls.c
+++ b/lib/libthr/thread/thr_syscalls.c
@@ -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)) =
OpenPOWER on IntegriCloud