[compiler-rt] r248325 - [asan] Versioned interceptor for pthread_create.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 22 14:34:45 PDT 2015


Author: eugenis
Date: Tue Sep 22 16:34:44 2015
New Revision: 248325

URL: http://llvm.org/viewvc/llvm-project?rev=248325&view=rev
Log:
[asan] Versioned interceptor for pthread_create.

This fixes a crash in pthread_create on linux/i386 due to abi
incompatibility between intercepted and non-intercepted functions.

See the test case for more details.

Added:
    compiler-rt/trunk/test/asan/TestCases/Linux/pthread_create_version.cc
Modified:
    compiler-rt/trunk/lib/asan/asan_interceptors.cc
    compiler-rt/trunk/lib/asan/asan_interceptors.h
    compiler-rt/trunk/lib/interception/interception_linux.h

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.cc?rev=248325&r1=248324&r2=248325&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.cc Tue Sep 22 16:34:44 2015
@@ -27,6 +27,10 @@
 #include "sanitizer_common/sanitizer_posix.h"
 #endif
 
+#if defined(__i386) && SANITIZER_LINUX
+#define ASAN_PTHREAD_CREATE_VERSION "GLIBC_2.1"
+#endif
+
 namespace __asan {
 
 // Return true if we can quickly decide that the region is unpoisoned.
@@ -791,7 +795,11 @@ void InitializeAsanInterceptors() {
 
   // Intercept threading-related functions
 #if ASAN_INTERCEPT_PTHREAD_CREATE
+#if defined(ASAN_PTHREAD_CREATE_VERSION)
+  ASAN_INTERCEPT_FUNC_VER(pthread_create, ASAN_PTHREAD_CREATE_VERSION);
+#else
   ASAN_INTERCEPT_FUNC(pthread_create);
+#endif
   ASAN_INTERCEPT_FUNC(pthread_join);
 #endif
 

Modified: compiler-rt/trunk/lib/asan/asan_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/asan/asan_interceptors.h?rev=248325&r1=248324&r2=248325&view=diff
==============================================================================
--- compiler-rt/trunk/lib/asan/asan_interceptors.h (original)
+++ compiler-rt/trunk/lib/asan/asan_interceptors.h Tue Sep 22 16:34:44 2015
@@ -98,6 +98,12 @@ DECLARE_REAL(int, sigaction, int signum,
     if ((!INTERCEPT_FUNCTION(name) || !REAL(name)))                      \
       VReport(1, "AddressSanitizer: failed to intercept '" #name "'\n"); \
   } while (0)
+#define ASAN_INTERCEPT_FUNC_VER(name, ver)                                     \
+  do {                                                                         \
+    if ((!INTERCEPT_FUNCTION_VER(name, ver) || !REAL(name)))                   \
+      VReport(                                                                 \
+          1, "AddressSanitizer: failed to intercept '" #name "@@" #ver "'\n"); \
+  } while (0)
 #else
 // OS X interceptors don't need to be initialized with INTERCEPT_FUNCTION.
 #define ASAN_INTERCEPT_FUNC(name)

Modified: compiler-rt/trunk/lib/interception/interception_linux.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/interception/interception_linux.h?rev=248325&r1=248324&r2=248325&view=diff
==============================================================================
--- compiler-rt/trunk/lib/interception/interception_linux.h (original)
+++ compiler-rt/trunk/lib/interception/interception_linux.h Tue Sep 22 16:34:44 2015
@@ -35,12 +35,12 @@ void *GetFuncAddrVer(const char *func_na
       (::__interception::uptr) & WRAP(func))
 
 #if !defined(__ANDROID__)  // android does not have dlvsym
-# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
-     ::__interception::real_##func = (func##_f)(unsigned long) \
-         ::__interception::GetFuncAddrVer(#func, symver)
+#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+  (::__interception::real_##func = (func##_f)(                \
+       unsigned long)::__interception::GetFuncAddrVer(#func, symver))
 #else
-# define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
-     INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
+#define INTERCEPT_FUNCTION_VER_LINUX_OR_FREEBSD(func, symver) \
+  INTERCEPT_FUNCTION_LINUX_OR_FREEBSD(func)
 #endif  // !defined(__ANDROID__)
 
 #endif  // INTERCEPTION_LINUX_H

Added: compiler-rt/trunk/test/asan/TestCases/Linux/pthread_create_version.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/pthread_create_version.cc?rev=248325&view=auto
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/pthread_create_version.cc (added)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/pthread_create_version.cc Tue Sep 22 16:34:44 2015
@@ -0,0 +1,23 @@
+// RUN: %clangxx_asan -std=c++11 %s -o %t && %run %t 2>&1
+// Regression test for the versioned pthread_create interceptor on linux/i386.
+// pthread_attr_init is not intercepted and binds to the new abi
+// pthread_create is intercepted; dlsym always returns the oldest version.
+// This results in a crash inside pthread_create in libc.
+
+#include <pthread.h>
+#include <stdlib.h>
+
+void *ThreadFunc(void *) { return nullptr; }
+
+int main() {
+  pthread_t t;
+  const size_t sz = 1024 * 1024;
+  void *p = malloc(sz);
+  pthread_attr_t attr;
+  pthread_attr_init(&attr);
+  pthread_attr_setstack(&attr, p, sz);
+  pthread_create(&t, &attr, ThreadFunc, nullptr);
+  pthread_join(t, nullptr);
+  free(p);
+  return 0;
+}




More information about the llvm-commits mailing list