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 (!MmapNoAccess(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 static void CheckMemoryLayoutSanity() { 68 uptr prev_end = 0; 69 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 70 uptr start = kMemoryLayout[i].start; 71 uptr end = kMemoryLayout[i].end; 72 MappingDesc::Type type = kMemoryLayout[i].type; 73 CHECK_LT(start, end); 74 CHECK_EQ(prev_end, start); 75 CHECK(addr_is_type(start, type)); 76 CHECK(addr_is_type((start + end) / 2, type)); 77 CHECK(addr_is_type(end - 1, type)); 78 if (type == MappingDesc::APP) { 79 uptr addr = start; 80 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 81 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 82 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 83 84 addr = (start + end) / 2; 85 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 86 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 87 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 88 89 addr = end - 1; 90 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 91 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 92 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 93 } 94 prev_end = end; 95 } 96 } 97 98 bool InitShadow(bool map_shadow, bool init_origins) { 99 // Let user know mapping parameters first. 100 VPrintf(1, "__msan_init %p\n", &__msan_init); 101 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) 102 VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start, 103 kMemoryLayout[i].end - 1); 104 105 CheckMemoryLayoutSanity(); 106 107 if (!MEM_IS_APP(&__msan_init)) { 108 Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", 109 (uptr)&__msan_init); 110 return false; 111 } 112 113 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 114 uptr start = kMemoryLayout[i].start; 115 uptr end = kMemoryLayout[i].end; 116 uptr size= end - start; 117 MappingDesc::Type type = kMemoryLayout[i].type; 118 if ((map_shadow && type == MappingDesc::SHADOW) || 119 (init_origins && type == MappingDesc::ORIGIN)) { 120 if (!CheckMemoryRangeAvailability(start, size)) return false; 121 if ((uptr)MmapFixedNoReserve(start, size) != start) return false; 122 if (common_flags()->use_madv_dontdump) 123 DontDumpShadowMemory(start, size); 124 } else if (type == MappingDesc::INVALID) { 125 if (!CheckMemoryRangeAvailability(start, size)) return false; 126 if (!ProtectMemoryRange(start, size)) return false; 127 } 128 } 129 130 return true; 131 } 132 133 void MsanDie() { 134 if (common_flags()->coverage) 135 __sanitizer_cov_dump(); 136 if (death_callback) 137 death_callback(); 138 internal__exit(flags()->exit_code); 139 } 140 141 static void MsanAtExit(void) { 142 if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) 143 ReportStats(); 144 if (msan_report_count > 0) { 145 ReportAtExitStatistics(); 146 if (flags()->exit_code) _exit(flags()->exit_code); 147 } 148 } 149 150 void InstallAtExitHandler() { 151 atexit(MsanAtExit); 152 } 153 154 // ---------------------- TSD ---------------- {{{1 155 156 static pthread_key_t tsd_key; 157 static bool tsd_key_inited = false; 158 159 void MsanTSDInit(void (*destructor)(void *tsd)) { 160 CHECK(!tsd_key_inited); 161 tsd_key_inited = true; 162 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 163 } 164 165 static THREADLOCAL MsanThread* msan_current_thread; 166 167 MsanThread *GetCurrentThread() { 168 return msan_current_thread; 169 } 170 171 void SetCurrentThread(MsanThread *t) { 172 // Make sure we do not reset the current MsanThread. 173 CHECK_EQ(0, msan_current_thread); 174 msan_current_thread = t; 175 // Make sure that MsanTSDDtor gets called at the end. 176 CHECK(tsd_key_inited); 177 pthread_setspecific(tsd_key, (void *)t); 178 } 179 180 void MsanTSDDtor(void *tsd) { 181 MsanThread *t = (MsanThread*)tsd; 182 if (t->destructor_iterations_ > 1) { 183 t->destructor_iterations_--; 184 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 185 return; 186 } 187 msan_current_thread = nullptr; 188 // Make sure that signal handler can not see a stale current thread pointer. 189 atomic_signal_fence(memory_order_seq_cst); 190 MsanThread::TSDDtor(tsd); 191 } 192 193 } // namespace __msan 194 195 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX 196