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