• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===-- msan_linux.cc -----------------------------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file is a part of MemorySanitizer.
11 //
12 // Linux- and FreeBSD-specific code.
13 //===----------------------------------------------------------------------===//
14 
15 #include "sanitizer_common/sanitizer_platform.h"
16 #if SANITIZER_FREEBSD || SANITIZER_LINUX
17 
18 #include "msan.h"
19 #include "msan_thread.h"
20 
21 #include <elf.h>
22 #include <link.h>
23 #include <pthread.h>
24 #include <stdio.h>
25 #include <stdlib.h>
26 #include <signal.h>
27 #include <unistd.h>
28 #include <unwind.h>
29 #include <execinfo.h>
30 #include <sys/time.h>
31 #include <sys/resource.h>
32 
33 #include "sanitizer_common/sanitizer_common.h"
34 #include "sanitizer_common/sanitizer_procmaps.h"
35 
36 namespace __msan {
37 
ReportMapRange(const char * descr,uptr beg,uptr size)38 void ReportMapRange(const char *descr, uptr beg, uptr size) {
39   if (size > 0) {
40     uptr end = beg + size - 1;
41     VPrintf(1, "%s : %p - %p\n", descr, beg, end);
42   }
43 }
44 
CheckMemoryRangeAvailability(uptr beg,uptr size)45 static bool CheckMemoryRangeAvailability(uptr beg, uptr size) {
46   if (size > 0) {
47     uptr end = beg + size - 1;
48     if (!MemoryRangeIsAvailable(beg, end)) {
49       Printf("FATAL: Memory range %p - %p is not available.\n", beg, end);
50       return false;
51     }
52   }
53   return true;
54 }
55 
ProtectMemoryRange(uptr beg,uptr size)56 static bool ProtectMemoryRange(uptr beg, uptr size) {
57   if (size > 0) {
58     uptr end = beg + size - 1;
59     if (!MmapNoAccess(beg, size)) {
60       Printf("FATAL: Cannot protect memory range %p - %p.\n", beg, end);
61       return false;
62     }
63   }
64   return true;
65 }
66 
CheckMemoryLayoutSanity()67 static void CheckMemoryLayoutSanity() {
68   uptr prev_end = 0;
69   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
70     uptr start = kMemoryLayout[i].start;
71     uptr end = kMemoryLayout[i].end;
72     MappingDesc::Type type = kMemoryLayout[i].type;
73     CHECK_LT(start, end);
74     CHECK_EQ(prev_end, start);
75     CHECK(addr_is_type(start, type));
76     CHECK(addr_is_type((start + end) / 2, type));
77     CHECK(addr_is_type(end - 1, type));
78     if (type == MappingDesc::APP) {
79       uptr addr = start;
80       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
81       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
82       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
83 
84       addr = (start + end) / 2;
85       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
86       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
87       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
88 
89       addr = end - 1;
90       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
91       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
92       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
93     }
94     prev_end = end;
95   }
96 }
97 
InitShadow(bool map_shadow,bool init_origins)98 bool InitShadow(bool map_shadow, bool init_origins) {
99   // Let user know mapping parameters first.
100   VPrintf(1, "__msan_init %p\n", &__msan_init);
101   for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
102     VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
103             kMemoryLayout[i].end - 1);
104 
105   CheckMemoryLayoutSanity();
106 
107   if (!MEM_IS_APP(&__msan_init)) {
108     Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
109            (uptr)&__msan_init);
110     return false;
111   }
112 
113   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
114     uptr start = kMemoryLayout[i].start;
115     uptr end = kMemoryLayout[i].end;
116     uptr size= end - start;
117     MappingDesc::Type type = kMemoryLayout[i].type;
118     if ((map_shadow && type == MappingDesc::SHADOW) ||
119         (init_origins && type == MappingDesc::ORIGIN)) {
120       if (!CheckMemoryRangeAvailability(start, size)) return false;
121       if ((uptr)MmapFixedNoReserve(start, size) != start) return false;
122       if (common_flags()->use_madv_dontdump)
123         DontDumpShadowMemory(start, size);
124     } else if (type == MappingDesc::INVALID) {
125       if (!CheckMemoryRangeAvailability(start, size)) return false;
126       if (!ProtectMemoryRange(start, size)) return false;
127     }
128   }
129 
130   return true;
131 }
132 
MsanDie()133 void MsanDie() {
134   if (common_flags()->coverage)
135     __sanitizer_cov_dump();
136   if (death_callback)
137     death_callback();
138   internal__exit(flags()->exit_code);
139 }
140 
MsanAtExit(void)141 static void MsanAtExit(void) {
142   if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
143     ReportStats();
144   if (msan_report_count > 0) {
145     ReportAtExitStatistics();
146     if (flags()->exit_code) _exit(flags()->exit_code);
147   }
148 }
149 
InstallAtExitHandler()150 void InstallAtExitHandler() {
151   atexit(MsanAtExit);
152 }
153 
154 // ---------------------- TSD ---------------- {{{1
155 
156 static pthread_key_t tsd_key;
157 static bool tsd_key_inited = false;
158 
MsanTSDInit(void (* destructor)(void * tsd))159 void MsanTSDInit(void (*destructor)(void *tsd)) {
160   CHECK(!tsd_key_inited);
161   tsd_key_inited = true;
162   CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
163 }
164 
165 static THREADLOCAL MsanThread* msan_current_thread;
166 
GetCurrentThread()167 MsanThread *GetCurrentThread() {
168   return msan_current_thread;
169 }
170 
SetCurrentThread(MsanThread * t)171 void SetCurrentThread(MsanThread *t) {
172   // Make sure we do not reset the current MsanThread.
173   CHECK_EQ(0, msan_current_thread);
174   msan_current_thread = t;
175   // Make sure that MsanTSDDtor gets called at the end.
176   CHECK(tsd_key_inited);
177   pthread_setspecific(tsd_key, (void *)t);
178 }
179 
MsanTSDDtor(void * tsd)180 void MsanTSDDtor(void *tsd) {
181   MsanThread *t = (MsanThread*)tsd;
182   if (t->destructor_iterations_ > 1) {
183     t->destructor_iterations_--;
184     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
185     return;
186   }
187   msan_current_thread = nullptr;
188   // Make sure that signal handler can not see a stale current thread pointer.
189   atomic_signal_fence(memory_order_seq_cst);
190   MsanThread::TSDDtor(tsd);
191 }
192 
193 }  // namespace __msan
194 
195 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
196