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