[compiler-rt] r321774 - [msan] Intercept sendmmsg, recvmmsg.

Evgeniy Stepanov via llvm-commits llvm-commits at lists.llvm.org
Wed Jan 3 15:32:15 PST 2018


Author: eugenis
Date: Wed Jan  3 15:32:15 2018
New Revision: 321774

URL: http://llvm.org/viewvc/llvm-project?rev=321774&view=rev
Log:
[msan] Intercept sendmmsg, recvmmsg.

Summary: Extend the sendmsg test to cover all recv*.

Reviewers: vitalybuka

Subscribers: llvm-commits, kubamracek

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

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/sanitizer_common/sanitizer_platform_limits_posix.cc
    compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
    compiler-rt/trunk/test/msan/Linux/sendmsg.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=321774&r1=321773&r2=321774&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Wed Jan  3 15:32:15 2018
@@ -2810,7 +2810,7 @@ INTERCEPTOR(long double, modfl, long dou
 #define INIT_MODF
 #endif
 
-#if SANITIZER_INTERCEPT_RECVMSG
+#if SANITIZER_INTERCEPT_RECVMSG || SANITIZER_INTERCEPT_RECVMMSG
 static void write_msghdr(void *ctx, struct __sanitizer_msghdr *msg,
                          SSIZE_T maxlen) {
   COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg, sizeof(*msg));
@@ -2823,7 +2823,9 @@ static void write_msghdr(void *ctx, stru
   if (msg->msg_control && msg->msg_controllen)
     COMMON_INTERCEPTOR_WRITE_RANGE(ctx, msg->msg_control, msg->msg_controllen);
 }
+#endif
 
+#if SANITIZER_INTERCEPT_RECVMSG
 INTERCEPTOR(SSIZE_T, recvmsg, int fd, struct __sanitizer_msghdr *msg,
             int flags) {
   void *ctx;
@@ -2846,7 +2848,30 @@ INTERCEPTOR(SSIZE_T, recvmsg, int fd, st
 #define INIT_RECVMSG
 #endif
 
-#if SANITIZER_INTERCEPT_SENDMSG
+#if SANITIZER_INTERCEPT_RECVMMSG
+INTERCEPTOR(int, recvmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
+            unsigned int vlen, int flags, void *timeout) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, recvmmsg, fd, msgvec, vlen, flags, timeout);
+  if (timeout) COMMON_INTERCEPTOR_READ_RANGE(ctx, timeout, struct_timespec_sz);
+  int res = REAL(recvmmsg)(fd, msgvec, vlen, flags, timeout);
+  if (res >= 0) {
+    if (fd >= 0) COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd);
+    for (int i = 0; i < res; ++i) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
+                                     sizeof(msgvec[i].msg_len));
+      write_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
+      COMMON_INTERCEPTOR_HANDLE_RECVMSG(ctx, &msgvec[i].msg_hdr);
+    }
+  }
+  return res;
+}
+#define INIT_RECVMMSG COMMON_INTERCEPT_FUNCTION(recvmmsg);
+#else
+#define INIT_RECVMMSG
+#endif
+
+#if SANITIZER_INTERCEPT_SENDMSG || SANITIZER_INTERCEPT_SENDMMSG
 static void read_msghdr_control(void *ctx, void *control, uptr controllen) {
   const unsigned kCmsgDataOffset =
       RoundUpTo(sizeof(__sanitizer_cmsghdr), sizeof(uptr));
@@ -2896,7 +2921,9 @@ static void read_msghdr(void *ctx, struc
   if (msg->msg_control && msg->msg_controllen)
     read_msghdr_control(ctx, msg->msg_control, msg->msg_controllen);
 }
+#endif
 
+#if SANITIZER_INTERCEPT_SENDMSG
 INTERCEPTOR(SSIZE_T, sendmsg, int fd, struct __sanitizer_msghdr *msg,
             int flags) {
   void *ctx;
@@ -2915,6 +2942,30 @@ INTERCEPTOR(SSIZE_T, sendmsg, int fd, st
 #define INIT_SENDMSG
 #endif
 
+#if SANITIZER_INTERCEPT_SENDMMSG
+INTERCEPTOR(int, sendmmsg, int fd, struct __sanitizer_mmsghdr *msgvec,
+            unsigned vlen, int flags) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, sendmmsg, fd, msgvec, vlen, flags);
+  if (fd >= 0) {
+    COMMON_INTERCEPTOR_FD_ACCESS(ctx, fd);
+    COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd);
+  }
+  int res = REAL(sendmmsg)(fd, msgvec, vlen, flags);
+  if (res >= 0 && msgvec)
+    for (int i = 0; i < res; ++i) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, &msgvec[i].msg_len,
+                                     sizeof(msgvec[i].msg_len));
+      if (common_flags()->intercept_send)
+        read_msghdr(ctx, &msgvec[i].msg_hdr, msgvec[i].msg_len);
+    }
+  return res;
+}
+#define INIT_SENDMMSG COMMON_INTERCEPT_FUNCTION(sendmmsg);
+#else
+#define INIT_SENDMMSG
+#endif
+
 #if SANITIZER_INTERCEPT_GETPEERNAME
 INTERCEPTOR(int, getpeername, int sockfd, void *addr, unsigned *addrlen) {
   void *ctx;
@@ -6483,6 +6534,8 @@ static void InitializeCommonInterceptors
   INIT_MODF;
   INIT_RECVMSG;
   INIT_SENDMSG;
+  INIT_RECVMMSG;
+  INIT_SENDMMSG;
   INIT_GETPEERNAME;
   INIT_IOCTL;
   INIT_INET_ATON;

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=321774&r1=321773&r2=321774&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Wed Jan  3 15:32:15 2018
@@ -221,6 +221,8 @@
 #define SANITIZER_INTERCEPT_MODF SI_POSIX
 #define SANITIZER_INTERCEPT_RECVMSG SI_POSIX
 #define SANITIZER_INTERCEPT_SENDMSG SI_POSIX
+#define SANITIZER_INTERCEPT_RECVMMSG SI_LINUX
+#define SANITIZER_INTERCEPT_SENDMMSG SI_LINUX
 #define SANITIZER_INTERCEPT_GETPEERNAME SI_POSIX
 #define SANITIZER_INTERCEPT_IOCTL SI_POSIX
 #define SANITIZER_INTERCEPT_INET_ATON SI_POSIX

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc?rev=321774&r1=321773&r2=321774&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.cc Wed Jan  3 15:32:15 2018
@@ -1026,6 +1026,12 @@ CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_len)
 CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_level);
 CHECK_SIZE_AND_OFFSET(cmsghdr, cmsg_type);
 
+#if SANITIZER_LINUX
+CHECK_TYPE_SIZE(mmsghdr);
+CHECK_SIZE_AND_OFFSET(mmsghdr, msg_hdr);
+CHECK_SIZE_AND_OFFSET(mmsghdr, msg_len);
+#endif
+
 COMPILER_CHECK(sizeof(__sanitizer_dirent) <= sizeof(dirent));
 CHECK_SIZE_AND_OFFSET(dirent, d_ino);
 #if SANITIZER_MAC

Modified: compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h?rev=321774&r1=321773&r2=321774&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_limits_posix.h Wed Jan  3 15:32:15 2018
@@ -482,6 +482,13 @@ namespace __sanitizer {
   };
 #endif
 
+#if SANITIZER_LINUX
+  struct __sanitizer_mmsghdr {
+    __sanitizer_msghdr msg_hdr;
+    unsigned int msg_len;
+  };
+#endif
+
 #if SANITIZER_MAC
   struct __sanitizer_dirent {
     unsigned long long d_ino;

Modified: compiler-rt/trunk/test/msan/Linux/sendmsg.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/Linux/sendmsg.cc?rev=321774&r1=321773&r2=321774&view=diff
==============================================================================
--- compiler-rt/trunk/test/msan/Linux/sendmsg.cc (original)
+++ compiler-rt/trunk/test/msan/Linux/sendmsg.cc Wed Jan  3 15:32:15 2018
@@ -1,10 +1,12 @@
 // RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SEND
 // RUN: %clangxx_msan %s -DSENDTO -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDTO
 // RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMSG
+// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && not %run %t 2>&1 | FileCheck %s --check-prefix=SENDMMSG
 
 // 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
+// RUN: %clangxx_msan %s -DSENDMMSG -o %t && %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
 
 // RUN: %clangxx_msan %s -DSEND -DPOISON -o %t && \
 // RUN:   MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
@@ -12,6 +14,8 @@
 // RUN:   MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
 // RUN: %clangxx_msan %s -DSENDMSG -DPOISON -o %t && \
 // RUN:   MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
+// RUN: %clangxx_msan %s -DSENDMMSG -DPOISON -o %t && \
+// RUN:   MSAN_OPTIONS=intercept_send=0 %run %t 2>&1 | FileCheck %s --check-prefix=NEGATIVE
 
 // UNSUPPORTED: android
 
@@ -20,54 +24,32 @@
 #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;
+const int kRecvBufSize = 100;
+int sockfd[2];
 
 int main() {
   int ret;
+  int sent;
   char buf[kBufSize] = {0};
-  pthread_t client_thread;
-  struct sockaddr_in serveraddr;
-  struct sockaddr_in6 serveraddr6;
-
-  memset(&serveraddr, 0, sizeof(serveraddr));
-  serveraddr.sin_family = AF_INET;
-  serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
-  serveraddr.sin_port = 0;
-  struct sockaddr *addr = (struct sockaddr *)&serveraddr;
-  socklen_t addrlen = sizeof(serveraddr);
-
-  sockfd = socket(addr->sa_family, SOCK_DGRAM, 0);
-  if (sockfd <= 0) {
-    // Try to fall-back to IPv6
-    memset(&serveraddr6, 0, sizeof(serveraddr6));
-    serveraddr6.sin6_family = AF_INET6;
-    serveraddr6.sin6_addr = in6addr_any;
-    serveraddr6.sin6_port = 0;
-    addr = (struct sockaddr *)&serveraddr6;
-    addrlen = sizeof(serveraddr6);
-
-    sockfd = socket(addr->sa_family, SOCK_DGRAM, 0);
-  }
-  assert(sockfd > 0);
+  char rbuf[kRecvBufSize];
 
-  bind(sockfd, addr, addrlen);
-  getsockname(sockfd, addr, &addrlen);
+  ret = socketpair(AF_LOCAL, SOCK_DGRAM, 0, sockfd);
+  assert(!ret);
 
 #if defined(POISON)
   __msan_poison(buf + 7, 1);
 #endif
 
-#if defined(SENDMSG)
+#if defined(SENDMSG) || defined(SENDMMSG)
   struct iovec iov[2] = {{buf, 5}, {buf + 5, 5}};
   struct msghdr msg;
-  msg.msg_name = addr;
-  msg.msg_namelen = addrlen;
+  msg.msg_name = nullptr;
+  msg.msg_namelen = 0;
   msg.msg_iov = iov;
   msg.msg_iovlen = 2;
   msg.msg_control = 0;
@@ -75,20 +57,95 @@ int main() {
   msg.msg_flags = 0;
 #endif
 
+#if defined(SENDMMSG)
+  struct iovec iov0[1] = {{buf, 7}};
+  struct msghdr msg0;
+  msg0.msg_name = nullptr;
+  msg0.msg_namelen = 0;
+  msg0.msg_iov = iov0;
+  msg0.msg_iovlen = 1;
+  msg0.msg_control = 0;
+  msg0.msg_controllen = 0;
+  msg0.msg_flags = 0;
+
+  struct mmsghdr mmsg[2];
+  mmsg[0].msg_hdr = msg0; // good
+  mmsg[1].msg_hdr = msg; // poisoned
+#endif
+
 #if defined(SEND)
-  ret = connect(sockfd, addr, addrlen);
-  assert(ret == 0);
-  ret = send(sockfd, buf, kBufSize, 0);
+  sent = send(sockfd[0], buf, kBufSize, 0);
   // SEND: Uninitialized bytes in __interceptor_send at offset 7 inside [{{.*}}, 10)
-  assert(ret > 0);
+  assert(sent > 0);
+
+  ret = recv(sockfd[1], rbuf, kRecvBufSize, 0);
+  assert(ret == sent);
+  assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
 #elif defined(SENDTO)
-  ret = sendto(sockfd, buf, kBufSize, 0, addr, addrlen);
+  sent = sendto(sockfd[0], buf, kBufSize, 0, nullptr, 0);
   // SENDTO: Uninitialized bytes in __interceptor_sendto at offset 7 inside [{{.*}}, 10)
-  assert(ret > 0);
+  assert(sent > 0);
+
+  struct sockaddr_storage ss;
+  socklen_t sslen = sizeof(ss);
+  ret = recvfrom(sockfd[1], rbuf, kRecvBufSize, 0, (struct sockaddr *)&ss,
+                 &sslen);
+  assert(ret == sent);
+  assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
+  assert(__msan_test_shadow(&ss, sizeof(ss)) == sslen);
 #elif defined(SENDMSG)
-  ret = sendmsg(sockfd, &msg, 0);
+  sent = sendmsg(sockfd[0], &msg, 0);
   // SENDMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
-  assert(ret > 0);
+  assert(sent > 0);
+
+  struct iovec riov[2] = {{rbuf, 3}, {rbuf + 3, kRecvBufSize - 3}};
+  struct msghdr rmsg;
+  rmsg.msg_name = nullptr;
+  rmsg.msg_namelen = 0;
+  rmsg.msg_iov = riov;
+  rmsg.msg_iovlen = 2;
+  rmsg.msg_control = 0;
+  rmsg.msg_controllen = 0;
+  rmsg.msg_flags = 0;
+
+  ret = recvmsg(sockfd[1], &rmsg, 0);
+  assert(ret == sent);
+  assert(__msan_test_shadow(rbuf, kRecvBufSize) == sent);
+#elif defined(SENDMMSG)
+  sent = sendmmsg(sockfd[0], mmsg, 2, 0);
+  // SENDMMSG: Uninitialized bytes in {{.*}} at offset 2 inside [{{.*}}, 5)
+  assert(sent == 2);
+  if (ret >= 2)
+    assert(mmsg[1].msg_len > 0);
+
+  struct iovec riov[2] = {{rbuf + kRecvBufSize / 2, kRecvBufSize / 2}};
+  struct msghdr rmsg;
+  rmsg.msg_name = nullptr;
+  rmsg.msg_namelen = 0;
+  rmsg.msg_iov = riov;
+  rmsg.msg_iovlen = 1;
+  rmsg.msg_control = 0;
+  rmsg.msg_controllen = 0;
+  rmsg.msg_flags = 0;
+
+  struct iovec riov0[2] = {{rbuf, kRecvBufSize / 2}};
+  struct msghdr rmsg0;
+  rmsg0.msg_name = nullptr;
+  rmsg0.msg_namelen = 0;
+  rmsg0.msg_iov = riov0;
+  rmsg0.msg_iovlen = 1;
+  rmsg0.msg_control = 0;
+  rmsg0.msg_controllen = 0;
+  rmsg0.msg_flags = 0;
+
+  struct mmsghdr rmmsg[2];
+  rmmsg[0].msg_hdr = rmsg0;
+  rmmsg[1].msg_hdr = rmsg;
+
+  ret = recvmmsg(sockfd[1], rmmsg, 2, 0, nullptr);
+  assert(ret == sent);
+  assert(__msan_test_shadow(rbuf, kRecvBufSize) == 7);
+  assert(__msan_test_shadow(rbuf + kRecvBufSize / 2, kRecvBufSize / 2) == 10);
 #endif
   fprintf(stderr, "== done\n");
   // NEGATIVE: == done




More information about the llvm-commits mailing list