1 //===-- msan_linux.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 MemorySanitizer. 10 // 11 // Linux-, NetBSD- and FreeBSD-specific code. 12 //===----------------------------------------------------------------------===// 13 14 #include "sanitizer_common/sanitizer_platform.h" 15 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD 16 17 # include <elf.h> 18 # include <link.h> 19 # include <pthread.h> 20 # include <signal.h> 21 # include <stdio.h> 22 # include <stdlib.h> 23 # if SANITIZER_LINUX 24 # include <sys/personality.h> 25 # endif 26 # include <sys/resource.h> 27 # include <sys/time.h> 28 # include <unistd.h> 29 # include <unwind.h> 30 31 # include "msan.h" 32 # include "msan_allocator.h" 33 # include "msan_chained_origin_depot.h" 34 # include "msan_report.h" 35 # include "msan_thread.h" 36 # include "sanitizer_common/sanitizer_common.h" 37 # include "sanitizer_common/sanitizer_procmaps.h" 38 # include "sanitizer_common/sanitizer_stackdepot.h" 39 40 namespace __msan { 41 42 void ReportMapRange(const char *descr, uptr beg, uptr size) { 43 if (size > 0) { 44 uptr end = beg + size - 1; 45 VPrintf(1, "%s : %p-%p\n", descr, (void *)beg, (void *)end); 46 } 47 } 48 49 static bool CheckMemoryRangeAvailability(uptr beg, uptr size, bool verbose) { 50 if (size > 0) { 51 uptr end = beg + size - 1; 52 if (!MemoryRangeIsAvailable(beg, end)) { 53 if (verbose) 54 Printf("FATAL: MemorySanitizer: Shadow range %p-%p is not available.\n", 55 (void *)beg, (void *)end); 56 return false; 57 } 58 } 59 return true; 60 } 61 62 static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) { 63 if (size > 0) { 64 void *addr = MmapFixedNoAccess(beg, size, name); 65 if (beg == 0 && addr) { 66 // Depending on the kernel configuration, we may not be able to protect 67 // the page at address zero. 68 uptr gap = 16 * GetPageSizeCached(); 69 beg += gap; 70 size -= gap; 71 addr = MmapFixedNoAccess(beg, size, name); 72 } 73 if ((uptr)addr != beg) { 74 uptr end = beg + size - 1; 75 Printf( 76 "FATAL: MemorySanitizer: Cannot protect memory range %p-%p (%s).\n", 77 (void *)beg, (void *)end, name); 78 return false; 79 } 80 } 81 return true; 82 } 83 84 static void CheckMemoryLayoutSanity() { 85 uptr prev_end = 0; 86 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 87 uptr start = kMemoryLayout[i].start; 88 uptr end = kMemoryLayout[i].end; 89 MappingDesc::Type type = kMemoryLayout[i].type; 90 CHECK_LT(start, end); 91 CHECK_EQ(prev_end, start); 92 CHECK(addr_is_type(start, type)); 93 CHECK(addr_is_type((start + end) / 2, type)); 94 CHECK(addr_is_type(end - 1, type)); 95 if (type == MappingDesc::APP || type == MappingDesc::ALLOCATOR) { 96 uptr addr = start; 97 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 98 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 99 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 100 101 addr = (start + end) / 2; 102 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 103 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 104 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 105 106 addr = end - 1; 107 CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 108 CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 109 CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 110 } 111 prev_end = end; 112 } 113 } 114 115 static bool InitShadow(bool init_origins, bool dry_run) { 116 // Let user know mapping parameters first. 117 VPrintf(1, "__msan_init %p\n", reinterpret_cast<void *>(&__msan_init)); 118 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) 119 VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start, 120 kMemoryLayout[i].end - 1); 121 122 CheckMemoryLayoutSanity(); 123 124 if (!MEM_IS_APP(&__msan_init)) { 125 if (!dry_run) 126 Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", 127 reinterpret_cast<void *>(&__msan_init)); 128 return false; 129 } 130 131 const uptr maxVirtualAddress = GetMaxUserVirtualAddress(); 132 133 for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 134 uptr start = kMemoryLayout[i].start; 135 uptr end = kMemoryLayout[i].end; 136 uptr size = end - start; 137 MappingDesc::Type type = kMemoryLayout[i].type; 138 139 // Check if the segment should be mapped based on platform constraints. 140 if (start >= maxVirtualAddress) 141 continue; 142 143 bool map = type == MappingDesc::SHADOW || 144 (init_origins && type == MappingDesc::ORIGIN); 145 bool protect = type == MappingDesc::INVALID || 146 (!init_origins && type == MappingDesc::ORIGIN); 147 CHECK(!(map && protect)); 148 if (!map && !protect) { 149 CHECK(type == MappingDesc::APP || type == MappingDesc::ALLOCATOR); 150 151 if (dry_run && type == MappingDesc::ALLOCATOR && 152 !CheckMemoryRangeAvailability(start, size, !dry_run)) 153 return false; 154 } 155 if (map) { 156 if (dry_run && !CheckMemoryRangeAvailability(start, size, !dry_run)) 157 return false; 158 if (!dry_run && 159 !MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name)) 160 return false; 161 if (!dry_run && common_flags()->use_madv_dontdump) 162 DontDumpShadowMemory(start, size); 163 } 164 if (protect) { 165 if (dry_run && !CheckMemoryRangeAvailability(start, size, !dry_run)) 166 return false; 167 if (!dry_run && !ProtectMemoryRange(start, size, kMemoryLayout[i].name)) 168 return false; 169 } 170 } 171 172 return true; 173 } 174 175 bool InitShadowWithReExec(bool init_origins) { 176 // Start with dry run: check layout is ok, but don't print warnings because 177 // warning messages will cause tests to fail (even if we successfully re-exec 178 // after the warning). 179 bool success = InitShadow(init_origins, true); 180 if (!success) { 181 # if SANITIZER_LINUX 182 // Perhaps ASLR entropy is too high. If ASLR is enabled, re-exec without it. 183 int old_personality = personality(0xffffffff); 184 bool aslr_on = 185 (old_personality != -1) && ((old_personality & ADDR_NO_RANDOMIZE) == 0); 186 187 if (aslr_on) { 188 VReport(1, 189 "WARNING: MemorySanitizer: memory layout is incompatible, " 190 "possibly due to high-entropy ASLR.\n" 191 "Re-execing with fixed virtual address space.\n" 192 "N.B. reducing ASLR entropy is preferable.\n"); 193 CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1); 194 ReExec(); 195 } 196 # endif 197 } 198 199 // The earlier dry run didn't actually map or protect anything. Run again in 200 // non-dry run mode. 201 return success && InitShadow(init_origins, false); 202 } 203 204 static void MsanAtExit(void) { 205 if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) 206 ReportStats(); 207 if (msan_report_count > 0) { 208 ReportAtExitStatistics(); 209 if (common_flags()->exitcode) 210 internal__exit(common_flags()->exitcode); 211 } 212 } 213 214 void InstallAtExitHandler() { 215 atexit(MsanAtExit); 216 } 217 218 // ---------------------- TSD ---------------- {{{1 219 220 #if SANITIZER_NETBSD 221 // Thread Static Data cannot be used in early init on NetBSD. 222 // Reuse the MSan TSD API for compatibility with existing code 223 // with an alternative implementation. 224 225 static void (*tsd_destructor)(void *tsd) = nullptr; 226 227 struct tsd_key { 228 tsd_key() : key(nullptr) {} 229 ~tsd_key() { 230 CHECK(tsd_destructor); 231 if (key) 232 (*tsd_destructor)(key); 233 } 234 MsanThread *key; 235 }; 236 237 static thread_local struct tsd_key key; 238 239 void MsanTSDInit(void (*destructor)(void *tsd)) { 240 CHECK(!tsd_destructor); 241 tsd_destructor = destructor; 242 } 243 244 MsanThread *GetCurrentThread() { 245 CHECK(tsd_destructor); 246 return key.key; 247 } 248 249 void SetCurrentThread(MsanThread *tsd) { 250 CHECK(tsd_destructor); 251 CHECK(tsd); 252 CHECK(!key.key); 253 key.key = tsd; 254 } 255 256 void MsanTSDDtor(void *tsd) { 257 CHECK(tsd_destructor); 258 CHECK_EQ(key.key, tsd); 259 key.key = nullptr; 260 // Make sure that signal handler can not see a stale current thread pointer. 261 atomic_signal_fence(memory_order_seq_cst); 262 MsanThread::TSDDtor(tsd); 263 } 264 #else 265 static pthread_key_t tsd_key; 266 static bool tsd_key_inited = false; 267 268 void MsanTSDInit(void (*destructor)(void *tsd)) { 269 CHECK(!tsd_key_inited); 270 tsd_key_inited = true; 271 CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 272 } 273 274 static THREADLOCAL MsanThread* msan_current_thread; 275 276 MsanThread *GetCurrentThread() { 277 return msan_current_thread; 278 } 279 280 void SetCurrentThread(MsanThread *t) { 281 // Make sure we do not reset the current MsanThread. 282 CHECK_EQ(0, msan_current_thread); 283 msan_current_thread = t; 284 // Make sure that MsanTSDDtor gets called at the end. 285 CHECK(tsd_key_inited); 286 pthread_setspecific(tsd_key, (void *)t); 287 } 288 289 void MsanTSDDtor(void *tsd) { 290 MsanThread *t = (MsanThread*)tsd; 291 if (t->destructor_iterations_ > 1) { 292 t->destructor_iterations_--; 293 CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 294 return; 295 } 296 ScopedBlockSignals block(nullptr); 297 msan_current_thread = nullptr; 298 // Make sure that signal handler can not see a stale current thread pointer. 299 atomic_signal_fence(memory_order_seq_cst); 300 MsanThread::TSDDtor(tsd); 301 } 302 # endif 303 304 static void BeforeFork() { 305 // Usually we lock ThreadRegistry, but msan does not have one. 306 LockAllocator(); 307 StackDepotLockBeforeFork(); 308 ChainedOriginDepotBeforeFork(); 309 } 310 311 static void AfterFork(bool fork_child) { 312 ChainedOriginDepotAfterFork(fork_child); 313 StackDepotUnlockAfterFork(fork_child); 314 UnlockAllocator(); 315 // Usually we unlock ThreadRegistry, but msan does not have one. 316 } 317 318 void InstallAtForkHandler() { 319 pthread_atfork( 320 &BeforeFork, []() { AfterFork(/* fork_child= */ false); }, 321 []() { AfterFork(/* fork_child= */ true); }); 322 } 323 324 } // namespace __msan 325 326 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD 327