1 //===-- asan_premap_shadow.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 // Reserve shadow memory with an ifunc resolver. 13 //===----------------------------------------------------------------------===// 14 15 #include "asan_mapping.h" 16 17 #if ASAN_PREMAP_SHADOW 18 19 #include "asan_premap_shadow.h" 20 #include "sanitizer_common/sanitizer_posix.h" 21 22 namespace __asan { 23 24 // The code in this file needs to run in an unrelocated binary. It may not 25 // access any external symbol, including its own non-hidden globals. 26 27 // Conservative upper limit. PremapShadowSize()28uptr PremapShadowSize() { 29 uptr granularity = GetMmapGranularity(); 30 return RoundUpTo(GetMaxVirtualAddress() >> SHADOW_SCALE, granularity); 31 } 32 33 // Returns an address aligned to 8 pages, such that one page on the left and 34 // PremapShadowSize() bytes on the right of it are mapped r/o. PremapShadow()35uptr PremapShadow() { 36 uptr granularity = GetMmapGranularity(); 37 uptr alignment = granularity * 8; 38 uptr left_padding = granularity; 39 uptr shadow_size = PremapShadowSize(); 40 uptr map_size = shadow_size + left_padding + alignment; 41 42 uptr map_start = (uptr)MmapNoAccess(map_size); 43 CHECK_NE(map_start, ~(uptr)0); 44 45 uptr shadow_start = RoundUpTo(map_start + left_padding, alignment); 46 uptr shadow_end = shadow_start + shadow_size; 47 internal_munmap(reinterpret_cast<void *>(map_start), 48 shadow_start - left_padding - map_start); 49 internal_munmap(reinterpret_cast<void *>(shadow_end), 50 map_start + map_size - shadow_end); 51 return shadow_start; 52 } 53 PremapShadowFailed()54bool PremapShadowFailed() { 55 uptr shadow = reinterpret_cast<uptr>(&__asan_shadow); 56 uptr resolver = reinterpret_cast<uptr>(&__asan_premap_shadow); 57 // shadow == resolver is how Android KitKat and older handles ifunc. 58 // shadow == 0 just in case. 59 if (shadow == 0 || shadow == resolver) 60 return true; 61 return false; 62 } 63 } // namespace __asan 64 65 extern "C" { __asan_premap_shadow()66decltype(__asan_shadow)* __asan_premap_shadow() { 67 // The resolver may be called multiple times. Map the shadow just once. 68 static uptr premapped_shadow = 0; 69 if (!premapped_shadow) premapped_shadow = __asan::PremapShadow(); 70 return reinterpret_cast<decltype(__asan_shadow)*>(premapped_shadow); 71 } 72 73 // __asan_shadow is a "function" that has the same address as the first byte of 74 // the shadow mapping. 75 INTERFACE_ATTRIBUTE __attribute__((ifunc("__asan_premap_shadow"))) void 76 __asan_shadow(); 77 } 78 79 #endif // ASAN_PREMAP_SHADOW 80