[compiler-rt] 4deda57 - [DFSan] Handle mmap() calls before interceptors are installed.

Matt Morehouse via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 19 15:08:15 PDT 2020


Author: Matt Morehouse
Date: 2020-08-19T15:07:41-07:00
New Revision: 4deda57106f7c9b982a49cb907c33e3966c8de7f

URL: https://github.com/llvm/llvm-project/commit/4deda57106f7c9b982a49cb907c33e3966c8de7f
DIFF: https://github.com/llvm/llvm-project/commit/4deda57106f7c9b982a49cb907c33e3966c8de7f.diff

LOG: [DFSan] Handle mmap() calls before interceptors are installed.

InitializeInterceptors() calls dlsym(), which calls calloc().  Depending
on the allocator implementation, calloc() may invoke mmap(), which
results in a segfault since REAL(mmap) is still being resolved.

We fix this by doing a direct syscall if interceptors haven't been fully
resolved yet.

Reviewed By: vitalybuka

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

Added: 
    compiler-rt/test/dfsan/interceptors.c

Modified: 
    compiler-rt/lib/dfsan/dfsan_interceptors.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/dfsan/dfsan_interceptors.cpp b/compiler-rt/lib/dfsan/dfsan_interceptors.cpp
index 673171c46f5a..12b74df2bd4e 100644
--- a/compiler-rt/lib/dfsan/dfsan_interceptors.cpp
+++ b/compiler-rt/lib/dfsan/dfsan_interceptors.cpp
@@ -11,16 +11,29 @@
 // Interceptors for standard library functions.
 //===----------------------------------------------------------------------===//
 
+#include <sys/syscall.h>
+#include <unistd.h>
+
 #include "dfsan/dfsan.h"
 #include "interception/interception.h"
 #include "sanitizer_common/sanitizer_common.h"
 
 using namespace __sanitizer;
 
+static bool interceptors_initialized;
+
 INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
             int fd, OFF_T offset) {
-  void *res = REAL(mmap)(addr, length, prot, flags, fd, offset);
-  if (res != (void*)-1)
+  void *res;
+
+  // interceptors_initialized is set to true during preinit_array, when we're
+  // single-threaded.  So we don't need to worry about accessing it atomically.
+  if (!interceptors_initialized)
+    res = (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
+  else
+    res = REAL(mmap)(addr, length, prot, flags, fd, offset);
+
+  if (res != (void *)-1)
     dfsan_set_label(0, res, RoundUpTo(length, GetPageSize()));
   return res;
 }
@@ -28,18 +41,18 @@ INTERCEPTOR(void *, mmap, void *addr, SIZE_T length, int prot, int flags,
 INTERCEPTOR(void *, mmap64, void *addr, SIZE_T length, int prot, int flags,
             int fd, OFF64_T offset) {
   void *res = REAL(mmap64)(addr, length, prot, flags, fd, offset);
-  if (res != (void*)-1)
+  if (res != (void *)-1)
     dfsan_set_label(0, res, RoundUpTo(length, GetPageSize()));
   return res;
 }
 
 namespace __dfsan {
 void InitializeInterceptors() {
-  static int inited = 0;
-  CHECK_EQ(inited, 0);
+  CHECK(!interceptors_initialized);
 
   INTERCEPT_FUNCTION(mmap);
   INTERCEPT_FUNCTION(mmap64);
-  inited = 1;
+
+  interceptors_initialized = true;
 }
 }  // namespace __dfsan

diff  --git a/compiler-rt/test/dfsan/interceptors.c b/compiler-rt/test/dfsan/interceptors.c
new file mode 100644
index 000000000000..77aec2078f13
--- /dev/null
+++ b/compiler-rt/test/dfsan/interceptors.c
@@ -0,0 +1,32 @@
+// RUN: %clang_dfsan -fno-sanitize=dataflow -DCALLOC -c %s -o %t-calloc.o
+// RUN: %clang_dfsan %s %t-calloc.o -o %t
+// RUN: %run %t
+//
+// Tests that calling mmap() during during dfsan initialization works.
+
+#include <assert.h>
+#include <sanitizer/dfsan_interface.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <unistd.h>
+
+#ifdef CALLOC
+
+// dfsan_init() installs interceptors via dlysm(), which calls calloc().
+// Calling mmap() from here should work even if interceptors haven't been fully
+// set up yet.
+void *calloc(size_t Num, size_t Size) {
+  size_t PageSize = getpagesize();
+  Size = Size * Num;
+  Size = (Size + PageSize - 1) & ~(PageSize - 1); // Round up to PageSize.
+  void *Ret = mmap(NULL, Size, PROT_READ | PROT_WRITE,
+                   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+  assert(Ret != MAP_FAILED);
+  return Ret;
+}
+
+#else
+
+int main() { return 0; }
+
+#endif // CALLOC


        


More information about the llvm-commits mailing list