diff --git a/compiler-rt/include/sanitizer/dfsan_interface.h b/compiler-rt/include/sanitizer/dfsan_interface.h --- a/compiler-rt/include/sanitizer/dfsan_interface.h +++ b/compiler-rt/include/sanitizer/dfsan_interface.h @@ -80,9 +80,11 @@ size_t dfsan_get_label_count(void); /// Flushes the DFSan shadow, i.e. forgets about all labels currently associated -/// with the application memory. Will work only if there are no other -/// threads executing DFSan-instrumented code concurrently. -/// Use this call to start over the taint tracking within the same procces. +/// with the application memory. Use this call to start over the taint tracking +/// within the same process. +/// +/// Note: If another thread is working with tainted data during the flush, that +/// taint could still be written to shadow after the flush. void dfsan_flush(void); /// Sets a callback to be invoked on calls to write(). The callback is invoked diff --git a/compiler-rt/lib/dfsan/dfsan.cpp b/compiler-rt/lib/dfsan/dfsan.cpp --- a/compiler-rt/lib/dfsan/dfsan.cpp +++ b/compiler-rt/lib/dfsan/dfsan.cpp @@ -428,7 +428,6 @@ } extern "C" void dfsan_flush() { - UnmapOrDie((void*)ShadowAddr(), UnusedAddr() - ShadowAddr()); if (!MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr())) Die(); } diff --git a/compiler-rt/test/dfsan/threaded_flush.c b/compiler-rt/test/dfsan/threaded_flush.c new file mode 100644 --- /dev/null +++ b/compiler-rt/test/dfsan/threaded_flush.c @@ -0,0 +1,36 @@ +// Tests that doing dfsan_flush() while another thread is executing doesn't +// segfault. +// RUN: %clang_dfsan %s -o %t && %run %t +#include +#include +#include +#include + +static unsigned char GlobalBuf[4096]; +static int ShutDownThread; +static int StartFlush; + +// Access GlobalBuf continuously, causing its shadow to be touched as well. +// When main() calls dfsan_flush(), no segfault should be triggered. +static void *accessGlobalInBackground(void *Arg) { + __atomic_store_n(&StartFlush, 1, __ATOMIC_RELEASE); + + while (!__atomic_load_n(&ShutDownThread, __ATOMIC_ACQUIRE)) + for (unsigned I = 0; I < sizeof(GlobalBuf); ++I) + ++GlobalBuf[I]; + + return NULL; +} + +int main() { + pthread_t Thread; + pthread_create(&Thread, NULL, accessGlobalInBackground, NULL); + while (!__atomic_load_n(&StartFlush, __ATOMIC_ACQUIRE)) + ; // Spin + + dfsan_flush(); + + __atomic_store_n(&ShutDownThread, 1, __ATOMIC_RELEASE); + pthread_join(Thread, NULL); + return 0; +}