[PATCH] D53528: [sanitizer] Avoid calling a nullptr in MonotonicNanoTime if interceptors are not yet initialized

Kuba (Brecka) Mracek via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Mon Oct 22 13:50:11 PDT 2018


kubamracek created this revision.
kubamracek added reviewers: cryptoad, alekseyshl, krytarowski.
kubamracek added a project: Sanitizers.
Herald added a subscriber: Sanitizers.

I'm seeing a TSan startup crash on Linux when used in Swift programs, where MonotonicNanoTime will try to call real_clock_gettime and then jump to NULL because interceptors are not yet initialized. Attaching the backtrace of how that happens below. This is on Ubuntu 18.04. Looks like TSan's main Initialize() function is called at a point where __progname is already set, but interceptors aren't yet set up.

  * thread #1, name = 'hello', stop reason = signal SIGSEGV: invalid address 
    * frame #0: 0x0000000000000000
      frame #1: 0x00005555555dbf0a ::real_clock_gettime
      frame #2: 0x00005555555b14f0 __sanitizer::MonotonicNanoTime
      frame #3: 0x000055555562d430 __sanitizer::SizeClassAllocator64<...>::PopulateFreeArray
      frame #4: 0x000055555562d161 __sanitizer::SizeClassAllocator64<...>::GetFromAllocator
      frame #5: 0x000055555562cf5d __sanitizer::SizeClassAllocator64LocalCache<...>::Refill
      frame #6: 0x000055555562c845 __sanitizer::SizeClassAllocator64LocalCache<...>::Allocate
      frame #7: 0x0000555555629e75 __sanitizer::CombinedAllocator<...>::Allocate
      frame #8: 0x0000555555628c02 __tsan::user_alloc_internal
      frame #9: 0x0000555555629168 __tsan::user_calloc
      frame #10: 0x00005555555c7a78 ::__interceptor_calloc
      frame #11: 0x00007ffff6ded7e5 libdl.so.2`___lldb_unnamed_symbol11$$libdl.so.2 + 277
      frame #12: 0x00007ffff6ded166 libdl.so.2`dlsym + 118
      frame #13: 0x00005555556317b8 __interception::GetRealFunctionAddress
      frame #14: 0x0000555555601c7c InitializeCommonInterceptors
      frame #15: 0x0000555555600b6a __tsan::InitializeInterceptors
      frame #16: 0x000055555555cc71 __tsan::Initialize
      frame #17: 0x00005555555c6340 __tsan::ScopedInterceptor::ScopedInterceptor
      frame #18: 0x00005555555c6f18 ::__interceptor___cxa_atexit
      frame #19: 0x00007ffff6af22e6 libstdc++.so.6`___lldb_unnamed_symbol241$$libstdc++.so.6 + 70
      frame #20: 0x00007ffff7de5733 ld-linux-x86-64.so.2`___lldb_unnamed_symbol50$$ld-linux-x86-64.so.2 + 259
      frame #21: 0x00007ffff7dd60ca ld-linux-x86-64.so.2`___lldb_unnamed_symbol4$$ld-linux-x86-64.so.2 + 105


Repository:
  rCRT Compiler Runtime

https://reviews.llvm.org/D53528

Files:
  lib/sanitizer_common/sanitizer_linux_libcdep.cc


Index: lib/sanitizer_common/sanitizer_linux_libcdep.cc
===================================================================
--- lib/sanitizer_common/sanitizer_linux_libcdep.cc
+++ lib/sanitizer_common/sanitizer_linux_libcdep.cc
@@ -770,11 +770,14 @@
 // vDSO function pointers haven't been initialized yet. __progname is
 // initialized after the vDSO function pointers, so if it exists, is not null
 // and is not empty, we can use clock_gettime.
+namespace __interception { int (*real_clock_gettime)(u32 clk_id, void *tp); }
 extern "C" SANITIZER_WEAK_ATTRIBUTE char *__progname;
 INLINE bool CanUseVDSO() {
   // Bionic is safe, it checks for the vDSO function pointers to be initialized.
   if (SANITIZER_ANDROID)
     return true;
+  if (!__interception::real_clock_gettime)
+    return false;
   if (&__progname && __progname && *__progname)
     return true;
   return false;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D53528.170488.patch
Type: text/x-patch
Size: 882 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20181022/f178215a/attachment.bin>


More information about the llvm-commits mailing list