[hwasan] fix the linux-only pthread_create interceptor and reinstate the two threaded...
authorKostya Serebryany <kcc@google.com>
Thu, 30 Aug 2018 23:22:26 +0000 (23:22 +0000)
committerKostya Serebryany <kcc@google.com>
Thu, 30 Aug 2018 23:22:26 +0000 (23:22 +0000)
llvm-svn: 341143

compiler-rt/lib/hwasan/hwasan_interceptors.cc
compiler-rt/lib/hwasan/hwasan_thread.h
compiler-rt/test/hwasan/TestCases/many-threads-uaf.c [new file with mode: 0644]
compiler-rt/test/hwasan/TestCases/thread-uaf.c [new file with mode: 0644]

index 3c892c5..8512c04 100644 (file)
@@ -292,14 +292,6 @@ 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();
   ThreadStartArg *A = reinterpret_cast<ThreadStartArg*>(arg);
@@ -309,11 +301,10 @@ static void *HwasanThreadStartFunc(void *arg) {
 INTERCEPTOR(int, pthread_create, void *th, void *attr, void *(*callback)(void*),
             void * param) {
   ScopedTaggingDisabler disabler;
-  ThreadStartArg A;
-  A.callback = callback;
-  A.param = param;
+  ThreadStartArg *A = GetCurrentThread()->thread_start_arg();
+  *A = {callback, param};
   int res = REAL(pthread_create)(UntagPtr(th), UntagPtr(attr),
-                                 &HwasanThreadStartFunc, &A);
+                                 &HwasanThreadStartFunc, A);
   return res;
 }
 #endif // HWASAN_WITH_INTERCEPTORS
index 16df85e..11ecf2f 100644 (file)
 
 namespace __hwasan {
 
+struct ThreadStartArg {
+  thread_callback_t callback;
+  void *param;
+};
+
 class Thread {
  public:
   static Thread *Create(thread_callback_t start_routine, void *arg);
@@ -70,6 +75,10 @@ class Thread {
     }
   }
 
+  // Return a scratch ThreadStartArg object to be used in
+  // pthread_create interceptor.
+  ThreadStartArg *thread_start_arg() { return &thread_start_arg_; }
+
  private:
   // NOTE: There is no Thread constructor. It is allocated
   // via mmap() and *must* be valid in zero-initialized state.
@@ -99,6 +108,8 @@ class Thread {
   static Thread *main_thread;
 
   u32 tagging_disabled_;  // if non-zero, malloc uses zero tag in this thread.
+
+  ThreadStartArg thread_start_arg_;
 };
 
 Thread *GetCurrentThread();
diff --git a/compiler-rt/test/hwasan/TestCases/many-threads-uaf.c b/compiler-rt/test/hwasan/TestCases/many-threads-uaf.c
new file mode 100644 (file)
index 0000000..7ee3554
--- /dev/null
@@ -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);
+}
diff --git a/compiler-rt/test/hwasan/TestCases/thread-uaf.c b/compiler-rt/test/hwasan/TestCases/thread-uaf.c
new file mode 100644 (file)
index 0000000..f64ceba
--- /dev/null
@@ -0,0 +1,26 @@
+// 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 *Thread(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: thread-uaf.c:[[@LINE-3]]
+  return NULL;
+}
+
+int main() {
+  __hwasan_enable_allocator_tagging();
+  pthread_t t;
+  pthread_create(&t, NULL, Thread, NULL);
+  pthread_join(t, NULL);
+}