[compiler-rt] r341111 - [hwasan] simplify the thread hangling: instead of the ThreadRegistry (too heavy) simply maintain a linked list of Threads

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Thu Aug 30 13:15:40 PDT 2018


Author: kcc
Date: Thu Aug 30 13:15:39 2018
New Revision: 341111

URL: http://llvm.org/viewvc/llvm-project?rev=341111&view=rev
Log:
[hwasan] simplify the thread hangling: instead of the ThreadRegistry (too heavy) simply maintain a linked list of Threads

Added:
    compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c
Modified:
    compiler-rt/trunk/lib/hwasan/hwasan.cc
    compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc
    compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
    compiler-rt/trunk/lib/hwasan/hwasan_report.cc
    compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
    compiler-rt/trunk/lib/hwasan/hwasan_thread.h

Modified: compiler-rt/trunk/lib/hwasan/hwasan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan.cc?rev=341111&r1=341110&r2=341111&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan.cc Thu Aug 30 13:15:39 2018
@@ -183,7 +183,6 @@ void __hwasan_init() {
   if (hwasan_inited) return;
   hwasan_init_is_running = 1;
   SanitizerToolName = "HWAddressSanitizer";
-  GetThreadRegistry();
 
   InitTlsSize();
 

Modified: compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc?rev=341111&r1=341110&r2=341111&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc Thu Aug 30 13:15:39 2018
@@ -292,29 +292,28 @@ INTERCEPTOR(void *, malloc, SIZE_T size)
 extern "C" int pthread_attr_init(void *attr);
 extern "C" int pthread_attr_destroy(void *attr);
 
+struct ThreadStartArg {
+  thread_callback_t callback;
+  void *param;
+  // TODO: something crazy is going on with pthread_create overwriting parts
+  // of the stack, hense the padding.
+  char padding[1000];
+};
+
 static void *HwasanThreadStartFunc(void *arg) {
   __hwasan_thread_enter();
-  return ((Thread *)arg)->ThreadStart();
+  ThreadStartArg *A = reinterpret_cast<ThreadStartArg*>(arg);
+  return A->callback(A->param);
 }
 
 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
             void * param) {
-  ENSURE_HWASAN_INITED(); // for GetTlsSize()
-  __sanitizer_pthread_attr_t myattr;
   ScopedTaggingDisabler disabler;
-  if (!attr) {
-    pthread_attr_init(&myattr);
-    attr = &myattr;
-  }
-
-  AdjustStackSize(attr);
-
-  Thread *t = Thread::Create(callback, param);
+  ThreadStartArg A;
+  A.callback = callback;
+  A.param = param;
   int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr),
-                                 HwasanThreadStartFunc, UntagPtr(t));
-
-  if (attr == &myattr)
-    pthread_attr_destroy(&myattr);
+                                 &HwasanThreadStartFunc, &A);
   return res;
 }
 #endif // HWASAN_WITH_INTERCEPTORS

Modified: compiler-rt/trunk/lib/hwasan/hwasan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_linux.cc?rev=341111&r1=341110&r2=341111&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_linux.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_linux.cc Thu Aug 30 13:15:39 2018
@@ -238,6 +238,7 @@ void HwasanTSDDtor(void *tsd) {
     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
     return;
   }
+  t->Destroy();
   __hwasan_thread_exit();
 }
 

Modified: compiler-rt/trunk/lib/hwasan/hwasan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_report.cc?rev=341111&r1=341110&r2=341111&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.cc Thu Aug 30 13:15:39 2018
@@ -210,7 +210,6 @@ void ReportTagMismatch(StackTrace *stack
   if (FindHeapAllocation(t->heap_allocations(), tagged_addr, &har))
     Printf("Address found in the ring buffer: %p %u %u\n", har.tagged_addr,
            har.free_context_id, har.requested_size);
-  Printf("Current thread: tid: %d\n", t->context()->tid);
 
 
   PrintTagsAroundAddr(tag_ptr);

Modified: compiler-rt/trunk/lib/hwasan/hwasan_thread.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_thread.cc?rev=341111&r1=341110&r2=341111&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.cc Thu Aug 30 13:15:39 2018
@@ -24,6 +24,39 @@ static u32 RandomSeed() {
   return seed;
 }
 
+static Thread *main_thread;
+static SpinMutex thread_list_mutex;
+
+void Thread::InsertIntoThreadList(Thread *t) {
+  CHECK(!t->next_);
+  if (!main_thread) {
+    main_thread = t;
+    return;
+  }
+  SpinMutexLock l(&thread_list_mutex);
+  Thread *last = main_thread;
+  while (last->next_)
+    last = last->next_;
+  last->next_ = t;
+}
+
+void Thread::RemoveFromThreadList(Thread *t) {
+  CHECK_NE(t, main_thread);
+  SpinMutexLock l(&thread_list_mutex);
+  Thread *prev = main_thread;
+  Thread *cur = prev->next_;
+  CHECK(cur);
+  while (cur) {
+    if (cur == t) {
+      prev->next_ = cur->next_;
+      return;
+    }
+    prev = cur;
+    cur = cur->next_;
+  }
+  CHECK(0 && "RemoveFromThreadList: thread not found");
+}
+
 Thread *Thread::Create(thread_callback_t start_routine,
                                void *arg) {
   uptr PageSize = GetPageSizeCached();
@@ -33,11 +66,9 @@ Thread *Thread::Create(thread_callback_t
   thread->arg_ = arg;
   thread->destructor_iterations_ = GetPthreadDestructorIterations();
   thread->random_state_ = flags()->random_tags ? RandomSeed() : 0;
-  thread->context_ = nullptr;
-  ThreadContext::Args args = {thread};
-  thread->tid_ = GetThreadRegistry().CreateThread(0, false, 0, &args);
   if (auto sz = flags()->heap_history_size)
     thread->heap_allocations_ = RingBuffer<HeapAllocationRecord>::New(sz);
+  InsertIntoThreadList(thread);
   return thread;
 }
 
@@ -80,6 +111,7 @@ void Thread::ClearShadowForThreadStackAn
 void Thread::Destroy() {
   malloc_storage().CommitBack();
   ClearShadowForThreadStackAndTLS();
+  RemoveFromThreadList(this);
   uptr size = RoundUpTo(sizeof(Thread), GetPageSizeCached());
   if (heap_allocations_)
     heap_allocations_->Delete();
@@ -87,10 +119,6 @@ void Thread::Destroy() {
   DTLS_Destroy();
 }
 
-thread_return_t Thread::ThreadStart() {
-  return start_routine_(arg_);
-}
-
 static u32 xorshift(u32 state) {
   state ^= state << 13;
   state ^= state >> 17;
@@ -115,32 +143,4 @@ tag_t Thread::GenerateRandomTag() {
   return tag;
 }
 
-void ThreadContext::OnCreated(void *arg) {
-  Args *args = static_cast<Args*>(arg);
-  thread = args->thread;
-  thread->set_context(this);
-}
-
-void ThreadContext::OnFinished() {
-  thread = nullptr;
-}
-
-static const u32 kMaxLiveThreads = 1024;
-
-static ThreadContextBase *ThreadContextFactory(u32 tid) {
-  static ALIGNED(16) char placeholder[sizeof(ThreadContext) * kMaxLiveThreads];
-  void *mem = &placeholder[0] + tid * sizeof(ThreadContext);
-  CHECK_LT(tid, kMaxLiveThreads);
-  return new (mem) ThreadContext(tid);
-}
-
-ThreadRegistry &GetThreadRegistry() {
-  static ALIGNED(16) char placeholder[sizeof(ThreadRegistry)];
-  static ThreadRegistry *registry;
-  if (!registry)
-    registry = new (placeholder)
-        ThreadRegistry(ThreadContextFactory, kMaxLiveThreads, kMaxLiveThreads);
-  return *registry;
-}
-
 } // namespace __hwasan

Modified: compiler-rt/trunk/lib/hwasan/hwasan_thread.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/hwasan/hwasan_thread.h?rev=341111&r1=341110&r2=341111&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.h Thu Aug 30 13:15:39 2018
@@ -16,37 +16,15 @@
 
 #include "hwasan_allocator.h"
 #include "sanitizer_common/sanitizer_common.h"
-#include "sanitizer_common/sanitizer_thread_registry.h"
 
 namespace __hwasan {
 
-class Thread;
-
-class ThreadContext : public ThreadContextBase {
- public:
-  explicit ThreadContext(int tid)
-      : ThreadContextBase(tid), thread(nullptr){}
-
-  Thread *thread;
-
-  void OnCreated(void *arg) override;
-  void OnFinished() override;
-
-  struct Args {
-    Thread *thread;
-  };
-};
-
-// We want this to be small.
-COMPILER_CHECK(sizeof(ThreadContext) <= 256);
-
 class Thread {
  public:
   static Thread *Create(thread_callback_t start_routine, void *arg);
   void Destroy();
 
   void Init();
-  thread_return_t ThreadStart();
 
   uptr stack_top() { return stack_top_; }
   uptr stack_bottom() { return stack_bottom_; }
@@ -75,9 +53,6 @@ class Thread {
     return heap_allocations_;
   }
 
-  void set_context(ThreadContext *context) { context_ = context; }
-  const ThreadContext *context() const { return context_; }
-
   tag_t GenerateRandomTag();
 
   int destructor_iterations_;
@@ -107,8 +82,9 @@ class Thread {
   HwasanThreadLocalMallocStorage malloc_storage_;
   HeapAllocationsRingBuffer *heap_allocations_;
 
-  u32 tid_;
-  ThreadContext *context_;
+  static void InsertIntoThreadList(Thread *t);
+  static void RemoveFromThreadList(Thread *t);
+  Thread *next_;  // All live threads form a linked list.
 
   u32 tagging_disabled_;  // if non-zero, malloc uses zero tag in this thread.
 };
@@ -116,16 +92,11 @@ class Thread {
 Thread *GetCurrentThread();
 void SetCurrentThread(Thread *t);
 
-// Returns the ThreadRegistry singleton.
-ThreadRegistry &GetThreadRegistry();
-
 struct ScopedTaggingDisabler {
   ScopedTaggingDisabler() { GetCurrentThread()->DisableTagging(); }
   ~ScopedTaggingDisabler() { GetCurrentThread()->EnableTagging(); }
 };
 
-// Returns the ThreadRegistry singleton.
-
 } // namespace __hwasan
 
 #endif // HWASAN_THREAD_H

Added: compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c?rev=341111&view=auto
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c (added)
+++ compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c Thu Aug 30 13:15:39 2018
@@ -0,0 +1,37 @@
+// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
+// REQUIRES: stable-runtime
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <sanitizer/hwasan_interface.h>
+
+void *BoringThread(void *arg) {
+  char * volatile x = (char*)malloc(10);
+  x[5] = 0;
+  free(x);
+  return NULL;
+}
+
+void *UAFThread(void *arg) {
+  char * volatile x = (char*)malloc(10);
+  fprintf(stderr, "ZZZ %p\n", x);
+  free(x);
+  x[5] = 42;
+  // CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address
+  // CHECK: WRITE of size 1
+  // CHECK: many-threads-uaf.c:[[@LINE-3]]
+  return NULL;
+}
+
+int main() {
+  __hwasan_enable_allocator_tagging();
+  pthread_t t;
+  for (int i = 0; i < 1100; i++) {
+    pthread_create(&t, NULL, BoringThread, NULL);
+    pthread_join(t, NULL);
+  }
+  pthread_create(&t, NULL, UAFThread, NULL);
+  pthread_join(t, NULL);
+}




More information about the llvm-commits mailing list