summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Potapenko <glider@google.com>2012-02-13 15:11:23 +0000
committerAlexander Potapenko <glider@google.com>2012-02-13 15:11:23 +0000
commitef4521e239a546fe688f297cc2c64a66b78a1e77 (patch)
treef33ba9092c3035bc56482918eaccff7df24898ec
parentfe52523b4c3584c570073b0298c3b0c6018b3885 (diff)
downloadbcm5719-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.cc42
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
OpenPOWER on IntegriCloud