summaryrefslogtreecommitdiff
path: root/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'compiler-rt/lib/hwasan/hwasan_interceptors.cpp')
-rw-r--r--compiler-rt/lib/hwasan/hwasan_interceptors.cpp60
1 files changed, 48 insertions, 12 deletions
diff --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
index 096bfe5b1864..75711de5a691 100644
--- a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
@@ -17,6 +17,7 @@
#include "hwasan.h"
#include "hwasan_checks.h"
#include "hwasan_thread.h"
+#include "hwasan_thread_list.h"
#include "interception/interception.h"
#include "sanitizer_common/sanitizer_linux.h"
#include "sanitizer_common/sanitizer_stackdepot.h"
@@ -44,8 +45,6 @@ using namespace __hwasan;
# include "sanitizer_common/sanitizer_syscalls_netbsd.inc"
struct ThreadStartArg {
- thread_callback_t callback;
- void *param;
__sanitizer_sigset_t starting_sigset_;
};
@@ -54,47 +53,84 @@ static void *HwasanThreadStartFunc(void *arg) {
ThreadStartArg A = *reinterpret_cast<ThreadStartArg *>(arg);
SetSigProcMask(&A.starting_sigset_, nullptr);
InternalFree(arg);
- return A.callback(A.param);
+ auto self = GetThreadSelf();
+ auto args = hwasanThreadArgRetval().GetArgs(self);
+ void *retval = (*args.routine)(args.arg_retval);
+ hwasanThreadArgRetval().Finish(self, retval);
+ return retval;
}
-INTERCEPTOR(int, pthread_create, void *th, void *attr,
+extern "C" {
+int pthread_attr_getdetachstate(void *attr, int *v);
+}
+
+INTERCEPTOR(int, pthread_create, void *thread, void *attr,
void *(*callback)(void *), void *param) {
EnsureMainThreadIDIsCorrect();
ScopedTaggingDisabler tagging_disabler;
+ int detached = 0;
+ if (attr)
+ pthread_attr_getdetachstate(attr, &detached);
ThreadStartArg *A = (ThreadStartArg *)InternalAlloc(sizeof(ThreadStartArg));
- A->callback = callback;
- A->param = param;
ScopedBlockSignals block(&A->starting_sigset_);
// ASAN uses the same approach to disable leaks from pthread_create.
# if CAN_SANITIZE_LEAKS
__lsan::ScopedInterceptorDisabler lsan_disabler;
# endif
- int result = REAL(pthread_create)(th, attr, &HwasanThreadStartFunc, A);
+
+ int result;
+ hwasanThreadArgRetval().Create(detached, {callback, param}, [&]() -> uptr {
+ result = REAL(pthread_create)(thread, attr, &HwasanThreadStartFunc, A);
+ return result ? 0 : *(uptr *)(thread);
+ });
if (result != 0)
InternalFree(A);
return result;
}
-INTERCEPTOR(int, pthread_join, void *t, void **arg) {
- return REAL(pthread_join)(t, arg);
+INTERCEPTOR(int, pthread_join, void *thread, void **retval) {
+ int result;
+ hwasanThreadArgRetval().Join((uptr)thread, [&]() {
+ result = REAL(pthread_join)(thread, retval);
+ return !result;
+ });
+ return result;
}
INTERCEPTOR(int, pthread_detach, void *thread) {
- return REAL(pthread_detach)(thread);
+ int result;
+ hwasanThreadArgRetval().Detach((uptr)thread, [&]() {
+ result = REAL(pthread_detach)(thread);
+ return !result;
+ });
+ return result;
}
INTERCEPTOR(int, pthread_exit, void *retval) {
+ auto *t = GetCurrentThread();
+ if (t && !t->IsMainThread())
+ hwasanThreadArgRetval().Finish(GetThreadSelf(), retval);
return REAL(pthread_exit)(retval);
}
# if SANITIZER_GLIBC
INTERCEPTOR(int, pthread_tryjoin_np, void *thread, void **ret) {
- return REAL(pthread_tryjoin_np)(thread, ret);
+ int result;
+ hwasanThreadArgRetval().Join((uptr)thread, [&]() {
+ result = REAL(pthread_tryjoin_np)(thread, ret);
+ return !result;
+ });
+ return result;
}
INTERCEPTOR(int, pthread_timedjoin_np, void *thread, void **ret,
const struct timespec *abstime) {
- return REAL(pthread_timedjoin_np)(thread, ret, abstime);
+ int result;
+ hwasanThreadArgRetval().Join((uptr)thread, [&]() {
+ result = REAL(pthread_timedjoin_np)(thread, ret, abstime);
+ return !result;
+ });
+ return result;
}
# endif