[compiler-rt] 68b76af - [HWSAN] Use ThreadArgRetval in HWSAN

Vitaly Buka via llvm-commits llvm-commits at lists.llvm.org
Thu May 11 15:20:15 PDT 2023


Author: Vitaly Buka
Date: 2023-05-11T15:20:02-07:00
New Revision: 68b76af8a48a49f20216941dc903cc5814f5b4ff

URL: https://github.com/llvm/llvm-project/commit/68b76af8a48a49f20216941dc903cc5814f5b4ff
DIFF: https://github.com/llvm/llvm-project/commit/68b76af8a48a49f20216941dc903cc5814f5b4ff.diff

LOG: [HWSAN] Use ThreadArgRetval in HWSAN

Fixes false leaks on thread arg, retval.

Reviewed By: Enna1

Differential Revision: https://reviews.llvm.org/D150166

Added: 
    

Modified: 
    compiler-rt/lib/hwasan/hwasan_interceptors.cpp
    compiler-rt/lib/hwasan/hwasan_thread.cpp
    compiler-rt/lib/hwasan/hwasan_thread_list.cpp
    compiler-rt/lib/hwasan/hwasan_thread_list.h
    compiler-rt/test/lsan/TestCases/create_thread_leak.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/hwasan/hwasan_interceptors.cpp b/compiler-rt/lib/hwasan/hwasan_interceptors.cpp
index 096bfe5b1864f..75711de5a691f 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 3375782ef29b4..5faa899541854 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 1ae3664f28273..7df4dd3d78518 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 0400499f93d5c..82f6c70a03f80 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 14acd1472bfda..10c377658e610 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>


        


More information about the llvm-commits mailing list