1*3cab2bb3Spatrick //===-- msan_linux.cpp ----------------------------------------------------===// 2*3cab2bb3Spatrick // 3*3cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4*3cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information. 5*3cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6*3cab2bb3Spatrick // 7*3cab2bb3Spatrick //===----------------------------------------------------------------------===// 8*3cab2bb3Spatrick // 9*3cab2bb3Spatrick // This file is a part of MemorySanitizer. 10*3cab2bb3Spatrick // 11*3cab2bb3Spatrick // Linux-, NetBSD- and FreeBSD-specific code. 12*3cab2bb3Spatrick //===----------------------------------------------------------------------===// 13*3cab2bb3Spatrick 14*3cab2bb3Spatrick #include "sanitizer_common/sanitizer_platform.h" 15*3cab2bb3Spatrick #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD 16*3cab2bb3Spatrick 17*3cab2bb3Spatrick #include "msan.h" 18*3cab2bb3Spatrick #include "msan_report.h" 19*3cab2bb3Spatrick #include "msan_thread.h" 20*3cab2bb3Spatrick 21*3cab2bb3Spatrick #include <elf.h> 22*3cab2bb3Spatrick #include <link.h> 23*3cab2bb3Spatrick #include <pthread.h> 24*3cab2bb3Spatrick #include <stdio.h> 25*3cab2bb3Spatrick #include <stdlib.h> 26*3cab2bb3Spatrick #include <signal.h> 27*3cab2bb3Spatrick #include <unistd.h> 28*3cab2bb3Spatrick #include <unwind.h> 29*3cab2bb3Spatrick #include <execinfo.h> 30*3cab2bb3Spatrick #include <sys/time.h> 31*3cab2bb3Spatrick #include <sys/resource.h> 32*3cab2bb3Spatrick 33*3cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h" 34*3cab2bb3Spatrick #include "sanitizer_common/sanitizer_procmaps.h" 35*3cab2bb3Spatrick 36*3cab2bb3Spatrick namespace __msan { 37*3cab2bb3Spatrick 38*3cab2bb3Spatrick void ReportMapRange(const char *descr, uptr beg, uptr size) { 39*3cab2bb3Spatrick if (size > 0) { 40*3cab2bb3Spatrick uptr end = beg + size - 1; 41*3cab2bb3Spatrick VPrintf(1, "%s : %p - %p\n", descr, beg, end); 42*3cab2bb3Spatrick } 43*3cab2bb3Spatrick } 44*3cab2bb3Spatrick 45*3cab2bb3Spatrick static bool CheckMemoryRangeAvailability(uptr beg, uptr size) { 46*3cab2bb3Spatrick if (size > 0) { 47*3cab2bb3Spatrick uptr end = beg + size - 1; 48*3cab2bb3Spatrick if (!MemoryRangeIsAvailable(beg, end)) { 49*3cab2bb3Spatrick Printf("FATAL: Memory range %p - %p is not available.\n", beg, end); 50*3cab2bb3Spatrick return false; 51*3cab2bb3Spatrick } 52*3cab2bb3Spatrick } 53*3cab2bb3Spatrick return true; 54*3cab2bb3Spatrick } 55*3cab2bb3Spatrick 56*3cab2bb3Spatrick static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) { 57*3cab2bb3Spatrick if (size > 0) { 58*3cab2bb3Spatrick void *addr = MmapFixedNoAccess(beg, size, name); 59*3cab2bb3Spatrick if (beg == 0 && addr) { 60*3cab2bb3Spatrick // Depending on the kernel configuration, we may not be able to protect 61*3cab2bb3Spatrick // the page at address zero. 62*3cab2bb3Spatrick uptr gap = 16 * GetPageSizeCached(); 63*3cab2bb3Spatrick beg += gap; 64*3cab2bb3Spatrick size -= gap; 65*3cab2bb3Spatrick addr = MmapFixedNoAccess(beg, size, name); 66*3cab2bb3Spatrick } 67*3cab2bb3Spatrick if ((uptr)addr != beg) { 68*3cab2bb3Spatrick uptr end = beg + size - 1; 69*3cab2bb3Spatrick Printf("FATAL: Cannot protect memory range %p - %p (%s).\n", beg, end, 70*3cab2bb3Spatrick name); 71*3cab2bb3Spatrick return false; 72*3cab2bb3Spatrick } 73*3cab2bb3Spatrick } 74*3cab2bb3Spatrick return true; 75*3cab2bb3Spatrick } 76*3cab2bb3Spatrick 77*3cab2bb3Spatrick static void CheckMemoryLayoutSanity() { 78*3cab2bb3Spatrick uptr prev_end = 0; 79*3cab2bb3Spatrick for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 80*3cab2bb3Spatrick uptr start = kMemoryLayout[i].start; 81*3cab2bb3Spatrick uptr end = kMemoryLayout[i].end; 82*3cab2bb3Spatrick MappingDesc::Type type = kMemoryLayout[i].type; 83*3cab2bb3Spatrick CHECK_LT(start, end); 84*3cab2bb3Spatrick CHECK_EQ(prev_end, start); 85*3cab2bb3Spatrick CHECK(addr_is_type(start, type)); 86*3cab2bb3Spatrick CHECK(addr_is_type((start + end) / 2, type)); 87*3cab2bb3Spatrick CHECK(addr_is_type(end - 1, type)); 88*3cab2bb3Spatrick if (type == MappingDesc::APP) { 89*3cab2bb3Spatrick uptr addr = start; 90*3cab2bb3Spatrick CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 91*3cab2bb3Spatrick CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 92*3cab2bb3Spatrick CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 93*3cab2bb3Spatrick 94*3cab2bb3Spatrick addr = (start + end) / 2; 95*3cab2bb3Spatrick CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 96*3cab2bb3Spatrick CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 97*3cab2bb3Spatrick CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 98*3cab2bb3Spatrick 99*3cab2bb3Spatrick addr = end - 1; 100*3cab2bb3Spatrick CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr))); 101*3cab2bb3Spatrick CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr))); 102*3cab2bb3Spatrick CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr))); 103*3cab2bb3Spatrick } 104*3cab2bb3Spatrick prev_end = end; 105*3cab2bb3Spatrick } 106*3cab2bb3Spatrick } 107*3cab2bb3Spatrick 108*3cab2bb3Spatrick bool InitShadow(bool init_origins) { 109*3cab2bb3Spatrick // Let user know mapping parameters first. 110*3cab2bb3Spatrick VPrintf(1, "__msan_init %p\n", &__msan_init); 111*3cab2bb3Spatrick for (unsigned i = 0; i < kMemoryLayoutSize; ++i) 112*3cab2bb3Spatrick VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start, 113*3cab2bb3Spatrick kMemoryLayout[i].end - 1); 114*3cab2bb3Spatrick 115*3cab2bb3Spatrick CheckMemoryLayoutSanity(); 116*3cab2bb3Spatrick 117*3cab2bb3Spatrick if (!MEM_IS_APP(&__msan_init)) { 118*3cab2bb3Spatrick Printf("FATAL: Code %p is out of application range. Non-PIE build?\n", 119*3cab2bb3Spatrick (uptr)&__msan_init); 120*3cab2bb3Spatrick return false; 121*3cab2bb3Spatrick } 122*3cab2bb3Spatrick 123*3cab2bb3Spatrick const uptr maxVirtualAddress = GetMaxUserVirtualAddress(); 124*3cab2bb3Spatrick 125*3cab2bb3Spatrick for (unsigned i = 0; i < kMemoryLayoutSize; ++i) { 126*3cab2bb3Spatrick uptr start = kMemoryLayout[i].start; 127*3cab2bb3Spatrick uptr end = kMemoryLayout[i].end; 128*3cab2bb3Spatrick uptr size = end - start; 129*3cab2bb3Spatrick MappingDesc::Type type = kMemoryLayout[i].type; 130*3cab2bb3Spatrick 131*3cab2bb3Spatrick // Check if the segment should be mapped based on platform constraints. 132*3cab2bb3Spatrick if (start >= maxVirtualAddress) 133*3cab2bb3Spatrick continue; 134*3cab2bb3Spatrick 135*3cab2bb3Spatrick bool map = type == MappingDesc::SHADOW || 136*3cab2bb3Spatrick (init_origins && type == MappingDesc::ORIGIN); 137*3cab2bb3Spatrick bool protect = type == MappingDesc::INVALID || 138*3cab2bb3Spatrick (!init_origins && type == MappingDesc::ORIGIN); 139*3cab2bb3Spatrick CHECK(!(map && protect)); 140*3cab2bb3Spatrick if (!map && !protect) 141*3cab2bb3Spatrick CHECK(type == MappingDesc::APP); 142*3cab2bb3Spatrick if (map) { 143*3cab2bb3Spatrick if (!CheckMemoryRangeAvailability(start, size)) 144*3cab2bb3Spatrick return false; 145*3cab2bb3Spatrick if (!MmapFixedNoReserve(start, size, kMemoryLayout[i].name)) 146*3cab2bb3Spatrick return false; 147*3cab2bb3Spatrick if (common_flags()->use_madv_dontdump) 148*3cab2bb3Spatrick DontDumpShadowMemory(start, size); 149*3cab2bb3Spatrick } 150*3cab2bb3Spatrick if (protect) { 151*3cab2bb3Spatrick if (!CheckMemoryRangeAvailability(start, size)) 152*3cab2bb3Spatrick return false; 153*3cab2bb3Spatrick if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name)) 154*3cab2bb3Spatrick return false; 155*3cab2bb3Spatrick } 156*3cab2bb3Spatrick } 157*3cab2bb3Spatrick 158*3cab2bb3Spatrick return true; 159*3cab2bb3Spatrick } 160*3cab2bb3Spatrick 161*3cab2bb3Spatrick static void MsanAtExit(void) { 162*3cab2bb3Spatrick if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) 163*3cab2bb3Spatrick ReportStats(); 164*3cab2bb3Spatrick if (msan_report_count > 0) { 165*3cab2bb3Spatrick ReportAtExitStatistics(); 166*3cab2bb3Spatrick if (common_flags()->exitcode) 167*3cab2bb3Spatrick internal__exit(common_flags()->exitcode); 168*3cab2bb3Spatrick } 169*3cab2bb3Spatrick } 170*3cab2bb3Spatrick 171*3cab2bb3Spatrick void InstallAtExitHandler() { 172*3cab2bb3Spatrick atexit(MsanAtExit); 173*3cab2bb3Spatrick } 174*3cab2bb3Spatrick 175*3cab2bb3Spatrick // ---------------------- TSD ---------------- {{{1 176*3cab2bb3Spatrick 177*3cab2bb3Spatrick #if SANITIZER_NETBSD 178*3cab2bb3Spatrick // Thread Static Data cannot be used in early init on NetBSD. 179*3cab2bb3Spatrick // Reuse the MSan TSD API for compatibility with existing code 180*3cab2bb3Spatrick // with an alternative implementation. 181*3cab2bb3Spatrick 182*3cab2bb3Spatrick static void (*tsd_destructor)(void *tsd) = nullptr; 183*3cab2bb3Spatrick 184*3cab2bb3Spatrick struct tsd_key { 185*3cab2bb3Spatrick tsd_key() : key(nullptr) {} 186*3cab2bb3Spatrick ~tsd_key() { 187*3cab2bb3Spatrick CHECK(tsd_destructor); 188*3cab2bb3Spatrick if (key) 189*3cab2bb3Spatrick (*tsd_destructor)(key); 190*3cab2bb3Spatrick } 191*3cab2bb3Spatrick MsanThread *key; 192*3cab2bb3Spatrick }; 193*3cab2bb3Spatrick 194*3cab2bb3Spatrick static thread_local struct tsd_key key; 195*3cab2bb3Spatrick 196*3cab2bb3Spatrick void MsanTSDInit(void (*destructor)(void *tsd)) { 197*3cab2bb3Spatrick CHECK(!tsd_destructor); 198*3cab2bb3Spatrick tsd_destructor = destructor; 199*3cab2bb3Spatrick } 200*3cab2bb3Spatrick 201*3cab2bb3Spatrick MsanThread *GetCurrentThread() { 202*3cab2bb3Spatrick CHECK(tsd_destructor); 203*3cab2bb3Spatrick return key.key; 204*3cab2bb3Spatrick } 205*3cab2bb3Spatrick 206*3cab2bb3Spatrick void SetCurrentThread(MsanThread *tsd) { 207*3cab2bb3Spatrick CHECK(tsd_destructor); 208*3cab2bb3Spatrick CHECK(tsd); 209*3cab2bb3Spatrick CHECK(!key.key); 210*3cab2bb3Spatrick key.key = tsd; 211*3cab2bb3Spatrick } 212*3cab2bb3Spatrick 213*3cab2bb3Spatrick void MsanTSDDtor(void *tsd) { 214*3cab2bb3Spatrick CHECK(tsd_destructor); 215*3cab2bb3Spatrick CHECK_EQ(key.key, tsd); 216*3cab2bb3Spatrick key.key = nullptr; 217*3cab2bb3Spatrick // Make sure that signal handler can not see a stale current thread pointer. 218*3cab2bb3Spatrick atomic_signal_fence(memory_order_seq_cst); 219*3cab2bb3Spatrick MsanThread::TSDDtor(tsd); 220*3cab2bb3Spatrick } 221*3cab2bb3Spatrick #else 222*3cab2bb3Spatrick static pthread_key_t tsd_key; 223*3cab2bb3Spatrick static bool tsd_key_inited = false; 224*3cab2bb3Spatrick 225*3cab2bb3Spatrick void MsanTSDInit(void (*destructor)(void *tsd)) { 226*3cab2bb3Spatrick CHECK(!tsd_key_inited); 227*3cab2bb3Spatrick tsd_key_inited = true; 228*3cab2bb3Spatrick CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 229*3cab2bb3Spatrick } 230*3cab2bb3Spatrick 231*3cab2bb3Spatrick static THREADLOCAL MsanThread* msan_current_thread; 232*3cab2bb3Spatrick 233*3cab2bb3Spatrick MsanThread *GetCurrentThread() { 234*3cab2bb3Spatrick return msan_current_thread; 235*3cab2bb3Spatrick } 236*3cab2bb3Spatrick 237*3cab2bb3Spatrick void SetCurrentThread(MsanThread *t) { 238*3cab2bb3Spatrick // Make sure we do not reset the current MsanThread. 239*3cab2bb3Spatrick CHECK_EQ(0, msan_current_thread); 240*3cab2bb3Spatrick msan_current_thread = t; 241*3cab2bb3Spatrick // Make sure that MsanTSDDtor gets called at the end. 242*3cab2bb3Spatrick CHECK(tsd_key_inited); 243*3cab2bb3Spatrick pthread_setspecific(tsd_key, (void *)t); 244*3cab2bb3Spatrick } 245*3cab2bb3Spatrick 246*3cab2bb3Spatrick void MsanTSDDtor(void *tsd) { 247*3cab2bb3Spatrick MsanThread *t = (MsanThread*)tsd; 248*3cab2bb3Spatrick if (t->destructor_iterations_ > 1) { 249*3cab2bb3Spatrick t->destructor_iterations_--; 250*3cab2bb3Spatrick CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 251*3cab2bb3Spatrick return; 252*3cab2bb3Spatrick } 253*3cab2bb3Spatrick msan_current_thread = nullptr; 254*3cab2bb3Spatrick // Make sure that signal handler can not see a stale current thread pointer. 255*3cab2bb3Spatrick atomic_signal_fence(memory_order_seq_cst); 256*3cab2bb3Spatrick MsanThread::TSDDtor(tsd); 257*3cab2bb3Spatrick } 258*3cab2bb3Spatrick #endif 259*3cab2bb3Spatrick 260*3cab2bb3Spatrick } // namespace __msan 261*3cab2bb3Spatrick 262*3cab2bb3Spatrick #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD 263