summaryrefslogtreecommitdiff
path: root/compiler-rt
diff options
context:
space:
mode:
authorVitaly Buka <vitalybuka@google.com>2023-05-08 16:18:32 -0700
committerVitaly Buka <vitalybuka@google.com>2023-05-11 15:20:02 -0700
commit68b76af8a48a49f20216941dc903cc5814f5b4ff (patch)
treed7962cba60dfbcb05b48125966a4a74c1f628187 /compiler-rt
parentf772dcbb5104bc83548e2454909f0a870dfadde5 (diff)
downloadllvm-68b76af8a48a49f20216941dc903cc5814f5b4ff.tar.gz
[HWSAN] Use ThreadArgRetval in HWSAN
Fixes false leaks on thread arg, retval. Reviewed By: Enna1 Differential Revision: https://reviews.llvm.org/D150166
Diffstat (limited to 'compiler-rt')
-rw-r--r--compiler-rt/lib/hwasan/hwasan_interceptors.cpp60
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread.cpp15
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread_list.cpp12
-rw-r--r--compiler-rt/lib/hwasan/hwasan_thread_list.h3
-rw-r--r--compiler-rt/test/lsan/TestCases/create_thread_leak.cpp5
5 files changed, 75 insertions, 20 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
diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cpp b/compiler-rt/lib/hwasan/hwasan_thread.cpp
index 3375782ef29b..5faa89954185 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_thread.cpp
@@ -173,9 +173,15 @@ static __hwasan::Thread *GetThreadByOsIDLocked(tid_t os_id) {
[os_id](__hwasan::Thread *t) { return t->os_id() == os_id; });
}
-void LockThreadRegistry() { __hwasan::hwasanThreadList().Lock(); }
+void LockThreadRegistry() {
+ __hwasan::hwasanThreadList().Lock();
+ __hwasan::hwasanThreadArgRetval().Lock();
+}
-void UnlockThreadRegistry() { __hwasan::hwasanThreadList().Unlock(); }
+void UnlockThreadRegistry() {
+ __hwasan::hwasanThreadArgRetval().Unlock();
+ __hwasan::hwasanThreadList().Unlock();
+}
void EnsureMainThreadIDIsCorrect() { __hwasan::EnsureMainThreadIDIsCorrect(); }
@@ -202,7 +208,10 @@ void GetThreadExtraStackRangesLocked(tid_t os_id,
InternalMmapVector<Range> *ranges) {}
void GetThreadExtraStackRangesLocked(InternalMmapVector<Range> *ranges) {}
-void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {}
+void GetAdditionalThreadContextPtrsLocked(InternalMmapVector<uptr> *ptrs) {
+ __hwasan::hwasanThreadArgRetval().GetAllPtrsLocked(ptrs);
+}
+
void GetRunningThreadsLocked(InternalMmapVector<tid_t> *threads) {}
} // namespace __lsan
diff --git a/compiler-rt/lib/hwasan/hwasan_thread_list.cpp b/compiler-rt/lib/hwasan/hwasan_thread_list.cpp
index 1ae3664f2827..7df4dd3d7851 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread_list.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_thread_list.cpp
@@ -1,10 +1,14 @@
#include "hwasan_thread_list.h"
+#include "sanitizer_common/sanitizer_thread_arg_retval.h"
+
namespace __hwasan {
static HwasanThreadList *hwasan_thread_list;
+static ThreadArgRetval *thread_data;
HwasanThreadList &hwasanThreadList() { return *hwasan_thread_list; }
+ThreadArgRetval &hwasanThreadArgRetval() { return *thread_data; }
void InitThreadList(uptr storage, uptr size) {
CHECK_EQ(hwasan_thread_list, nullptr);
@@ -13,6 +17,12 @@ void InitThreadList(uptr storage, uptr size) {
HwasanThreadList)) char thread_list_placeholder[sizeof(HwasanThreadList)];
hwasan_thread_list =
new (thread_list_placeholder) HwasanThreadList(storage, size);
+
+ CHECK_EQ(thread_data, nullptr);
+
+ static ALIGNED(alignof(
+ ThreadArgRetval)) char thread_data_placeholder[sizeof(ThreadArgRetval)];
+ thread_data = new (thread_data_placeholder) ThreadArgRetval();
}
-} // namespace __hwasan
+} // namespace __hwasan
diff --git a/compiler-rt/lib/hwasan/hwasan_thread_list.h b/compiler-rt/lib/hwasan/hwasan_thread_list.h
index 0400499f93d5..82f6c70a03f8 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread_list.h
+++ b/compiler-rt/lib/hwasan/hwasan_thread_list.h
@@ -47,8 +47,8 @@
#include "hwasan_allocator.h"
#include "hwasan_flags.h"
#include "hwasan_thread.h"
-
#include "sanitizer_common/sanitizer_placement_new.h"
+#include "sanitizer_common/sanitizer_thread_arg_retval.h"
namespace __hwasan {
@@ -222,5 +222,6 @@ class SANITIZER_MUTEX HwasanThreadList {
void InitThreadList(uptr storage, uptr size);
HwasanThreadList &hwasanThreadList();
+ThreadArgRetval &hwasanThreadArgRetval();
} // namespace __hwasan
diff --git a/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp b/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp
index 14acd1472bfd..10c377658e61 100644
--- a/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp
+++ b/compiler-rt/test/lsan/TestCases/create_thread_leak.cpp
@@ -6,9 +6,8 @@
// RUN: %run not %t 10 0 0 1 2>&1 | FileCheck %s --check-prefixes=LEAK,LEAK234
// FIXME: Remove "not". There is no leak.
-// False LEAK123 is broken for HWASAN.
-// False LEAK234 is broken for ASAN, HWASAN, LSAN.
-// RUN: %run %if asan %{ not %} %if hwasan %{ not %} %if lsan-standalone %{ not %} %t 10 0 0 0
+// False LEAK234 is broken for ASAN, LSAN.
+// RUN: %run %if asan %{ not %} %if lsan-standalone %{ not %} %t 10 0 0 0
#include <pthread.h>
#include <stdlib.h>