Index: include/sanitizer/dfsan_interface.h =================================================================== --- include/sanitizer/dfsan_interface.h +++ include/sanitizer/dfsan_interface.h @@ -52,6 +52,13 @@ /// Sets the label for each address in [addr,addr+size) to \c label. void dfsan_set_label(dfsan_label label, void *addr, size_t size); +// Reset labels and shadow memory for dfsan to restart from clean. +// This is intended to work in a single threaded setting (main use +// case is to avoid running out of labels in fuzzing). +// This function is not safe to use in multithreaded code or when +// there are active stack frames processing non-zero labels. +void dfsan_reset(void); + /// Sets the label for each address in [addr,addr+size) to the union of the /// current label for that address and \c label. void dfsan_add_label(dfsan_label label, void *addr, size_t size); Index: lib/dfsan/dfsan.h =================================================================== --- lib/dfsan/dfsan.h +++ lib/dfsan/dfsan.h @@ -34,6 +34,7 @@ extern "C" { void dfsan_add_label(dfsan_label label, void *addr, uptr size); void dfsan_set_label(dfsan_label label, void *addr, uptr size); +void dfsan_reset(void); dfsan_label dfsan_read_label(const void *addr, uptr size); dfsan_label dfsan_union(dfsan_label l1, dfsan_label l2); } // extern "C" Index: lib/dfsan/dfsan.cc =================================================================== --- lib/dfsan/dfsan.cc +++ lib/dfsan/dfsan.cc @@ -26,6 +26,7 @@ #include "sanitizer_common/sanitizer_libc.h" #include "dfsan/dfsan.h" +#include using namespace __dfsan; @@ -158,6 +159,20 @@ } } +// Reset labels and shadow memory for dfsan to restart from clean. +// This is intended to work in a single threaded setting (to avoid +// running out of labels in fuzzing). +// This function is not safe to use in multithreaded code or when +// there are active stack frames processing non-zero labels. +extern "C" SANITIZER_INTERFACE_ATTRIBUTE +void dfsan_reset(void) { + // reset label count + atomic_store(&__dfsan_last_label, 0, memory_order_relaxed); + // reset shadow memory + MmapFixedNoReserve(ShadowAddr(), UnusedAddr() - ShadowAddr()); + assert(atomic_load(&__dfsan_last_label, memory_order_relaxed) == 0); +} + // Resolves the union of two unequal labels. Nonequality is a precondition for // this function (the instrumentation pass inlines the equality test). extern "C" SANITIZER_INTERFACE_ATTRIBUTE Index: lib/dfsan/done_abilist.txt =================================================================== --- lib/dfsan/done_abilist.txt +++ lib/dfsan/done_abilist.txt @@ -6,6 +6,8 @@ ############################################################################### fun:dfsan_union=uninstrumented fun:dfsan_union=discard +fun:dfsan_reset=uninstrumented +fun:dfsan_reset=discard fun:dfsan_create_label=uninstrumented fun:dfsan_create_label=discard fun:dfsan_set_label=uninstrumented Index: test/dfsan/reset.cc =================================================================== --- /dev/null +++ test/dfsan/reset.cc @@ -0,0 +1,26 @@ +// RUN: %clang_dfsan %s -o %t && %run %t +// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t + +// Tests that dfsan is reset correctly in single threaded code. + +#include + +#include + +void foo() { + int i = 1; + int j = 1; + dfsan_label i_label = dfsan_create_label("i", 0); + dfsan_set_label(i_label, &i, sizeof(i)); + dfsan_label j_label = dfsan_create_label("j", 0); + dfsan_add_label(j_label, &j, sizeof(j)); +} + +int main(void) { + foo(); + assert(dfsan_get_label_count() == 2); + dfsan_reset(); + assert(dfsan_get_label_count() == 0); + + return 0; +} Index: test/dfsan/reset_multithread.cc =================================================================== --- /dev/null +++ test/dfsan/reset_multithread.cc @@ -0,0 +1,30 @@ +// RUN: %clang_dfsan %s -o %t && %run %t +// RUN: %clang_dfsan -mllvm -dfsan-args-abi %s -o %t && %run %t +// XFAIL: * +// Tests that dfsan runtime is reset can be violated in multithreaded settings. + +#include + +#include +#include + +void *baz(void* unused) { + for(int i = 0; i < 1000000000; i++) { + for(int k = 0; k < 100; k++) { + int j = 1; + dfsan_label j_label = dfsan_create_label("j", 0); + dfsan_set_label(j_label, &j, sizeof(j)); + } + dfsan_reset(); + assert(dfsan_get_label_count() == 0); + } +} + +int main(void) { + pthread_t t1, t2; + pthread_create(&t1, NULL, baz, NULL); + pthread_create(&t2, NULL, baz, NULL); + pthread_join(t1, NULL); + pthread_join(t2, NULL); + return 0; +}