[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