[compiler-rt] r195914 - tsan: add support for passing file descriptors over UNIX domain sockets

Dmitry Vyukov dvyukov at google.com
Thu Nov 28 01:09:43 PST 2013


Author: dvyukov
Date: Thu Nov 28 03:09:42 2013
New Revision: 195914

URL: http://llvm.org/viewvc/llvm-project?rev=195914&view=rev
Log:
tsan: add support for passing file descriptors over UNIX domain sockets

tsan was missing new fd's arrived from recvmsg(),
and thus was reporting false positives due to missed synchronization on the fd's


Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.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=195914&r1=195913&r2=195914&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Thu Nov 28 03:09:42 2013
@@ -25,6 +25,7 @@
 //   COMMON_INTERCEPTOR_MUTEX_UNLOCK
 //   COMMON_INTERCEPTOR_MUTEX_REPAIR
 //   COMMON_INTERCEPTOR_SET_PTHREAD_NAME
+//   COMMON_INTERCEPTOR_HANDLE_RECVMSG
 //===----------------------------------------------------------------------===//
 #include "interception/interception.h"
 #include "sanitizer_platform_interceptors.h"
@@ -55,6 +56,10 @@
 #define COMMON_INTERCEPTOR_MUTEX_REPAIR(ctx, m) {}
 #endif
 
+#ifndef COMMON_INTERCEPTOR_HANDLE_RECVMSG
+#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) ((void)(msg))
+#endif
+
 #if SANITIZER_INTERCEPT_STRCMP
 static inline int CharCmpX(unsigned char c1, unsigned char c2) {
   return (c1 == c2) ? 0 : (c1 < c2) ? -1 : 1;
@@ -1402,7 +1407,10 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, st
   SSIZE_T res = REAL(recvmsg)(fd, msg, flags);
   if (res >= 0) {
     if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
-    if (msg) write_msghdr(ctx, msg, res);
+    if (msg) {
+      write_msghdr(ctx, msg, res);
+      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg);
+    }
   }
   return res;
 }

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=195914&r1=195913&r2=195914&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Thu Nov 28 03:09:42 2013
@@ -1834,6 +1834,14 @@ struct TsanInterceptorContext {
   const uptr pc;
 };
 
+static void HandleRecvmsg(ThreadState *thr, uptr pc,
+    __sanitizer_msghdr *msg) {
+  int fds[64];
+  int cnt = ExtractRecvmsgFDs(msg, fds, ARRAY_SIZE(fds));
+  for (int i = 0; i < cnt; i++)
+    FdEventCreate(thr, pc, fds[i]);
+}
+
 #include "sanitizer_common/sanitizer_platform_interceptors.h"
 // Causes interceptor recursion (getpwuid_r() calls fopen())
 #undef SANITIZER_INTERCEPT_GETPWNAM_AND_FRIENDS
@@ -1900,6 +1908,10 @@ struct TsanInterceptorContext {
   MutexRepair(((TsanInterceptorContext *)ctx)->thr, \
             ((TsanInterceptorContext *)ctx)->pc, (uptr)m)
 
+#define COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, msg) \
+  HandleRecvmsg(((TsanInterceptorContext *)ctx)->thr, \
+      ((TsanInterceptorContext *)ctx)->pc, msg)
+
 #include "sanitizer_common/sanitizer_common_interceptors.inc"
 
 #define TSAN_SYSCALL() \

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h?rev=195914&r1=195913&r2=195914&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform.h Thu Nov 28 03:09:42 2013
@@ -162,6 +162,7 @@ void internal_start_thread(void(*func)(v
 // Guesses with high probability, may yield both false positives and negatives.
 bool IsGlobalVar(uptr addr);
 int ExtractResolvFDs(void *state, int *fds, int nfd);
+int ExtractRecvmsgFDs(void *msg, int *fds, int nfd);
 
 }  // namespace __tsan
 

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc?rev=195914&r1=195913&r2=195914&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_platform_linux.cc Thu Nov 28 03:09:42 2013
@@ -34,6 +34,7 @@
 #include <sys/mman.h>
 #include <sys/prctl.h>
 #include <sys/syscall.h>
+#include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/types.h>
 #include <sys/resource.h>
@@ -347,6 +348,9 @@ bool IsGlobalVar(uptr addr) {
 }
 
 #ifndef TSAN_GO
+// Extract file descriptors passed to glibc internal __res_iclose function.
+// This is required to properly "close" the fds, because we do not see internal
+// closes within glibc. The code is a pure hack.
 int ExtractResolvFDs(void *state, int *fds, int nfd) {
   int cnt = 0;
   __res_state *statp = (__res_state*)state;
@@ -356,6 +360,26 @@ int ExtractResolvFDs(void *state, int *f
   }
   return cnt;
 }
+
+// Extract file descriptors passed via UNIX domain sockets.
+// This is requried to properly handle "open" of these fds.
+// see 'man recvmsg' and 'man 3 cmsg'.
+int ExtractRecvmsgFDs(void *msgp, int *fds, int nfd) {
+  int res = 0;
+  msghdr *msg = (msghdr*)msgp;
+  struct cmsghdr *cmsg = CMSG_FIRSTHDR(msg);
+  for (; cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) {
+    if (cmsg->cmsg_level != SOL_SOCKET || cmsg->cmsg_type != SCM_RIGHTS)
+      continue;
+    int n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(fds[0]);
+    for (int i = 0; i < n; i++) {
+      fds[res++] = ((int*)CMSG_DATA(cmsg))[i];
+      if (res == nfd)
+        return res;
+    }
+  }
+  return res;
+}
 #endif
 
 





More information about the llvm-commits mailing list