178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===-- msan_linux.cc -----------------------------------------------------===// 278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// 378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// The LLVM Compiler Infrastructure 478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// 578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// This file is distributed under the University of Illinois Open Source 678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// License. See LICENSE.TXT for details. 778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// 878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===----------------------------------------------------------------------===// 978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// 1078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// This file is a part of MemorySanitizer. 1178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// 1278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov// Linux-specific code. 1378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov//===----------------------------------------------------------------------===// 1478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 1524e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#include "sanitizer_common/sanitizer_platform.h" 1624e13723f8477d8c42ab8b2a7f4f69fc089842f1Evgeniy Stepanov#if SANITIZER_LINUX 1778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 1878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "msan.h" 192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include "msan_thread.h" 2078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 210f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner#include <elf.h> 220f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner#include <link.h> 232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines#include <pthread.h> 2478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <stdio.h> 2578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <stdlib.h> 2678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <signal.h> 2778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <unistd.h> 2878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <unwind.h> 2978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <execinfo.h> 3078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <sys/time.h> 3178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include <sys/resource.h> 3278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 3378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_common.h" 3478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#include "sanitizer_common/sanitizer_procmaps.h" 3578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 3678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovnamespace __msan { 3778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 3878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kMemBeg = 0x600000000000; 3978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kMemEnd = 0x7fffffffffff; 4078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kShadowBeg = MEM_TO_SHADOW(kMemBeg); 4178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kShadowEnd = MEM_TO_SHADOW(kMemEnd); 422d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic const uptr kBad1Beg = 0; 4378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kBad1End = kShadowBeg - 1; 4478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kBad2Beg = kShadowEnd + 1; 4578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kBad2End = kMemBeg - 1; 4678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kOriginsBeg = kBad2Beg; 4778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovstatic const uptr kOriginsEnd = kBad2End; 4878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 4978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovbool InitShadow(bool prot1, bool prot2, bool map_shadow, bool init_origins) { 5062355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov if ((uptr) & InitShadow < kMemBeg) { 5162355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov Printf("FATAL: Code below application range: %p < %p. Non-PIE build?\n", 5262355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov &InitShadow, (void *)kMemBeg); 5362355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov return false; 5462355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov } 5562355e98e83906e99a792441a72362005c740d4dEvgeniy Stepanov 562d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "__msan_init %p\n", &__msan_init); 572d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "Memory : %p %p\n", kMemBeg, kMemEnd); 582d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "Bad2 : %p %p\n", kBad2Beg, kBad2End); 592d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "Origins : %p %p\n", kOriginsBeg, kOriginsEnd); 602d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "Shadow : %p %p\n", kShadowBeg, kShadowEnd); 612d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines VPrintf(1, "Bad1 : %p %p\n", kBad1Beg, kBad1End); 6278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 634c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov if (!MemoryRangeIsAvailable(kShadowBeg, 642d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines init_origins ? kOriginsEnd : kShadowEnd) || 652d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (prot1 && !MemoryRangeIsAvailable(kBad1Beg, kBad1End)) || 662d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines (prot2 && !MemoryRangeIsAvailable(kBad2Beg, kBad2End))) { 674c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov Printf("FATAL: Shadow memory range is not available.\n"); 684c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov return false; 694c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov } 704c9ddc143839c9f4b79152737cd2869c99e8e86dEvgeniy Stepanov 7178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov if (prot1 && !Mprotect(kBad1Beg, kBad1End - kBad1Beg)) 7278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov return false; 7378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov if (prot2 && !Mprotect(kBad2Beg, kBad2End - kBad2Beg)) 7478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov return false; 7578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov if (map_shadow) { 7678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowEnd - kShadowBeg); 7778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov if (shadow != (void*)kShadowBeg) return false; 7878c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov } 7978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov if (init_origins) { 8078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsEnd - kOriginsBeg); 8178c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov if (origins != (void*)kOriginsBeg) return false; 8278c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov } 8378c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov return true; 8478c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov} 8578c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 8678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanovvoid MsanDie() { 872d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (death_callback) 882d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines death_callback(); 8978c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov _exit(flags()->exit_code); 9078c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov} 9199bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov 9299bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanovstatic void MsanAtExit(void) { 935d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines if (flags()->print_stats && (flags()->atexit || msan_report_count > 0)) 945d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines ReportStats(); 9599bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov if (msan_report_count > 0) { 9699bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov ReportAtExitStatistics(); 975d71de26cedae3dafc17449fe0182045c0bd20e8Stephen Hines if (flags()->exit_code) _exit(flags()->exit_code); 9899bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov } 9999bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov} 10099bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov 10199bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanovvoid InstallAtExitHandler() { 10299bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov atexit(MsanAtExit); 10399bf1d71c634ab0ed39d7614fd8f8f2c2201e111Evgeniy Stepanov} 1040f92deb81207c80481ff0257fbaba640fe669633Reid Kleckner 1052d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines// ---------------------- TSD ---------------- {{{1 1062d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1072d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic pthread_key_t tsd_key; 1082d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesstatic bool tsd_key_inited = false; 1092d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MsanTSDInit(void (*destructor)(void *tsd)) { 1102d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(!tsd_key_inited); 1112d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines tsd_key_inited = true; 1122d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_EQ(0, pthread_key_create(&tsd_key, destructor)); 1132d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1142d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1152d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid *MsanTSDGet() { 1162d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(tsd_key_inited); 1172d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return pthread_getspecific(tsd_key); 1182d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1192d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1202d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MsanTSDSet(void *tsd) { 1212d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK(tsd_key_inited); 1222d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines pthread_setspecific(tsd_key, tsd); 1232d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1242d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 1252d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hinesvoid MsanTSDDtor(void *tsd) { 1262d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MsanThread *t = (MsanThread*)tsd; 1272d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines if (t->destructor_iterations_ > 1) { 1282d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines t->destructor_iterations_--; 1292d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines CHECK_EQ(0, pthread_setspecific(tsd_key, tsd)); 1302d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines return; 1312d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines } 1322d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines MsanThread::TSDDtor(tsd); 1332d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines} 1342d1fdb26e458c4ddc04155c1d421bced3ba90cd0Stephen Hines 135ba5e99668e3030cc5bab357a04271a1bdbac209cAlexey Samsonov} // namespace __msan 13678c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov 13778c56c3c407d2c92825c86e6af7a0230d6019a1cEvgeniy Stepanov#endif // __linux__ 138