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