[compiler-rt] r334703 - [ASAN] fix startup crash in dlsym for long paths since glibc 2.27

Peter Wu via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 14 03:42:54 PDT 2018


Author: lekensteyn
Date: Thu Jun 14 03:42:54 2018
New Revision: 334703

URL: http://llvm.org/viewvc/llvm-project?rev=334703&view=rev
Log:
[ASAN] fix startup crash in dlsym for long paths since glibc 2.27

Summary:
Error messages for dlsym used to be stored on the stack, but since
commit 2449ae7b ("ld.so: Introduce struct dl_exception") in glibc 2.27
these are now stored on the heap (and thus use the dlsym alloc pool).

Messages look like "undefined symbol: __isoc99_printf\0/path/to/a.out".
With many missing library functions and long object paths, the pool is
quickly exhausted. Implement a simple mechanism to return freed memory
to the pool (clear it in case it is used for calloc).

Fixes https://github.com/google/sanitizers/issues/957

Reviewed By: vitalybuka

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

Added:
    compiler-rt/trunk/test/asan/TestCases/long-object-path.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_malloc_linux.cc

Modified: compiler-rt/trunk/lib/asan/asan_malloc_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_malloc_linux.cc?rev=334703&r1=334702&r2=334703&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_malloc_linux.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_malloc_linux.cc Thu Jun 14 03:42:54 2018
@@ -31,6 +31,7 @@
 using namespace __asan;  // NOLINT
 
 static uptr allocated_for_dlsym;
+static uptr last_dlsym_alloc_size_in_words;
 static const uptr kDlsymAllocPoolSize = SANITIZER_RTEMS ? 4096 : 1024;
 static uptr alloc_memory_for_dlsym[kDlsymAllocPoolSize];
 
@@ -42,11 +43,25 @@ static INLINE bool IsInDlsymAllocPool(co
 static void *AllocateFromLocalPool(uptr size_in_bytes) {
   uptr size_in_words = RoundUpTo(size_in_bytes, kWordSize) / kWordSize;
   void *mem = (void*)&alloc_memory_for_dlsym[allocated_for_dlsym];
+  last_dlsym_alloc_size_in_words = size_in_words;
   allocated_for_dlsym += size_in_words;
   CHECK_LT(allocated_for_dlsym, kDlsymAllocPoolSize);
   return mem;
 }
 
+static void DeallocateFromLocalPool(const void *ptr) {
+  // Hack: since glibc 2.27, dlsym longer use stack-allocated memory to store
+  // error messages and instead use malloc followed by free. To avoid pool
+  // exhaustion due to long object filenames, handle that special case here.
+  uptr prev_offset = allocated_for_dlsym - last_dlsym_alloc_size_in_words;
+  void *prev_mem = (void*)&alloc_memory_for_dlsym[prev_offset];
+  if (prev_mem == ptr) {
+    REAL(memset)(prev_mem, 0, last_dlsym_alloc_size_in_words * kWordSize);
+    allocated_for_dlsym = prev_offset;
+    last_dlsym_alloc_size_in_words = 0;
+  }
+}
+
 static int PosixMemalignFromLocalPool(void **memptr, uptr alignment,
                                       uptr size_in_bytes) {
   if (UNLIKELY(!CheckPosixMemalignAlignment(alignment)))
@@ -107,8 +122,10 @@ static void *ReallocFromLocalPool(void *
 
 INTERCEPTOR(void, free, void *ptr) {
   GET_STACK_TRACE_FREE;
-  if (UNLIKELY(IsInDlsymAllocPool(ptr)))
+  if (UNLIKELY(IsInDlsymAllocPool(ptr))) {
+    DeallocateFromLocalPool(ptr);
     return;
+  }
   asan_free(ptr, &stack, FROM_MALLOC);
 }
 

Added: compiler-rt/trunk/test/asan/TestCases/long-object-path.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/long-object-path.cc?rev=334703&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/long-object-path.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/long-object-path.cc Thu Jun 14 03:42:54 2018
@@ -0,0 +1,7 @@
+// RUN: mkdir -p %T/a-long-directory-name-to-test-allocations-for-exceptions-in-_dl_lookup_symbol_x-since-glibc-2.27
+// RUN: %clangxx_asan -g %s -o %T/long-object-path
+// RUN: %run %T/a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../a-*/../long-object-path
+
+int main(void) {
+    return 0;
+}




More information about the llvm-commits mailing list