1 //===-- msan_linux.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 MemorySanitizer. 11 // 12 // Linux- and FreeBSD-specific code. 13 //===----------------------------------------------------------------------===// 14 15 #include "sanitizer_common/sanitizer_platform.h" 16 #if SANITIZER_FREEBSD || SANITIZER_LINUX 17 18 #include "msan.h" 19 #include "msan_thread.h" 20 21 #include <elf.h> 22 #include <link.h> 23 #include <pthread.h> 24 #include <stdio.h> 25 #include <stdlib.h> 26 #include <signal.h> 27 #include <unistd.h> 28 #include <unwind.h> 29 #include <execinfo.h> 30 #include <sys/time.h> 31 #include <sys/resource.h> 32 33 #include "sanitizer_common/sanitizer_common.h" 34 #include "sanitizer_common/sanitizer_procmaps.h" 35 36 namespace __msan { 37 38 void ReportMapRange(const char *descr, uptr beg, uptr size) { 39 if (size > 0) { 40 uptr end = beg + size - 1; 41 VPrintf(1, "%s : %p - %p\n", descr, beg, end); 42 } 43 } 44 45 static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { 46 if (size > 0) { 47 uptr end = beg + size - 1; 48 if (!MemoryRangeIsAvailable(beg, end)) { 49 Printf("FATAL: Memory range %p - %p is not available.\n", beg, end); 50 return false; 51 } 52 } 53 return true; 54 } 55 56 static bool ProtectMemoryRange(uptr beg, uptr size) { 57 if (size > 0) { 58 uptr end = beg + size - 1; 59 if (!Mprotect(beg, size)) { 60 Printf("FATAL: Cannot protect memory range %p - %p.\n", beg, end); 61 return false; 62 } 63 } 64 return true; 65 } 66 67 bool InitShadow(bool map_shadow, bool init_origins) { 68 // Let user know mapping parameters first. 69 VPrintf(1, "__msan_init %p\n", &__msan_init); 70 ReportMapRange("Low Memory ", kLowMemBeg, kLowMemSize); 71 ReportMapRange("Bad1 ", kBad1Beg, kBad1Size); 72 ReportMapRange("Shadow ", kShadowBeg, kShadowSize); 73 ReportMapRange("Bad2 ", kBad2Beg, kBad2Size); 74 ReportMapRange("Origins ", kOriginsBeg, kOriginsSize); 75 ReportMapRange("Bad3 ", kBad3Beg, kBad3Size); 76 ReportMapRange("High Memory", kHighMemBeg, kHighMemSize); 77 78 // Check mapping sanity (the invariant). 79 CHECK_EQ(kLowMemBeg, 0); 80 CHECK_EQ(kBad1Beg, kLowMemBeg + kLowMemSize); 81 CHECK_EQ(kShadowBeg, kBad1Beg + kBad1Size); 82 CHECK_GT(kShadowSize, 0); 83 CHECK_GE(kShadowSize, kLowMemSize + kHighMemSize); 84 CHECK_EQ(kBad2Beg, kShadowBeg + kShadowSize); 85 CHECK_EQ(kOriginsBeg, kBad2Beg + kBad2Size); 86 CHECK_EQ(kOriginsSize, kShadowSize); 87 CHECK_EQ(kBad3Beg, kOriginsBeg + kOriginsSize); 88 CHECK_EQ(kHighMemBeg, kBad3Beg + kBad3Size); 89 CHECK_GT(kHighMemSize, 0); 90 CHECK_GE(kHighMemBeg + kHighMemSize, kHighMemBeg); // Tests for no overflow. 91 92 if (kLowMemSize > 0) { 93 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kLowMemBeg))); 94 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kLowMemBeg + kLowMemSize - 1))); 95 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kLowMemBeg))); 96 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kLowMemBeg + kLowMemSize - 1))); 97 } 98 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kHighMemBeg))); 99 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kHighMemBeg + kHighMemSize - 1))); 100 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kHighMemBeg))); 101 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kHighMemBeg + kHighMemSize - 1))); 102 103 if (!MEM_IS_APP(&__msan_init)) { 104 Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", 105 (uptr)&__msan_init); 106 return false; 107 } 108 109 if (!CheckMemoryRangeAvailability(kShadowBeg, kShadowSize) || 110 (init_origins && 111 !CheckMemoryRangeAvailability(kOriginsBeg, kOriginsSize)) || 112 !CheckMemoryRangeAvailability(kBad1Beg, kBad1Size) || 113 !CheckMemoryRangeAvailability(kBad2Beg, kBad2Size) || 114 !CheckMemoryRangeAvailability(kBad3Beg, kBad3Size)) { 115 return false; 116 } 117 118 if (!ProtectMemoryRange(kBad1Beg, kBad1Size) || 119 !ProtectMemoryRange(kBad2Beg, kBad2Size) || 120 !ProtectMemoryRange(kBad3Beg, kBad3Size)) { 121 return false; 122 } 123 124 if (map_shadow) { 125 void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowSize); 126 if (shadow != (void*)kShadowBeg) return false; 127 } 128 if (init_origins) { 129 void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsSize); 130 if (origins != (void*)kOriginsBeg) return false; 131 } 132 return true; 133 } 134 135 void MsanDie() { 136 if (common_flags()->coverage) 137 __sanitizer_cov_dump(); 138 if (death_callback) 139 death_callback(); 140 _exit(flags()->exit_code); 141 } 142 143 static void MsanAtExit(void) { 144 if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) 145 ReportStats(); 146 if (msan_report_count > 0) { 147 ReportAtExitStatistics(); 148 if (flags()->exit_code) _exit(flags()->exit_code); 149 } 150 } 151 152 void InstallAtExitHandler() { 153 atexit(MsanAtExit); 154 } 155 156 // ---------------------- TSD ---------------- {{{1 157 158 static pthread_key_t tsd_key; 159 static bool tsd_key_inited = false; 160 void MsanTSDInit(void (*destructor)(void *tsd)) { 161 CHECK(!tsd_key_inited); 162 tsd_key_inited = true; 163 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 164 } 165 166 void *MsanTSDGet() { 167 CHECK(tsd_key_inited); 168 return pthread_getspecific(tsd_key); 169 } 170 171 void MsanTSDSet(void *tsd) { 172 CHECK(tsd_key_inited); 173 pthread_setspecific(tsd_key, tsd); 174 } 175 176 void MsanTSDDtor(void *tsd) { 177 MsanThread *t = (MsanThread*)tsd; 178 if (t->destructor_iterations_ > 1) { 179 t->destructor_iterations_--; 180 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 181 return; 182 } 183 MsanThread::TSDDtor(tsd); 184 } 185 186 } // namespace __msan 187 188 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX 189