[compiler-rt] r182466 - [msan] getaddrinfo & nested interceptor support.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Wed May 22 05:50:27 PDT 2013


Author: eugenis
Date: Wed May 22 07:50:26 2013
New Revision: 182466

URL: http://llvm.org/viewvc/llvm-project?rev=182466&view=rev
Log:
[msan] getaddrinfo & nested interceptor support.

Multiple connected changes:
- Ignore reads from nested interceptors.
- Check shadow on reads from common interceptors.
- getaddrinfo interceptor.


Added:
    compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo-positive.cc   (with props)
    compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo.cc   (with props)
Modified:
    compiler-rt/trunk/lib/msan/msan_interceptors.cc
    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/lib/tsan/rtl/tsan_stat.cc
    compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h

Added: compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo-positive.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo-positive.cc?rev=182466&view=auto
==============================================================================
--- compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo-positive.cc (added)
+++ compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo-positive.cc Wed May 22 07:50:26 2013
@@ -0,0 +1,19 @@
+// RUN: %clangxx_msan -m64 -O0 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+// RUN: %clangxx_msan -m64 -O3 %s -o %t && not %t >%t.out 2>&1
+// RUN: FileCheck %s < %t.out
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdlib.h>
+
+int main(void) {
+  struct addrinfo *ai;
+  struct addrinfo hint;
+  int res = getaddrinfo("localhost", NULL, &hint, &ai);
+  // CHECK: UMR in __interceptor_getaddrinfo at offset 0 inside
+  // CHECK: WARNING: Use of uninitialized value
+  // CHECK: #0 {{.*}} in main {{.*}}getaddrinfo-positive.cc:[[@LINE-3]]
+  return 0;
+}

Propchange: compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo-positive.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Added: compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo.cc?rev=182466&view=auto
==============================================================================
--- compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo.cc (added)
+++ compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo.cc Wed May 22 07:50:26 2013
@@ -0,0 +1,24 @@
+// RUN: %clangxx_msan -m64 -O0 %s -o %t && %t
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+#include <stdlib.h>
+
+void poison_stack_ahead() {
+  char buf[100000];
+  // With -O0 this poisons a large chunk of stack.
+}
+
+int main(void) {
+  poison_stack_ahead();
+
+  struct addrinfo *ai;
+
+  // This should trigger loading of libnss_dns and friends.
+  // Those libraries are typically uninstrumented.They will call strlen() on a
+  // stack-allocated buffer, which is very likely to be poisoned. Test that we
+  // don't report this as an UMR.
+  int res = getaddrinfo("not-in-etc-hosts", NULL, NULL, &ai);
+  return 0;
+}

Propchange: compiler-rt/trunk/lib/msan/lit_tests/getaddrinfo.cc
------------------------------------------------------------------------------
    svn:eol-style = LF

Modified: compiler-rt/trunk/lib/msan/msan_interceptors.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_interceptors.cc?rev=182466&r1=182465&r2=182466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_interceptors.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_interceptors.cc Wed May 22 07:50:26 2013
@@ -32,6 +32,18 @@ extern "C" const int __msan_keep_going;
 
 using namespace __msan;
 
+// True if this is a nested interceptor.
+static THREADLOCAL int in_interceptor_scope;
+
+struct InterceptorScope {
+  InterceptorScope() { ++in_interceptor_scope; }
+  ~InterceptorScope() { --in_interceptor_scope; }
+};
+
+bool IsInInterceptorScope() {
+  return in_interceptor_scope;
+}
+
 #define ENSURE_MSAN_INITED() do { \
   CHECK(!msan_init_is_running); \
   if (!msan_inited) { \
@@ -39,24 +51,30 @@ using namespace __msan;
   } \
 } while (0)
 
-#define CHECK_UNPOISONED(x, n) \
-  do { \
-    sptr offset = __msan_test_shadow(x, n);                 \
-    if (__msan::IsInSymbolizer()) break;                    \
-    if (offset >= 0 && __msan::flags()->report_umrs) {      \
-      GET_CALLER_PC_BP_SP;                                  \
-      (void)sp;                                             \
-      Printf("UMR in %s at offset %d inside [%p, +%d) \n",  \
-             __FUNCTION__, offset, x, n);                   \
-      __msan::PrintWarningWithOrigin(                       \
-        pc, bp, __msan_get_origin((char*)x + offset));      \
-      if (!__msan_keep_going) {                             \
-        Printf("Exiting\n");                                \
-        Die();                                              \
-      }                                                     \
-    }                                                       \
+// Check that [x, x+n) range is unpoisoned.
+#define CHECK_UNPOISONED_0(x, n)                                              \
+  do {                                                                        \
+    sptr offset = __msan_test_shadow(x, n);                                   \
+    if (__msan::IsInSymbolizer()) break;                                      \
+    if (offset >= 0 && __msan::flags()->report_umrs) {                        \
+      GET_CALLER_PC_BP_SP;                                                    \
+      (void) sp;                                                              \
+      Printf("UMR in %s at offset %d inside [%p, +%d) \n", __FUNCTION__,      \
+             offset, x, n);                                                   \
+      __msan::PrintWarningWithOrigin(pc, bp,                                  \
+                                     __msan_get_origin((char *) x + offset)); \
+      if (!__msan_keep_going) {                                               \
+        Printf("Exiting\n");                                                  \
+        Die();                                                                \
+      }                                                                       \
+    }                                                                         \
   } while (0)
 
+// Check that [x, x+n) range is unpoisoned unless we are in a nested
+// interceptor.
+#define CHECK_UNPOISONED(x, n) \
+  if (!IsInInterceptorScope()) CHECK_UNPOISONED_0(x, n);
+
 static void *fast_memset(void *ptr, int c, SIZE_T n);
 static void *fast_memcpy(void *dst, const void *src, SIZE_T n);
 
@@ -953,18 +971,28 @@ INTERCEPTOR(int, pthread_create, void *t
   return res;
 }
 
+struct MSanInterceptorContext {
+  bool in_interceptor_scope;
+};
+
+// A version of CHECK_UNPOISED using a saved scope value. Used in common interceptors.
+#define CHECK_UNPOISONED_CTX(ctx, x, n)                        \
+  if (!((MSanInterceptorContext *) ctx)->in_interceptor_scope) \
+    CHECK_UNPOISONED_0(x, n);
+
 #define COMMON_INTERCEPTOR_WRITE_RANGE(ctx, ptr, size) \
-    __msan_unpoison(ptr, size)
-#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) do { } while (false)
-#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)  \
-  do {                                            \
-    if (msan_init_is_running)                     \
-      return REAL(func)(__VA_ARGS__);             \
-    ctx = 0;                                      \
-    (void)ctx;                                    \
-    ENSURE_MSAN_INITED();                         \
+  __msan_unpoison(ptr, size)
+#define COMMON_INTERCEPTOR_READ_RANGE(ctx, ptr, size) \
+  CHECK_UNPOISONED_CTX(ctx, ptr, size);
+#define COMMON_INTERCEPTOR_ENTER(ctx, func, ...)                \
+  if (msan_init_is_running) return REAL(func)(__VA_ARGS__);     \
+  MSanInterceptorContext msan_ctx = { IsInInterceptorScope() }; \
+  ctx = (void *)&msan_ctx;                                      \
+  InterceptorScope interceptor_scope;                           \
+  ENSURE_MSAN_INITED();
+#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) \
+  do {                                         \
   } while (false)
-#define COMMON_INTERCEPTOR_FD_ACQUIRE(ctx, fd) do { } while (false)
 #define COMMON_INTERCEPTOR_FD_RELEASE(ctx, fd) do { } while (false)
 #define COMMON_INTERCEPTOR_SET_THREAD_NAME(ctx, name) \
   do { } while (false)  // FIXME

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=182466&r1=182465&r2=182466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_common_interceptors.inc Wed May 22 07:50:26 2013
@@ -748,6 +748,38 @@ INTERCEPTOR(int, pthread_getschedparam,
 #define INIT_PTHREAD_GETSCHEDPARAM
 #endif
 
+#if SANITIZER_INTERCEPT_GETADDRINFO
+INTERCEPTOR(int, getaddrinfo, char *node, char *service,
+            struct __sanitizer_addrinfo *hints,
+            struct __sanitizer_addrinfo **out) {
+  void *ctx;
+  COMMON_INTERCEPTOR_ENTER(ctx, getaddrinfo, node, service, hints, out);
+  if (node) COMMON_INTERCEPTOR_READ_RANGE(ctx, node, REAL(strlen)(node) + 1);
+  if (service)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, service, REAL(strlen)(service) + 1);
+  if (hints)
+    COMMON_INTERCEPTOR_READ_RANGE(ctx, hints, sizeof(__sanitizer_addrinfo));
+  int res = REAL(getaddrinfo)(node, service, hints, out);
+  if (res == 0) {
+    struct __sanitizer_addrinfo *p = *out;
+    while (p) {
+      COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p, sizeof(__sanitizer_addrinfo));
+      if (p->ai_addr)
+        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_addr, struct_sockaddr_sz);
+      if (p->ai_canonname)
+        COMMON_INTERCEPTOR_WRITE_RANGE(ctx, p->ai_canonname,
+                                       REAL(strlen)(p->ai_canonname) + 1);
+      p = p->ai_next;
+    }
+  }
+  return res;
+}
+#define INIT_GETADDRINFO INTERCEPT_FUNCTION(getaddrinfo);
+#else
+#define INIT_GETADDRINFO
+#endif
+
+
 #define SANITIZER_COMMON_INTERCEPTORS_INIT \
   INIT_STRCASECMP;                         \
   INIT_STRNCASECMP;                        \
@@ -770,4 +802,5 @@ INTERCEPTOR(int, pthread_getschedparam,
   INIT_GLOB;                               \
   INIT_WAIT;                               \
   INIT_INET;                               \
-  INIT_PTHREAD_GETSCHEDPARAM;
+  INIT_PTHREAD_GETSCHEDPARAM;              \
+  INIT_GETADDRINFO;

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=182466&r1=182465&r2=182466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h (original)
+++ compiler-rt/trunk/lib/sanitizer_common/sanitizer_platform_interceptors.h Wed May 22 07:50:26 2013
@@ -70,5 +70,6 @@
 # define SANITIZER_INTERCEPT_WAIT SI_NOT_WINDOWS
 # define SANITIZER_INTERCEPT_INET SI_NOT_WINDOWS
 # define SANITIZER_INTERCEPT_PTHREAD_GETSCHEDPARAM SI_NOT_WINDOWS
+# define SANITIZER_INTERCEPT_GETADDRINFO SI_NOT_WINDOWS
 
 #endif  // #ifndef SANITIZER_PLATFORM_INTERCEPTORS_H

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=182466&r1=182465&r2=182466&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 May 22 07:50:26 2013
@@ -29,9 +29,11 @@
 #include <sys/utsname.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/socket.h>
 #include <sys/time.h>
 #include <sys/resource.h>
 #include <sys/socket.h>
+#include <netdb.h>
 #include <time.h>
 
 #if !SANITIZER_ANDROID
@@ -56,6 +58,7 @@ namespace __sanitizer {
   unsigned struct_sigaction_sz = sizeof(struct sigaction);
   unsigned struct_itimerval_sz = sizeof(struct itimerval);
   unsigned pthread_t_sz = sizeof(pthread_t);
+  unsigned struct_sockaddr_sz = sizeof(struct sockaddr);
 
 #if !SANITIZER_ANDROID
   unsigned ucontext_t_sz = sizeof(ucontext_t);
@@ -133,4 +136,12 @@ COMPILER_CHECK(offsetof(struct __sanitiz
                offsetof(struct dl_phdr_info, dlpi_phnum));
 #endif
 
+COMPILER_CHECK(sizeof(struct __sanitizer_addrinfo) == sizeof(struct addrinfo));
+COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_addr) ==
+               offsetof(struct addrinfo, ai_addr));
+COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_canonname) ==
+               offsetof(struct addrinfo, ai_canonname));
+COMPILER_CHECK(offsetof(struct __sanitizer_addrinfo, ai_next) ==
+               offsetof(struct addrinfo, ai_next));
+
 #endif  // SANITIZER_LINUX || 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=182466&r1=182465&r2=182466&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 May 22 07:50:26 2013
@@ -29,6 +29,7 @@ namespace __sanitizer {
   extern unsigned siginfo_t_sz;
   extern unsigned struct_itimerval_sz;
   extern unsigned pthread_t_sz;
+  extern unsigned struct_sockaddr_sz;
 
 #if !SANITIZER_ANDROID
   extern unsigned ucontext_t_sz;
@@ -83,6 +84,17 @@ namespace __sanitizer {
     short dlpi_phnum;
   };
 #endif
+
+  struct __sanitizer_addrinfo {
+    int ai_flags;
+    int ai_family;
+    int ai_socktype;
+    int ai_protocol;
+    uptr ai_addrlen;
+    void *ai_addr;
+    char *ai_canonname;
+    struct __sanitizer_addrinfo *ai_next;
+  };
 }  // namespace __sanitizer
 
 #endif

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc?rev=182466&r1=182465&r2=182466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.cc Wed May 22 07:50:26 2013
@@ -311,6 +311,7 @@ void StatOutput(u64 *stat) {
   name[StatInt_wait4]                    = "  wait4                           ";
   name[StatInt_inet_ntop]                = "  inet_ntop                       ";
   name[StatInt_inet_pton]                = "  inet_pton                       ";
+  name[StatInt_getaddrinfo]              = "  getaddrinfo                     ";
 
   name[StatAnnotation]                   = "Dynamic annotations               ";
   name[StatAnnotateHappensBefore]        = "  HappensBefore                   ";

Modified: compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h?rev=182466&r1=182465&r2=182466&view=diff
==============================================================================
--- compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h (original)
+++ compiler-rt/trunk/lib/tsan/rtl/tsan_stat.h Wed May 22 07:50:26 2013
@@ -306,6 +306,7 @@ enum StatType {
   StatInt_wait4,
   StatInt_inet_ntop,
   StatInt_inet_pton,
+  StatInt_getaddrinfo,
 
   // Dynamic annotations.
   StatAnnotation,





More information about the llvm-commits mailing list