[compiler-rt] r272980 - [msan] Intercept send/sendto/sendmsg.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Thu Jun 16 17:43:12 PDT 2016


Author: eugenis
Date: Thu Jun 16 19:43:11 2016
New Revision: 272980

URL: http://llvm.org/viewvc/llvm-project?rev=272980&view=rev
Log:
[msan] Intercept send/sendto/sendmsg.

send/sendmsg moved from tsan to sanitizer_common; sendto is new.

Added:
    compiler-rt/trunk/test/msan/Linux/sendmsg.cc
Modified:
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
    compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc
    compiler-rt/trunk/test/asan/TestCases/Linux/recvfrom.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=272980&r1=272979&r2=272980&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Thu Jun 16 19:43:11 2016
@@ -2498,6 +2498,37 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, st
 #define INIT_RECVMSG
 #endif
 
+#if SANITIZER_INTERCEPT_SENDMSG
+static void read_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
+                        SSIZE_T maxlen) {
+  COMMON_INTERCEPTOR_READ_RANGE(ctx, msg, sizeof(*msg));
+  if (msg->msg_name && msg->msg_namelen)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_name, msg->msg_namelen);
+  if (msg->msg_iov && msg->msg_iovlen)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_iov,
+                                  sizeof(*msg->msg_iov) * msg->msg_iovlen);
+  read_iovec(ctx, msg->msg_iov, msg->msg_iovlen, maxlen);
+  if (msg->msg_control && msg->msg_controllen)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, msg->msg_control, msg->msg_controllen);
+}
+
+INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
+            int flags) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, sendmsg, fd, msg, flags);
+  if (fd >= 0) {
+    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+  }
+  SSIZE_T res = REAL(sendmsg)(fd, msg, flags);
+  if (res >= 0 && msg) read_msghdr(ctx, msg, res);
+  return res;
+}
+#define INIT_SENDMSG COMMON_INTERCEPT_FUNCTION(sendmsg);
+#else
+#define INIT_SENDMSG
+#endif
+
 #if SANITIZER_INTERCEPT_GETPEERNAME
 INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
   void *ctx;
@@ -5529,6 +5560,39 @@ INTERCEPTOR(SSIZE_T, recvfrom, int fd, v
 #define INIT_RECV_RECVFROM
 #endif
 
+#if SANITIZER_INTERCEPT_SEND_SENDTO
+INTERCEPTOR(SSIZE_T, send, int fd, void *buf, SIZE_T len, int flags) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, send, fd, buf, len, flags);
+  if (fd >= 0) {
+    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+  }
+  SSIZE_T res = REAL(send)(fd, buf, len, flags);
+  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
+  return res;
+}
+
+INTERCEPTOR(SSIZE_T, sendto, int fd, void *buf, SIZE_T len, int flags,
+            void *srcaddr, int addrlen) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, sendto, fd, buf, len, flags, srcaddr, addrlen);
+  if (fd >= 0) {
+    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+  }
+  if (srcaddr && addrlen) COMMON_INTERCEPTOR_READ_RANGE(ctx, srcaddr, addrlen);
+  SSIZE_T res = REAL(sendto)(fd, buf, len, flags, srcaddr, addrlen);
+  if (res > 0) COMMON_INTERCEPTOR_READ_RANGE(ctx, buf, Min((SIZE_T)res, len));
+  return res;
+}
+#define INIT_SEND_SENDTO           \
+  COMMON_INTERCEPT_FUNCTION(send); \
+  COMMON_INTERCEPT_FUNCTION(sendto);
+#else
+#define INIT_SEND_SENDTO
+#endif
+
 #if SANITIZER_INTERCEPT_STAT
 INTERCEPTOR(int, stat, const char *path, void *buf) {
   void *ctx;
@@ -5684,6 +5748,7 @@ static void InitializeCommonInterceptors
   INIT_ACCEPT4;
   INIT_MODF;
   INIT_RECVMSG;
+  INIT_SENDMSG;
   INIT_GETPEERNAME;
   INIT_IOCTL;
   INIT_INET_ATON;
@@ -5796,6 +5861,7 @@ static void InitializeCommonInterceptors
   INIT_CTERMID;
   INIT_CTERMID_R;
   INIT_RECV_RECVFROM;
+  INIT_SEND_SENDTO;
   INIT_STAT;
   INIT___XSTAT;
   INIT___XSTAT64;

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h?rev=272980&r1=272979&r2=272980&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Thu Jun 16 19:43:11 2016
@@ -155,6 +155,7 @@
 #define SANITIZER_INTERCEPT_ACCEPT4 SI_LINUX_NOT_ANDROID
 #define SANITIZER_INTERCEPT_MODF SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_RECVMSG SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SENDMSG SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_GETPEERNAME SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_IOCTL SI_NOT_WINDOWS
 #define SANITIZER_INTERCEPT_INET_ATON SI_NOT_WINDOWS
@@ -308,6 +309,7 @@
 
 #define SANITIZER_INTERCEPTOR_HOOKS SI_LINUX
 #define SANITIZER_INTERCEPT_RECV_RECVFROM SI_NOT_WINDOWS
+#define SANITIZER_INTERCEPT_SEND_SENDTO SI_NOT_WINDOWS
 
 #define SANITIZER_INTERCEPT_STAT (SI_FREEBSD || SI_MAC || SI_ANDROID)
 #define SANITIZER_INTERCEPT___XSTAT !SANITIZER_INTERCEPT_STAT && SI_NOT_WINDOWS

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=272980&r1=272979&r2=272980&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_interceptors.cc Thu Jun 16 19:43:11 2016
@@ -1615,26 +1615,6 @@ TSAN_INTERCEPTOR(int, pipe2, int *pipefd
 }
 #endif
 
-TSAN_INTERCEPTOR(long_t, send, int fd, void *buf, long_t len, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(send, fd, buf, len, flags);
-  if (fd >= 0) {
-    FdAccess(thr, pc, fd);
-    FdRelease(thr, pc, fd);
-  }
-  int res = REAL(send)(fd, buf, len, flags);
-  return res;
-}
-
-TSAN_INTERCEPTOR(long_t, sendmsg, int fd, void *msg, int flags) {
-  SCOPED_TSAN_INTERCEPTOR(sendmsg, fd, msg, flags);
-  if (fd >= 0) {
-    FdAccess(thr, pc, fd);
-    FdRelease(thr, pc, fd);
-  }
-  int res = REAL(sendmsg)(fd, msg, flags);
-  return res;
-}
-
 TSAN_INTERCEPTOR(int, unlink, char *path) {
   SCOPED_TSAN_INTERCEPTOR(unlink, path);
   Release(thr, pc, File2addr(path));
@@ -2560,9 +2540,6 @@ void InitializeInterceptors() {
   TSAN_INTERCEPT(pipe);
   TSAN_INTERCEPT(pipe2);
 
-  TSAN_INTERCEPT(send);
-  TSAN_INTERCEPT(sendmsg);
-
   TSAN_INTERCEPT(unlink);
   TSAN_INTERCEPT(tmpfile);
   TSAN_MAYBE_INTERCEPT_TMPFILE64;

Modified: compiler-rt/trunk/test/asan/TestCases/Linux/recvfrom.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/asan/TestCases/Linux/recvfrom.cc?rev=272980&r1=272979&r2=272980&view=diff
==============================================================================
--- compiler-rt/trunk/test/asan/TestCases/Linux/recvfrom.cc (original)
+++ compiler-rt/trunk/test/asan/TestCases/Linux/recvfrom.cc Thu Jun 16 19:43:11 2016
@@ -1,6 +1,7 @@
 // Test that ASan detects buffer overflow on read from socket via recvfrom.
 //
-// RUN: %clangxx_asan %s -o %t && not %run %t 2>&1 | FileCheck %s
+// RUN: %clangxx_asan %s -DRECVFROM -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-RECVFROM
+// RUN: %clangxx_asan %s -DSENDTO -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=CHECK-SENDTO
 //
 // UNSUPPORTED: android
 
@@ -25,21 +26,31 @@ const int kBufSize = 10;
 int sockfd;
 
 static void *client_thread_udp(void *data) {
+#ifdef SENDTO
+  const char buf[kBufSize / 2] = {0, };
+#else
   const char buf[kBufSize] = {0, };
+#endif
   struct sockaddr_in serveraddr;
   socklen_t addrlen = sizeof(serveraddr);
 
   int succeeded = getsockname(sockfd, (struct sockaddr *)&serveraddr, &addrlen);
   CHECK_ERROR(succeeded < 0, "in getsockname");
 
-  succeeded = sendto(sockfd, buf, kBufSize, 0,
-                     (struct sockaddr *)&serveraddr, sizeof(serveraddr));
+  succeeded = sendto(sockfd, buf, kBufSize, 0, (struct sockaddr *)&serveraddr,
+                     sizeof(serveraddr));
+  // CHECK-SENDTO: {{READ of size 10 at 0x.* thread T1}}
+  // CHECK-SENDTO: {{    #1 0x.* in client_thread_udp.*recvfrom.cc:}}[[@LINE-3]]
   CHECK_ERROR(succeeded < 0, "in sending message");
   return NULL;
 }
 
 int main() {
+#ifdef RECVFROM
   char buf[kBufSize / 2];
+#else
+  char buf[kBufSize];
+#endif
   pthread_t client_thread;
   struct sockaddr_in serveraddr;
 
@@ -59,10 +70,10 @@ int main() {
   CHECK_ERROR(succeeded, "creating thread");
 
   recvfrom(sockfd, buf, kBufSize, 0, NULL, NULL); // BOOM
-  // CHECK: {{WRITE of size 10 at 0x.* thread T0}}
-  // CHECK: {{    #1 0x.* in main.*recvfrom.cc:}}[[@LINE-2]]
-  // CHECK: {{Address 0x.* is located in stack of thread T0 at offset}}
-  // CHECK-NEXT: in{{.*}}main{{.*}}recvfrom.cc
+  // CHECK-RECVFROM: {{WRITE of size 10 at 0x.* thread T0}}
+  // CHECK-RECVFROM: {{    #1 0x.* in main.*recvfrom.cc:}}[[@LINE-2]]
+  // CHECK-RECVFROM: {{Address 0x.* is located in stack of thread T0 at offset}}
+  // CHECK-RECVFROM-NEXT: in{{.*}}main{{.*}}recvfrom.cc
   succeeded = pthread_join(client_thread, NULL);
   CHECK_ERROR(succeeded, "joining thread");
   return 0;

Added: compiler-rt/trunk/test/msan/Linux/sendmsg.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/Linux/sendmsg.cc?rev=272980&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/Linux/sendmsg.cc (added)
+++ compiler-rt/trunk/test/msan/Linux/sendmsg.cc Thu Jun 16 19:43:11 2016
@@ -0,0 +1,83 @@
+// RUN: %clangxx_msan %s -DSEND -DBUF -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SEND
+// RUN: %clangxx_msan %s -DSENDTO -DBUF -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO
+// RUN: %clangxx_msan %s -DSENDMSG -DBUF -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG
+
+// FIXME: intercept connect() and add a SEND+ADDR test
+// RUN: %clangxx_msan %s -DSENDTO -DADDR -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO-ADDR
+// RUN: %clangxx_msan %s -DSENDMSG -DADDR -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG-ADDR
+
+// RUN: %clangxx_msan %s -DSEND -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
+// RUN: %clangxx_msan %s -DSENDTO -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
+// RUN: %clangxx_msan %s -DSENDMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
+
+// UNSUPPORTED: android
+
+#include <assert.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <netdb.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sanitizer/msan_interface.h>
+
+const int kBufSize = 10;
+int sockfd;
+
+int main() {
+  int ret;
+  char buf[kBufSize] = {0};
+  pthread_t client_thread;
+  struct sockaddr_in serveraddr;
+
+  sockfd = socket(AF_INET, SOCK_DGRAM, 0);
+
+  memset(&serveraddr, 0, sizeof(serveraddr));
+  serveraddr.sin_family = AF_INET;
+  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
+  serveraddr.sin_port = 0;
+
+  bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr));
+  socklen_t addrlen = sizeof(serveraddr);
+  getsockname(sockfd, (struct sockaddr *)&serveraddr, &addrlen);
+
+#if defined(ADDR)
+  assert(addrlen > 3);
+  __msan_poison(((char *)&serveraddr) + 3, 1);
+#elif defined(BUF)
+  __msan_poison(buf + 7, 1);
+#endif
+
+#if defined(SENDMSG)
+  struct iovec iov[2] = {{buf, 5}, {buf + 5, 5}};
+  struct msghdr msg;
+  memset(&msg, 0, sizeof(msg));
+  msg.msg_name = &serveraddr;
+  msg.msg_namelen = addrlen;
+  msg.msg_iov = iov;
+  msg.msg_iovlen = 2;
+#endif
+
+#if defined(SEND)
+  ret = connect(sockfd, (struct sockaddr *)&serveraddr, addrlen);
+  assert(ret == 0);
+  ret = send(sockfd, buf, kBufSize, 0);
+  // SEND: Uninitialized bytes in __interceptor_send at offset 7 inside [{{.*}}, 10)
+  assert(ret > 0);
+#elif defined(SENDTO)
+  ret =
+      sendto(sockfd, buf, kBufSize, 0, (struct sockaddr *)&serveraddr, addrlen);
+  // SENDTO: Uninitialized bytes in __interceptor_sendto at offset 7 inside [{{.*}}, 10)
+  // SENDTO-ADDR: Uninitialized bytes in __interceptor_sendto at offset 3 inside [{{.*}},
+  assert(ret > 0);
+#elif defined(SENDMSG)
+  ret = sendmsg(sockfd, &msg, 0);
+  // SENDMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
+  // SENDMSG-ADDR: Uninitialized bytes in {{.*}} at offset 3 inside [{{.*}},
+  assert(ret > 0);
+#endif
+  fprintf(stderr, "== done\n");
+  // NEGATIVE: == done
+  return 0;
+}




More information about the llvm-commits mailing list