[compiler-rt] bbb90fe - [tsan] Fix ASLR edge case, and improve diagnostics (#97125)

via llvm-commits llvm-commits at lists.llvm.org
Thu Jul 11 08:25:46 PDT 2024


Author: Thurston Dang
Date: 2024-07-11T08:25:41-07:00
New Revision: bbb90feb8742b4a83c4bbfbbbdf0f9735939d184

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

LOG: [tsan] Fix ASLR edge case, and improve diagnostics (#97125)

In extremely rare cases (estimated 1 in 3 million), minor allocations
that happen after the memory layout was checked in
InitializePlatformEarly() [1] may result in the memory layout
unexpectedly being incompatible in InitializePlatform(). We fix this by
adding another memory layout check (and opportunity to re-exec without
ASLR) in InitializePlatform().

To improve future debuggability, this patch also dumps the process map
if the memory layout is unexpectedly incompatible.

[1]
```
 __sanitizer::InitializePlatformEarly();
  __tsan::InitializePlatformEarly();

#if !SANITIZER_GO
  InitializeAllocator(); // <-- ~8MB mmap'ed
  ReplaceSystemMalloc();
#endif
  if (common_flags()->detect_deadlocks)
    ctx->dd = DDetector::Create(flags()); // <-- ~4MB mmap'ed
  Processor *proc = ProcCreate(); // <-- ~1MB mmap'ed
  ProcWire(proc, thr);
  InitializeInterceptors(); <-- ~3MB mmap'ed
  InitializePlatform();
```

Added: 
    

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

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
index c723dba556ed2..621c679a05db4 100644
--- a/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
+++ b/compiler-rt/lib/tsan/rtl/tsan_platform_linux.cpp
@@ -215,7 +215,7 @@ void InitializeShadowMemoryPlatform() {
 #endif  // #if !SANITIZER_GO
 
 #  if !SANITIZER_GO
-static void ReExecIfNeeded() {
+static void ReExecIfNeeded(bool ignore_heap) {
   // Go maps shadow memory lazily and works fine with limited address space.
   // Unlimited stack is not a problem as well, because the executable
   // is not compiled with -pie.
@@ -266,7 +266,7 @@ static void ReExecIfNeeded() {
 
   if (reexec) {
     // Don't check the address space since we're going to re-exec anyway.
-  } else if (!CheckAndProtect(false, false, false)) {
+  } else if (!CheckAndProtect(false, ignore_heap, false)) {
     // ASLR personality check.
     // N.B. 'personality' is sometimes forbidden by sandboxes, so we only call
     // this as a last resort (when the memory mapping is incompatible and TSan
@@ -290,10 +290,11 @@ static void ReExecIfNeeded() {
       CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1);
       reexec = true;
     } else {
-      VReport(1,
-              "FATAL: ThreadSanitizer: memory layout is incompatible, "
-              "even though ASLR is disabled.\n"
-              "Please file a bug.\n");
+      Printf(
+          "FATAL: ThreadSanitizer: memory layout is incompatible, "
+          "even though ASLR is disabled.\n"
+          "Please file a bug.\n");
+      DumpProcessMap();
       Die();
     }
   }
@@ -376,7 +377,8 @@ void InitializePlatformEarly() {
 #  endif
 
 #  if !SANITIZER_GO
-  ReExecIfNeeded();
+  // Heap has not been allocated yet
+  ReExecIfNeeded(false);
 #  endif
 }
 
@@ -394,6 +396,17 @@ void InitializePlatform() {
 #    endif
   }
 
+  // We called ReExecIfNeeded() in InitializePlatformEarly(), but there are
+  // intervening allocations that result in an edge case:
+  // 1) InitializePlatformEarly(): memory layout is compatible
+  // 2) Intervening allocations happen
+  // 3) InitializePlatform(): memory layout is incompatible and fails
+  //    CheckAndProtect()
+#    if !SANITIZER_GO
+  // Heap has already been allocated
+  ReExecIfNeeded(true);
+#    endif
+
   // Earlier initialization steps already re-exec'ed until we got a compatible
   // memory layout, so we don't expect any more issues here.
   if (!CheckAndProtect(true, true, true)) {
@@ -401,6 +414,7 @@ void InitializePlatform() {
         "FATAL: ThreadSanitizer: unexpectedly found incompatible memory "
         "layout.\n");
     Printf("FATAL: Please file a bug.\n");
+    DumpProcessMap();
     Die();
   }
 


        


More information about the llvm-commits mailing list