[compiler-rt] eaea9ed - [hwasan] Reset current thread pointer on thread exit.
Evgenii Stepanov via llvm-commits
llvm-commits at lists.llvm.org
Fri May 8 10:31:40 PDT 2020
Author: Evgenii Stepanov
Date: 2020-05-08T10:31:25-07:00
New Revision: eaea9ed83509d283db40aeeb324f2d4b235e816b
URL: https://github.com/llvm/llvm-project/commit/eaea9ed83509d283db40aeeb324f2d4b235e816b
DIFF: https://github.com/llvm/llvm-project/commit/eaea9ed83509d283db40aeeb324f2d4b235e816b.diff
LOG: [hwasan] Reset current thread pointer on thread exit.
Summary:
This is necessary to handle calls to free() after __hwasan_thread_exit,
which is possible in glibc.
Also, add a null check to GetCurrentThread, otherwise the logic in
GetThreadByBufferAddress turns it into a non-null value. This means that
all of the checks for GetCurrentThread() != nullptr do not have any
effect at all right now!
Reviewers: pcc, hctim
Subscribers: #sanitizers, llvm-commits
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D79608
Added:
compiler-rt/test/hwasan/TestCases/libc_thread_freeres.c
Modified:
compiler-rt/lib/hwasan/hwasan.cpp
compiler-rt/lib/hwasan/hwasan_linux.cpp
compiler-rt/lib/hwasan/hwasan_thread.cpp
Removed:
################################################################################
diff --git a/compiler-rt/lib/hwasan/hwasan.cpp b/compiler-rt/lib/hwasan/hwasan.cpp
index f8c9446b68b1..6f64829cc5ad 100644
--- a/compiler-rt/lib/hwasan/hwasan.cpp
+++ b/compiler-rt/lib/hwasan/hwasan.cpp
@@ -186,7 +186,7 @@ void __sanitizer::BufferedStackTrace::UnwindImpl(
uptr pc, uptr bp, void *context, bool request_fast, u32 max_depth) {
Thread *t = GetCurrentThread();
if (!t) {
- // the thread is still being created.
+ // The thread is still being created, or has already been destroyed.
size = 0;
return;
}
diff --git a/compiler-rt/lib/hwasan/hwasan_linux.cpp b/compiler-rt/lib/hwasan/hwasan_linux.cpp
index ed0f30161b02..f1e830ddf901 100644
--- a/compiler-rt/lib/hwasan/hwasan_linux.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_linux.cpp
@@ -354,8 +354,11 @@ void AndroidTestTlsSlot() {}
#endif
Thread *GetCurrentThread() {
- auto *R = (StackAllocationsRingBuffer *)GetCurrentThreadLongPtr();
- return hwasanThreadList().GetThreadByBufferAddress((uptr)(R->Next()));
+ uptr *ThreadLongPtr = GetCurrentThreadLongPtr();
+ if (UNLIKELY(*ThreadLongPtr == 0))
+ return nullptr;
+ auto *R = (StackAllocationsRingBuffer *)ThreadLongPtr;
+ return hwasanThreadList().GetThreadByBufferAddress((uptr)R->Next());
}
struct AccessInfo {
diff --git a/compiler-rt/lib/hwasan/hwasan_thread.cpp b/compiler-rt/lib/hwasan/hwasan_thread.cpp
index cabf614c005c..b81a6350c05c 100644
--- a/compiler-rt/lib/hwasan/hwasan_thread.cpp
+++ b/compiler-rt/lib/hwasan/hwasan_thread.cpp
@@ -90,6 +90,12 @@ void Thread::Destroy() {
if (heap_allocations_)
heap_allocations_->Delete();
DTLS_Destroy();
+ // Unregister this as the current thread.
+ // Instrumented code can not run on this thread from this point onwards, but
+ // malloc/free can still be served. Glibc may call free() very late, after all
+ // TSD destructors are done.
+ CHECK_EQ(GetCurrentThread(), this);
+ *GetCurrentThreadLongPtr() = 0;
}
void Thread::Print(const char *Prefix) {
diff --git a/compiler-rt/test/hwasan/TestCases/libc_thread_freeres.c b/compiler-rt/test/hwasan/TestCases/libc_thread_freeres.c
new file mode 100644
index 000000000000..83451f5bdf40
--- /dev/null
+++ b/compiler-rt/test/hwasan/TestCases/libc_thread_freeres.c
@@ -0,0 +1,22 @@
+// RUN: %clang_hwasan %s -o %t && %env_hwasan_opts=random_tags=1 %run %t
+// REQUIRES: stable-runtime
+
+#include <pthread.h>
+#include <sanitizer/hwasan_interface.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+void *ThreadFn(void *) {
+ strerror_l(-1, 0);
+ __hwasan_enable_allocator_tagging();
+ // This will trigger memory deallocation in __strerror_thread_freeres,
+ // at a point when HwasanThread is already gone.
+}
+
+int main() {
+ pthread_t t;
+ pthread_create(&t, NULL, ThreadFn, NULL);
+ pthread_join(t, NULL);
+ return 0;
+}
More information about the llvm-commits
mailing list