[compiler-rt] r238109 - [msan] Mprotect all inaccessible memory regions.

Evgeniy Stepanov eugeni.stepanov at gmail.com
Sat May 23 19:47:59 PDT 2015


Author: eugenis
Date: Sat May 23 21:47:59 2015
New Revision: 238109

URL: http://llvm.org/viewvc/llvm-project?rev=238109&view=rev
Log:
[msan] Mprotect all inaccessible memory regions.

Fix 2 bugs in memory mapping setup:
- the invalid region at offset 0 was not protected because mmap at
  address 0 fails with EPERM on most Linux systems. We did not
  notice this because the check condition was flipped: the code was
  checking that mprotect has failed. And the test that was supposed
  to catch this was weakened by the mitigations in the mmap
  interceptor.
- when running without origins, the origin shadow range was left
  unprotected.

The new test ensures that mmap w/o MAP_FIXED always returns valid
application addresses.

Added:
    compiler-rt/trunk/test/msan/mmap.cc
Modified:
    compiler-rt/trunk/lib/msan/msan.cc
    compiler-rt/trunk/lib/msan/msan.h
    compiler-rt/trunk/lib/msan/msan_linux.cc

Modified: compiler-rt/trunk/lib/msan/msan.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.cc?rev=238109&r1=238108&r2=238109&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.cc (original)
+++ compiler-rt/trunk/lib/msan/msan.cc Sat May 23 21:47:59 2015
@@ -390,7 +390,7 @@ void __msan_init() {
   __msan_clear_on_return();
   if (__msan_get_track_origins())
     VPrintf(1, "msan_track_origins\n");
-  if (!InitShadow(/* map_shadow */ true, __msan_get_track_origins())) {
+  if (!InitShadow(__msan_get_track_origins())) {
     Printf("FATAL: MemorySanitizer can not mmap the shadow memory.\n");
     Printf("FATAL: Make sure to compile with -fPIE and to link with -pie.\n");
     Printf("FATAL: Disabling ASLR is known to cause this error.\n");

Modified: compiler-rt/trunk/lib/msan/msan.h
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan.h?rev=238109&r1=238108&r2=238109&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan.h (original)
+++ compiler-rt/trunk/lib/msan/msan.h Sat May 23 21:47:59 2015
@@ -125,7 +125,7 @@ extern bool msan_init_is_running;
 extern int msan_report_count;
 
 bool ProtectRange(uptr beg, uptr end);
-bool InitShadow(bool map_shadow, bool init_origins);
+bool InitShadow(bool init_origins);
 char *GetProcSelfMaps();
 void InitializeInterceptors();
 

Modified: compiler-rt/trunk/lib/msan/msan_linux.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/msan/msan_linux.cc?rev=238109&r1=238108&r2=238109&view=diff
==============================================================================
--- compiler-rt/trunk/lib/msan/msan_linux.cc (original)
+++ compiler-rt/trunk/lib/msan/msan_linux.cc Sat May 23 21:47:59 2015
@@ -55,8 +55,17 @@ static bool CheckMemoryRangeAvailability
 
 static bool ProtectMemoryRange(uptr beg, uptr size) {
   if (size > 0) {
-    uptr end = beg + size - 1;
-    if (!MmapNoAccess(beg, size)) {
+    void *addr = MmapNoAccess(beg, size);
+    if (beg == 0 && addr != 0) {
+      // Depending on the kernel configuration, we may not be able to protect
+      // the page at address zero.
+      uptr gap = 16 * GetPageSizeCached();
+      beg += gap;
+      size -= gap;
+      addr = MmapNoAccess(beg, size);
+    }
+    if ((uptr)addr != beg) {
+      uptr end = beg + size - 1;
       Printf("FATAL: Cannot protect memory range %p - %p.\n", beg, end);
       return false;
     }
@@ -95,7 +104,7 @@ static void CheckMemoryLayoutSanity() {
   }
 }
 
-bool InitShadow(bool map_shadow, bool init_origins) {
+bool InitShadow(bool init_origins) {
   // Let user know mapping parameters first.
   VPrintf(1, "__msan_init %p\n", &__msan_init);
   for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
@@ -115,15 +124,27 @@ bool InitShadow(bool map_shadow, bool in
     uptr end = kMemoryLayout[i].end;
     uptr size= end - start;
     MappingDesc::Type type = kMemoryLayout[i].type;
-    if ((map_shadow && type == MappingDesc::SHADOW) ||
-        (init_origins && type == MappingDesc::ORIGIN)) {
-      if (!CheckMemoryRangeAvailability(start, size)) return false;
-      if ((uptr)MmapFixedNoReserve(start, size) != start) return false;
+
+    bool map = type == MappingDesc::SHADOW ||
+               (init_origins && type == MappingDesc::ORIGIN);
+    bool protect = type == MappingDesc::INVALID ||
+                   (!init_origins && type == MappingDesc::ORIGIN);
+    CHECK(!(map && protect));
+    if (!map && !protect)
+      CHECK(type == MappingDesc::APP);
+    if (map) {
+      if (!CheckMemoryRangeAvailability(start, size))
+        return false;
+      if ((uptr)MmapFixedNoReserve(start, size) != start)
+        return false;
       if (common_flags()->use_madv_dontdump)
         DontDumpShadowMemory(start, size);
-    } else if (type == MappingDesc::INVALID) {
-      if (!CheckMemoryRangeAvailability(start, size)) return false;
-      if (!ProtectMemoryRange(start, size)) return false;
+    }
+    if (protect) {
+      if (!CheckMemoryRangeAvailability(start, size))
+        return false;
+      if (!ProtectMemoryRange(start, size))
+        return false;
     }
   }
 

Added: compiler-rt/trunk/test/msan/mmap.cc
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/msan/mmap.cc?rev=238109&view=auto
==============================================================================
--- compiler-rt/trunk/test/msan/mmap.cc (added)
+++ compiler-rt/trunk/test/msan/mmap.cc Sat May 23 21:47:59 2015
@@ -0,0 +1,42 @@
+// Test that mmap (without MAP_FIXED) always returns valid application addresses.
+// RUN: %clangxx_msan -O0 %s -o %t && %run %t
+// RUN: %clangxx_msan -O0 -fsanitize-memory-track-origins %s -o %t && %run %t
+
+#include <assert.h>
+#include <errno.h>
+#include <stdint.h>
+#include <sys/mman.h>
+#include <stdio.h>
+
+bool AddrIsApp(void *p) {
+  uintptr_t addr = (uintptr_t)p;
+#if defined(__FreeBSD__) && defined(__x86_64__)
+  return addr < 0x010000000000ULL || addr >= 0x600000000000ULL;
+#elif defined(__x86_64__)
+  return addr >= 0x600000000000ULL;
+#elif defined(__mips64)
+  return addr >= 0x00e000000000ULL;
+#endif
+}
+
+int main() {
+  // Large enough to quickly exhaust the entire address space.
+#if defined(__mips64)
+  const size_t kMapSize = 0x100000000ULL;
+#else
+  const size_t kMapSize = 0x1000000000ULL;
+#endif
+  int success_count = 0;
+  while (true) {
+    void *p = mmap(0, kMapSize, PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+    printf("%p\n", p);
+    if (p == MAP_FAILED) {
+      assert(errno == ENOMEM);
+      break;
+    }
+    assert(AddrIsApp(p));
+    success_count++;
+  }
+  printf("successful mappings: %d\n", success_count);
+  assert(success_count > 5);
+}





More information about the llvm-commits mailing list