1 //===-- asan_shadow_setup.cc ----------------------------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file is a part of AddressSanitizer, an address sanity checker. 11 // 12 // Set up the shadow memory. 13 //===----------------------------------------------------------------------===// 14 15 #include "sanitizer_common/sanitizer_platform.h" 16 17 // asan_fuchsia.cc and asan_rtems.cc have their own 18 // InitializeShadowMemory implementation. 19 #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS 20 21 #include "asan_internal.h" 22 #include "asan_mapping.h" 23 24 namespace __asan { 25 26 // ---------------------- mmap -------------------- {{{1 27 // Reserve memory range [beg, end]. 28 // We need to use inclusive range because end+1 may not be representable. 29 void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) { 30 CHECK_EQ((beg % GetMmapGranularity()), 0); 31 CHECK_EQ(((end + 1) % GetMmapGranularity()), 0); 32 uptr size = end - beg + 1; 33 DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb. 34 if (!MmapFixedNoReserve(beg, size, name)) { 35 Report( 36 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. " 37 "Perhaps you're using ulimit -v\n", 38 size); 39 Abort(); 40 } 41 if (common_flags()->no_huge_pages_for_shadow) NoHugePagesInRegion(beg, size); 42 if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size); 43 } 44 45 static void ProtectGap(uptr addr, uptr size) { 46 if (!flags()->protect_shadow_gap) { 47 // The shadow gap is unprotected, so there is a chance that someone 48 // is actually using this memory. Which means it needs a shadow... 49 uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached()); 50 uptr GapShadowEnd = 51 RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1; 52 if (Verbosity()) 53 Printf( 54 "protect_shadow_gap=0:" 55 " not protecting shadow gap, allocating gap's shadow\n" 56 "|| `[%p, %p]` || ShadowGap's shadow ||\n", 57 GapShadowBeg, GapShadowEnd); 58 ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd, 59 "unprotected gap shadow"); 60 return; 61 } 62 void *res = MmapFixedNoAccess(addr, size, "shadow gap"); 63 if (addr == (uptr)res) return; 64 // A few pages at the start of the address space can not be protected. 65 // But we really want to protect as much as possible, to prevent this memory 66 // being returned as a result of a non-FIXED mmap(). 67 if (addr == kZeroBaseShadowStart) { 68 uptr step = GetMmapGranularity(); 69 while (size > step && addr < kZeroBaseMaxShadowStart) { 70 addr += step; 71 size -= step; 72 void *res = MmapFixedNoAccess(addr, size, "shadow gap"); 73 if (addr == (uptr)res) return; 74 } 75 } 76 77 Report( 78 "ERROR: Failed to protect the shadow gap. " 79 "ASan cannot proceed correctly. ABORTING.\n"); 80 DumpProcessMap(); 81 Die(); 82 } 83 84 static void MaybeReportLinuxPIEBug() { 85 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__aarch64__)) 86 Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n"); 87 Report( 88 "See https://github.com/google/sanitizers/issues/856 for possible " 89 "workarounds.\n"); 90 #endif 91 } 92 93 void InitializeShadowMemory() { 94 // Set the shadow memory address to uninitialized. 95 __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel; 96 97 uptr shadow_start = kLowShadowBeg; 98 // Detect if a dynamic shadow address must used and find a available location 99 // when necessary. When dynamic address is used, the macro |kLowShadowBeg| 100 // expands to |__asan_shadow_memory_dynamic_address| which is 101 // |kDefaultShadowSentinel|. 102 bool full_shadow_is_available = false; 103 if (shadow_start == kDefaultShadowSentinel) { 104 __asan_shadow_memory_dynamic_address = 0; 105 CHECK_EQ(0, kLowShadowBeg); 106 shadow_start = FindDynamicShadowStart(); 107 if (SANITIZER_LINUX) full_shadow_is_available = true; 108 } 109 // Update the shadow memory address (potentially) used by instrumentation. 110 __asan_shadow_memory_dynamic_address = shadow_start; 111 112 if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); 113 114 if (!full_shadow_is_available) 115 full_shadow_is_available = 116 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd); 117 118 #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \ 119 !ASAN_FIXED_MAPPING 120 if (!full_shadow_is_available) { 121 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; 122 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0; 123 } 124 #endif 125 126 if (Verbosity()) PrintAddressSpaceLayout(); 127 128 if (full_shadow_is_available) { 129 // mmap the low shadow plus at least one page at the left. 130 if (kLowShadowBeg) 131 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); 132 // mmap the high shadow. 133 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); 134 // protect the gap. 135 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); 136 CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1); 137 } else if (kMidMemBeg && 138 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && 139 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) { 140 CHECK(kLowShadowBeg != kLowShadowEnd); 141 // mmap the low shadow plus at least one page at the left. 142 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); 143 // mmap the mid shadow. 144 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow"); 145 // mmap the high shadow. 146 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); 147 // protect the gaps. 148 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); 149 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); 150 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); 151 } else { 152 Report( 153 "Shadow memory range interleaves with an existing memory mapping. " 154 "ASan cannot proceed correctly. ABORTING.\n"); 155 Report("ASan shadow was supposed to be located in the [%p-%p] range.\n", 156 shadow_start, kHighShadowEnd); 157 MaybeReportLinuxPIEBug(); 158 DumpProcessMap(); 159 Die(); 160 } 161 } 162 163 } // namespace __asan 164 165 #endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS 166