1 //===-- asan_shadow_setup.cpp ---------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file is a part of AddressSanitizer, an address sanity checker. 10 // 11 // Set up the shadow memory. 12 //===----------------------------------------------------------------------===// 13 14 #include "sanitizer_common/sanitizer_platform.h" 15 16 // asan_fuchsia.cpp has their own InitializeShadowMemory implementation. 17 #if !SANITIZER_FUCHSIA 18 19 # include "asan_internal.h" 20 # include "asan_mapping.h" 21 22 namespace __asan { 23 24 static void ProtectGap(uptr addr, uptr size) { 25 if (!flags()->protect_shadow_gap) { 26 // The shadow gap is unprotected, so there is a chance that someone 27 // is actually using this memory. Which means it needs a shadow... 28 uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached()); 29 uptr GapShadowEnd = 30 RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1; 31 if (Verbosity()) 32 Printf( 33 "protect_shadow_gap=0:" 34 " not protecting shadow gap, allocating gap's shadow\n" 35 "|| `[%p, %p]` || ShadowGap's shadow ||\n", 36 (void*)GapShadowBeg, (void*)GapShadowEnd); 37 ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd, 38 "unprotected gap shadow"); 39 return; 40 } 41 __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart, 42 kZeroBaseMaxShadowStart); 43 } 44 45 static void MaybeReportLinuxPIEBug() { 46 #if SANITIZER_LINUX && \ 47 (defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64) 48 Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n"); 49 Report( 50 "See https://github.com/google/sanitizers/issues/856 for possible " 51 "workarounds.\n"); 52 #endif 53 } 54 55 void InitializeShadowMemory() { 56 // Set the shadow memory address to uninitialized. 57 __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel; 58 59 uptr shadow_start = kLowShadowBeg; 60 // Detect if a dynamic shadow address must used and find a available location 61 // when necessary. When dynamic address is used, the macro |kLowShadowBeg| 62 // expands to |__asan_shadow_memory_dynamic_address| which is 63 // |kDefaultShadowSentinel|. 64 bool full_shadow_is_available = false; 65 if (shadow_start == kDefaultShadowSentinel) { 66 shadow_start = FindDynamicShadowStart(); 67 if (SANITIZER_LINUX) full_shadow_is_available = true; 68 } 69 // Update the shadow memory address (potentially) used by instrumentation. 70 __asan_shadow_memory_dynamic_address = shadow_start; 71 72 if (kLowShadowBeg) shadow_start -= GetMmapGranularity(); 73 74 if (!full_shadow_is_available) 75 full_shadow_is_available = 76 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd); 77 78 #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \ 79 !ASAN_FIXED_MAPPING 80 if (!full_shadow_is_available) { 81 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0; 82 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0; 83 } 84 #endif 85 86 if (Verbosity()) PrintAddressSpaceLayout(); 87 88 if (full_shadow_is_available) { 89 // mmap the low shadow plus at least one page at the left. 90 if (kLowShadowBeg) 91 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); 92 // mmap the high shadow. 93 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); 94 // protect the gap. 95 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); 96 CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1); 97 } else if (kMidMemBeg && 98 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && 99 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) { 100 CHECK(kLowShadowBeg != kLowShadowEnd); 101 // mmap the low shadow plus at least one page at the left. 102 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow"); 103 // mmap the mid shadow. 104 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow"); 105 // mmap the high shadow. 106 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow"); 107 // protect the gaps. 108 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); 109 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1); 110 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1); 111 } else { 112 Report( 113 "Shadow memory range interleaves with an existing memory mapping. " 114 "ASan cannot proceed correctly. ABORTING.\n"); 115 Report("ASan shadow was supposed to be located in the [%p-%p] range.\n", 116 (void*)shadow_start, (void*)kHighShadowEnd); 117 MaybeReportLinuxPIEBug(); 118 DumpProcessMap(); 119 Die(); 120 } 121 } 122 123 } // namespace __asan 124 125 #endif // !SANITIZER_FUCHSIA 126