diff options
author | Alexander Potapenko <glider@google.com> | 2012-02-13 15:11:23 +0000 |
---|---|---|
committer | Alexander Potapenko <glider@google.com> | 2012-02-13 15:11:23 +0000 |
commit | ef4521e239a546fe688f297cc2c64a66b78a1e77 (patch) | |
tree | f33ba9092c3035bc56482918eaccff7df24898ec | |
parent | fe52523b4c3584c570073b0298c3b0c6018b3885 (diff) | |
download | bcm5719-llvm-ef4521e239a546fe688f297cc2c64a66b78a1e77.tar.gz bcm5719-llvm-ef4521e239a546fe688f297cc2c64a66b78a1e77.zip |
Check whether the shadow memory range intersects with an existing mapping.
This should help to detect problems with ASLR or linker tricks early.
llvm-svn: 150391
-rw-r--r-- | compiler-rt/lib/asan/asan_rtl.cc | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index 067469a4256..568a79f5d6e 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -118,6 +118,42 @@ static void ReserveShadowMemoryRange(uintptr_t beg, uintptr_t end) { CHECK(res == (void*)beg && "ReserveShadowMemoryRange failed"); } +inline bool IntervalsAreSeparate(uintptr_t start1, uintptr_t end1, + uintptr_t start2, uintptr_t end2) { + CHECK(start1 <= end1); + CHECK(start2 <= end2); + if (start1 == start2) { + return false; + } else { + if (start1 < start2) { + return (end1 < start2); + } else { + return (end2 < start1); + } + } + return false; +} + +// FIXME: this is thread-unsafe, but should not cause problems most of the time. +// When the shadow is mapped only a single thread usually exists (plus maybe +// several worker threads on Mac, which aren't expected to map big chunks of +// memory. +bool AsanShadowRangeIsAvailable() { + AsanProcMaps procmaps; + uintptr_t start, end; + bool available = true; + while (procmaps.Next(&start, &end, + /*offset*/NULL, /*filename*/NULL, /*size*/NULL)) { + if (!IntervalsAreSeparate(start, end, + kLowShadowBeg - kMmapGranularity, + kHighShadowEnd)) { + available = false; + break; + } + } + return available; +} + // ---------------------- LowLevelAllocator ------------- {{{1 void *LowLevelAllocator::Allocate(size_t size) { CHECK((size & (size - 1)) == 0 && "size must be a power of two"); @@ -464,7 +500,7 @@ void __asan_init() { AsanDisableCoreDumper(); } - { + if (AsanShadowRangeIsAvailable()) { if (kLowShadowBeg != kLowShadowEnd) { // mmap the low shadow plus at least one page. ReserveShadowMemoryRange(kLowShadowBeg - kMmapGranularity, kLowShadowEnd); @@ -474,6 +510,10 @@ void __asan_init() { // protect the gap void *prot = AsanMprotect(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); CHECK(prot == (void*)kShadowGapBeg); + } else { + Report("Shadow memory range interleaves with an existing memory mapping. " + "ASan cannot proceed correctly. ABORTING.\n"); + AsanDie(); } // On Linux AsanThread::ThreadStart() calls malloc() that's why asan_inited |