[compiler-rt] r341438 - [hwasan] print thread IDs when reporting a bug (also had to fix pthread_create on Linux)

Kostya Serebryany via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 4 18:16:50 PDT 2018


Author: kcc
Date: Tue Sep  4 18:16:50 2018
New Revision: 341438

URL: http://llvm.org/viewvc/llvm-project?rev=341438&view=rev
Log:
[hwasan] print thread IDs when reporting a bug (also had to fix pthread_create on Linux)

Modified:
    compiler-rt/trunk/lib/hwasan/hwasan_interceptors.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
    compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c
    compiler-rt/trunk/test/hwasan/TestCases/thread-uaf.c

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=341438&r1=341437&r2=341438&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_interceptors.cc Tue Sep  4 18:16:50 2018
@@ -292,16 +292,23 @@ 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;
+};
+
 static void *HwasanThreadStartFunc(void *arg) {
   __hwasan_thread_enter();
-  ThreadStartArg *A = reinterpret_cast<ThreadStartArg*>(arg);
-  return A->callback(A->param);
+  ThreadStartArg A = *reinterpret_cast<ThreadStartArg*>(arg);
+  UnmapOrDie(arg, GetPageSizeCached());
+  return A.callback(A.param);
 }
 
 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
             void * param) {
   ScopedTaggingDisabler disabler;
-  ThreadStartArg *A = GetCurrentThread()->thread_start_arg();
+  ThreadStartArg *A = reinterpret_cast<ThreadStartArg *> (MmapOrDie(
+      GetPageSizeCached(), "pthread_create"));
   *A = {callback, param};
   int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr),
                                  &HwasanThreadStartFunc, A);

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=341438&r1=341437&r2=341438&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_report.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_report.cc Tue Sep  4 18:16:50 2018
@@ -43,6 +43,7 @@ class Decorator: public __sanitizer::San
   const char *Origin() const { return Magenta(); }
   const char *Name() const { return Green(); }
   const char *Location() { return Green(); }
+  const char *Thread() { return Green(); }
 };
 
 bool FindHeapAllocation(HeapAllocationsRingBuffer *rb,
@@ -116,7 +117,7 @@ void PrintAddressDescription(uptr tagged
              har.requested_size, UntagAddr(har.tagged_addr),
              UntagAddr(har.tagged_addr) + har.requested_size);
       Printf("%s", d.Allocation());
-      Printf("freed by thread %p here:\n", t);
+      Printf("freed by thread T%zd here:\n", t->unique_id());
       Printf("%s", d.Default());
       GetStackTraceFromId(har.free_context_id).Print();
 
@@ -124,6 +125,7 @@ void PrintAddressDescription(uptr tagged
       Printf("previously allocated here:\n", t);
       Printf("%s", d.Default());
       GetStackTraceFromId(har.alloc_context_id).Print();
+      t->Announce();
 
       num_descriptions_printed++;
     }
@@ -131,8 +133,10 @@ void PrintAddressDescription(uptr tagged
     // Very basic check for stack memory.
     if (t->AddrIsInStack(untagged_addr)) {
       Printf("%s", d.Location());
-      Printf("Address %p is located in stack of thread %p\n", untagged_addr, t);
-      Printf("%s", d.Default());
+      Printf("Address %p is located in stack of thread T%zd\n", untagged_addr,
+             t->unique_id());
+      t->Announce();
+
       num_descriptions_printed++;
     }
   });
@@ -230,18 +234,21 @@ void ReportTagMismatch(StackTrace *stack
   Report("ERROR: %s: %s on address %p at pc %p\n", SanitizerToolName, bug_type,
          untagged_addr, pc);
 
+  Thread *t = GetCurrentThread();
+
   tag_t ptr_tag = GetTagFromPointer(tagged_addr);
   tag_t *tag_ptr = reinterpret_cast<tag_t*>(MemToShadow(untagged_addr));
   tag_t mem_tag = *tag_ptr;
   Printf("%s", d.Access());
-  Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem)\n",
+  Printf("%s of size %zu at %p tags: %02x/%02x (ptr/mem) in thread T%zd\n",
          is_store ? "WRITE" : "READ", access_size, untagged_addr, ptr_tag,
-         mem_tag);
+         mem_tag, t->unique_id());
   Printf("%s", d.Default());
 
   stack->Print();
 
   PrintAddressDescription(tagged_addr, access_size);
+  t->Announce();
 
   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=341438&r1=341437&r2=341438&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.cc (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.cc Tue Sep  4 18:16:50 2018
@@ -63,10 +63,11 @@ void Thread::Create() {
   uptr size = RoundUpTo(sizeof(Thread), PageSize);
   Thread *thread = (Thread*)MmapOrDie(size, __func__);
   thread->destructor_iterations_ = GetPthreadDestructorIterations();
-  thread->random_state_ = flags()->random_tags ? RandomSeed() : 0;
+  thread->unique_id_ = unique_id++;
+  thread->random_state_ =
+      flags()->random_tags ? RandomSeed() : thread->unique_id_;
   if (auto sz = flags()->heap_history_size)
     thread->heap_allocations_ = RingBuffer<HeapAllocationRecord>::New(sz);
-  thread->unique_id_ = unique_id++;
   InsertIntoThreadList(thread);
   SetCurrentThread(thread);
   thread->Init();
@@ -100,7 +101,7 @@ void Thread::Init() {
     CHECK(MemIsApp(stack_top_ - 1));
   }
   if (flags()->verbose_threads)
-    Print("Creating  ");
+    Print("Creating  : ");
 }
 
 void Thread::ClearShadowForThreadStackAndTLS() {
@@ -112,7 +113,7 @@ void Thread::ClearShadowForThreadStackAn
 
 void Thread::Destroy() {
   if (flags()->verbose_threads)
-    Print("Destroying");
+    Print("Destroying: ");
   malloc_storage().CommitBack();
   ClearShadowForThreadStackAndTLS();
   RemoveFromThreadList(this);
@@ -124,8 +125,8 @@ void Thread::Destroy() {
 }
 
 void Thread::Print(const char *Prefix) {
-  Printf("%s: thread %p id: %zd stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix,
-         this, unique_id_, stack_bottom(), stack_top(),
+  Printf("%sT%zd %p stack: [%p,%p) sz: %zd tls: [%p,%p)\n", Prefix,
+         unique_id_, this, stack_bottom(), stack_top(),
          stack_top() - stack_bottom(),
          tls_begin(), tls_end());
 }

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=341438&r1=341437&r2=341438&view=diff
==============================================================================
--- compiler-rt/trunk/lib/hwasan/hwasan_thread.h (original)
+++ compiler-rt/trunk/lib/hwasan/hwasan_thread.h Tue Sep  4 18:16:50 2018
@@ -19,11 +19,6 @@
 
 namespace __hwasan {
 
-struct ThreadStartArg {
-  thread_callback_t callback;
-  void *param;
-};
-
 class Thread {
  public:
   static void Create();  // Must be called from the thread itself.
@@ -73,9 +68,12 @@ class Thread {
     }
   }
 
-  // Return a scratch ThreadStartArg object to be used in
-  // pthread_create interceptor.
-  ThreadStartArg *thread_start_arg() { return &thread_start_arg_; }
+  u64 unique_id() const { return unique_id_; }
+  void Announce() {
+    if (announced_) return;
+    announced_ = true;
+    Print("Thread: ");
+  }
 
  private:
   // NOTE: There is no Thread constructor. It is allocated
@@ -108,7 +106,7 @@ class Thread {
 
   u32 tagging_disabled_;  // if non-zero, malloc uses zero tag in this thread.
 
-  ThreadStartArg thread_start_arg_;
+  bool announced_;
 };
 
 Thread *GetCurrentThread();

Modified: 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=341438&r1=341437&r2=341438&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/many-threads-uaf.c Tue Sep  4 18:16:50 2018
@@ -14,12 +14,12 @@ void *BoringThread(void *arg) {
   return NULL;
 }
 
-// CHECK: Creating  : thread {{.*}} id: 0
-// CHECK: Creating  : thread {{.*}} id: 1
-// CHECK: Destroying: thread {{.*}} id: 1
-// CHECK: Creating  : thread {{.*}} id: 1100
-// CHECK: Destroying: thread {{.*}} id: 1100
-// CHECK: Creating  : thread {{.*}} id: 1101
+// CHECK: Creating  : T0
+// CHECK: Creating  : T1
+// CHECK: Destroying: T1
+// CHECK: Creating  : T1100
+// CHECK: Destroying: T1100
+// CHECK: Creating  : T1101
 
 void *UAFThread(void *arg) {
   char * volatile x = (char*)malloc(10);
@@ -29,6 +29,7 @@ void *UAFThread(void *arg) {
   // CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address
   // CHECK: WRITE of size 1
   // CHECK: many-threads-uaf.c:[[@LINE-3]]
+  // CHECK: Thread: T1101
   return NULL;
 }
 

Modified: compiler-rt/trunk/test/hwasan/TestCases/thread-uaf.c
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/hwasan/TestCases/thread-uaf.c?rev=341438&r1=341437&r2=341438&view=diff
==============================================================================
--- compiler-rt/trunk/test/hwasan/TestCases/thread-uaf.c (original)
+++ compiler-rt/trunk/test/hwasan/TestCases/thread-uaf.c Tue Sep  4 18:16:50 2018
@@ -1,3 +1,5 @@
+// Tests UAF detection where Allocate/Deallocate/Use
+// happen in separate threads.
 // RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
 // REQUIRES: stable-runtime
 
@@ -7,20 +9,48 @@
 
 #include <sanitizer/hwasan_interface.h>
 
-void *Thread(void *arg) {
-  char * volatile x = (char*)malloc(10);
-  fprintf(stderr, "ZZZ %p\n", x);
+char *volatile x;
+int state;
+
+void *Allocate(void *arg) {
+  x = (char*)malloc(10);
+  __sync_fetch_and_add(&state, 1);
+  while (__sync_fetch_and_add(&state, 0) != 3) {}
+  return NULL;
+}
+void *Deallocate(void *arg) {
+  while (__sync_fetch_and_add(&state, 0) != 1) {}
   free(x);
+  __sync_fetch_and_add(&state, 1);
+  while (__sync_fetch_and_add(&state, 0) != 3) {}
+  return NULL;
+}
+
+void *Use(void *arg) {
+  while (__sync_fetch_and_add(&state, 0) != 2) {}
   x[5] = 42;
   // CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address
-  // CHECK: WRITE of size 1
+  // CHECK: WRITE of size 1 {{.*}} in thread T3
   // CHECK: thread-uaf.c:[[@LINE-3]]
+  // CHECK: freed by thread T2 here
+  // CHECK: in Deallocate
+  // CHECK: previously allocated here:
+  // CHECK: in Allocate
+  // CHECK: Thread: T2 0x
+  // CHECK: Thread: T3 0x
+  __sync_fetch_and_add(&state, 1);
   return NULL;
 }
 
 int main() {
   __hwasan_enable_allocator_tagging();
-  pthread_t t;
-  pthread_create(&t, NULL, Thread, NULL);
-  pthread_join(t, NULL);
+  pthread_t t1, t2, t3;
+
+  pthread_create(&t1, NULL, Allocate, NULL);
+  pthread_create(&t2, NULL, Deallocate, NULL);
+  pthread_create(&t3, NULL, Use, NULL);
+
+  pthread_join(t1, NULL);
+  pthread_join(t2, NULL);
+  pthread_join(t3, NULL);
 }




More information about the llvm-commits mailing list