[compiler-rt] 1db68fc - tsan: fix mmap atomicity

Dmitry Vyukov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 24 00:47:52 PDT 2021


Author: Dmitry Vyukov
Date: 2021-06-24T09:47:44+02:00
New Revision: 1db68fcd8e76dc6437f028c8ace408aa7d04e647

URL: https://github.com/llvm/llvm-project/commit/1db68fcd8e76dc6437f028c8ace408aa7d04e647
DIFF: https://github.com/llvm/llvm-project/commit/1db68fcd8e76dc6437f028c8ace408aa7d04e647.diff

LOG: tsan: fix mmap atomicity

Mmap interceptor is not atomic in the sense that it
exposes unmapped shadow for a brief period of time.
This breaks programs that mmap over another mmap
and access the region concurrently.
Don't unmap shadow in the mmap interceptor to fix this.
Just mapping new shadow on top should be enough to zero it.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D104593

Added: 
    compiler-rt/test/tsan/mmap_stress2.cpp

Modified: 
    compiler-rt/lib/tsan/rtl/tsan_rtl.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
index 0efa99788abe6..d3fde2ad24c4e 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_rtl.cpp
@@ -999,7 +999,6 @@ static void MemoryRangeSet(ThreadState *thr, uptr pc, uptr addr, uptr size,
     // Reset middle part.
     u64 *p1 = p;
     p = RoundDown(end, kPageSize);
-    UnmapOrDie((void*)p1, (uptr)p - (uptr)p1);
     if (!MmapFixedSuperNoReserve((uptr)p1, (uptr)p - (uptr)p1))
       Die();
     // Set the ending.

diff  --git a/compiler-rt/test/tsan/mmap_stress2.cpp b/compiler-rt/test/tsan/mmap_stress2.cpp
new file mode 100644
index 0000000000000..23ff8318519a0
--- /dev/null
+++ b/compiler-rt/test/tsan/mmap_stress2.cpp
@@ -0,0 +1,51 @@
+// RUN: %clang_tsan -O1 %s -o %t && %env_tsan_opts=report_atomic_races=0 %run %t 2>&1 | FileCheck %s
+// This test exposed non-atomicity in mmap interceptor
+// which made shadow for the region temporarily unmapped.
+// This resulted in crashes in the Accesser thread.
+#include "test.h"
+#include <errno.h>
+#include <sys/mman.h>
+
+// The size needs to be large enough to trigger
+// large region optimization in the runtime.
+const size_t kMmapSize = 16 << 20;
+
+void *Remapper(void *arg) {
+  for (;;) {
+    void *p = mmap(arg, kMmapSize, PROT_READ | PROT_WRITE,
+                   MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
+    if (p == MAP_FAILED)
+      exit(printf("mmap failed: %d\n", errno));
+  }
+  return 0;
+}
+
+void *Accesser(void *arg) {
+  unsigned rnd = time(0);
+  for (;;) {
+    int index = rand_r(&rnd) % kMmapSize;
+    char *p = &((char *)arg)[index];
+    __atomic_fetch_add(p, 1, __ATOMIC_ACQ_REL);
+  }
+  return 0;
+}
+
+int main() {
+  void *p = mmap(0, kMmapSize, PROT_READ | PROT_WRITE,
+                 MAP_PRIVATE | MAP_ANON, -1, 0);
+  if (p == MAP_FAILED)
+    exit(printf("mmap failed: %d\n", errno));
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+  pthread_t th[2];
+  if (pthread_create(&th[0], &attr, Remapper, p))
+    exit(printf("pthread_create failed: %d\n", errno));
+  if (pthread_create(&th[1], &attr, Accesser, p))
+    exit(printf("pthread_create failed: %d\n", errno));
+  pthread_attr_destroy(&attr);
+  sleep(3);
+  fprintf(stderr, "DONE\n");
+}
+
+// CHECK: DONE


        


More information about the llvm-commits mailing list