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