[compiler-rt] r263641 - [tsan] Detect uses of uninitialized, destroyed and invalid mutexes

Kuba Brecka via llvm-commits llvm-commits at lists.llvm.org
Wed Mar 16 08:39:21 PDT 2016


Author: kuba.brecka
Date: Wed Mar 16 10:39:20 2016
New Revision: 263641

URL: http://llvm.org/viewvc/llvm-project?rev=263641&view=rev
Log:
[tsan] Detect uses of uninitialized, destroyed and invalid mutexes

This patch adds a new TSan report type, ReportTypeMutexInvalidAccess, which is triggered when pthread_mutex_lock or pthread_mutex_unlock returns EINVAL (this means the mutex is invalid, uninitialized or already destroyed).

Differential Revision: http://reviews.llvm.org/D18132


Added:
    compiler-rt/trunk/test/tsan/mutex_lock_destroyed.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Wed Mar 16 10:39:20 2016
@@ -91,6 +91,10 @@
 #define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
 #endif
 
+#ifndef COMMON_INTERCEPTOR_MUTEX_INVALID
+#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) {}
+#endif
+
 #ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
 #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
 #endif
@@ -3346,6 +3350,8 @@ INTERCEPTOR(int, pthread_mutex_lock, voi
     COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m);
   if (res == 0 || res == errno_EOWNERDEAD)
     COMMON_INTERCEPTOR_MUTEX_LOCK(ctx, m);
+  if (res == errno_EINVAL)
+    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
   return res;
 }
 
@@ -3353,7 +3359,10 @@ INTERCEPTOR(int, pthread_mutex_unlock, v
   void *ctx;
   COMMON_INTERCEPTOR_ENTER(ctx, pthread_mutex_unlock, m);
   COMMON_INTERCEPTOR_MUTEX_UNLOCK(ctx, m);
-  return REAL(pthread_mutex_unlock)(m);
+  int res = REAL(pthread_mutex_unlock)(m);
+  if (res == errno_EINVAL)
+    COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m);
+  return res;
 }
 
 #define INIT_PTHREAD_MUTEX_LOCK COMMON_INTERCEPT_FUNCTION(pthread_mutex_lock)

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_debugging.cc Wed Mar 16 10:39:20 2016
@@ -25,6 +25,7 @@ static const char *ReportTypeDescription
   if (typ == ReportTypeThreadLeak) return "thread-leak";
   if (typ == ReportTypeMutexDestroyLocked) return "locked-mutex-destroy";
   if (typ == ReportTypeMutexDoubleLock) return "mutex-double-lock";
+  if (typ == ReportTypeMutexInvalidAccess) return "mutex-invalid-access";
   if (typ == ReportTypeMutexBadUnlock) return "mutex-bad-unlock";
   if (typ == ReportTypeMutexBadReadLock) return "mutex-bad-read-lock";
   if (typ == ReportTypeMutexBadReadUnlock) return "mutex-bad-read-unlock";

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Wed Mar 16 10:39:20 2016
@@ -2409,6 +2409,10 @@ static void HandleRecvmsg(ThreadState *t
   MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
             ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
 
+#define COMMON_INTERCEPTOR_MUTEX_INVALID(ctx, m) \
+  MutexInvalidAccess(((TsanInterceptorContext *)ctx)->thr, \
+                     ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
+
 #if !SANITIZER_MAC
 #define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
   HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.cc Wed Mar 16 10:39:20 2016
@@ -96,6 +96,8 @@ static const char *ReportTypeString(Repo
     return "destroy of a locked mutex";
   if (typ == ReportTypeMutexDoubleLock)
     return "double lock of a mutex";
+  if (typ == ReportTypeMutexInvalidAccess)
+    return "use of an invalid mutex (e.g. uninitialized or destroyed)";
   if (typ == ReportTypeMutexBadUnlock)
     return "unlock of an unlocked mutex (or by a wrong thread)";
   if (typ == ReportTypeMutexBadReadLock)

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_report.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_report.h?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_report.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_report.h Wed Mar 16 10:39:20 2016
@@ -27,6 +27,7 @@ enum ReportType {
   ReportTypeThreadLeak,
   ReportTypeMutexDestroyLocked,
   ReportTypeMutexDoubleLock,
+  ReportTypeMutexInvalidAccess,
   ReportTypeMutexBadUnlock,
   ReportTypeMutexBadReadLock,
   ReportTypeMutexBadReadUnlock,

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl.h Wed Mar 16 10:39:20 2016
@@ -695,6 +695,7 @@ void MutexReadLock(ThreadState *thr, upt
 void MutexReadUnlock(ThreadState *thr, uptr pc, uptr addr);
 void MutexReadOrWriteUnlock(ThreadState *thr, uptr pc, uptr addr);
 void MutexRepair(ThreadState *thr, uptr pc, uptr addr);  // call on EOWNERDEAD
+void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr);
 
 void Acquire(ThreadState *thr, uptr pc, uptr addr);
 // AcquireGlobal synchronizes the current thread with all other threads.

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_rtl_mutex.cc Wed Mar 16 10:39:20 2016
@@ -350,6 +350,14 @@ void MutexRepair(ThreadState *thr, uptr
   s->mtx.Unlock();
 }
 
+void MutexInvalidAccess(ThreadState *thr, uptr pc, uptr addr) {
+  DPrintf("#%d: MutexInvalidAccess %zx\n", thr->tid, addr);
+  SyncVar *s = ctx->metamap.GetOrCreateAndLock(thr, pc, addr, true);
+  u64 mid = s->GetId();
+  s->mtx.Unlock();
+  ReportMutexMisuse(thr, pc, ReportTypeMutexInvalidAccess, addr, mid);
+}
+
 void Acquire(ThreadState *thr, uptr pc, uptr addr) {
   DPrintf("#%d: Acquire %zx\n", thr->tid, addr);
   if (thr->ignore_sync)

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc?rev=263641&r1=263640&r2=263641&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_suppressions.cc Wed Mar 16 10:39:20 2016
@@ -80,6 +80,8 @@ static const char *conv(ReportType typ)
     return kSuppressionMutex;
   else if (typ == ReportTypeMutexDoubleLock)
     return kSuppressionMutex;
+  else if (typ == ReportTypeMutexInvalidAccess)
+    return kSuppressionMutex;
   else if (typ == ReportTypeMutexBadUnlock)
     return kSuppressionMutex;
   else if (typ == ReportTypeMutexBadReadLock)

Added: compiler-rt/trunk/test/tsan/mutex_lock_destroyed.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/tsan/mutex_lock_destroyed.cc?rev=263641&view=auto
==============================================================================
--- compiler-rt/trunk/test/tsan/mutex_lock_destroyed.cc (added)
+++ compiler-rt/trunk/test/tsan/mutex_lock_destroyed.cc Wed Mar 16 10:39:20 2016
@@ -0,0 +1,25 @@
+// RUN: %clangxx_tsan %s -o %t
+// RUN: %deflake %run %t | FileCheck %s
+// RUN: %deflake %run %t 1 | FileCheck %s
+
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+int main(int argc, char *argv[]) {
+  pthread_mutex_t *m = (pthread_mutex_t *)malloc(sizeof(pthread_mutex_t));
+  pthread_mutex_init(m, 0);
+  pthread_mutex_lock(m);
+  pthread_mutex_unlock(m);
+  pthread_mutex_destroy(m);
+
+  if (argc > 1 && argv[1][0] == '1')
+    free(m);
+
+  pthread_mutex_lock(m);
+  // CHECK: WARNING: ThreadSanitizer: use of an invalid mutex (e.g. uninitialized or destroyed)
+  // CHECK:   #0 pthread_mutex_lock
+  // CHECK:   #1 main {{.*}}mutex_lock_destroyed.cc:[[@LINE-3]]
+
+  return 0;
+}




More information about the llvm-commits mailing list