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