xref: /NextBSD/contrib/compiler-rt/lib/msan/msan_linux.cc (revision 84d351007654069f9643c8e4b4802a7f5f08ee42)
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,const char * name)56 static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
57   if (size > 0) {
58     void *addr = MmapNoAccess(beg, size, name);
59     if (beg == 0 && addr != 0) {
60       // Depending on the kernel configuration, we may not be able to protect
61       // the page at address zero.
62       uptr gap = 16 * GetPageSizeCached();
63       beg += gap;
64       size -= gap;
65       addr = MmapNoAccess(beg, size, name);
66     }
67     if ((uptr)addr != beg) {
68       uptr end = beg + size - 1;
69       Printf("FATAL: Cannot protect memory range %p - %p.\n", beg, end);
70       return false;
71     }
72   }
73   return true;
74 }
75 
CheckMemoryLayoutSanity()76 static void CheckMemoryLayoutSanity() {
77   uptr prev_end = 0;
78   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
79     uptr start = kMemoryLayout[i].start;
80     uptr end = kMemoryLayout[i].end;
81     MappingDesc::Type type = kMemoryLayout[i].type;
82     CHECK_LT(start, end);
83     CHECK_EQ(prev_end, start);
84     CHECK(addr_is_type(start, type));
85     CHECK(addr_is_type((start + end) / 2, type));
86     CHECK(addr_is_type(end - 1, type));
87     if (type == MappingDesc::APP) {
88       uptr addr = start;
89       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
90       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
91       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
92 
93       addr = (start + end) / 2;
94       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
95       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
96       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
97 
98       addr = end - 1;
99       CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
100       CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
101       CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
102     }
103     prev_end = end;
104   }
105 }
106 
InitShadow(bool init_origins)107 bool InitShadow(bool init_origins) {
108   // Let user know mapping parameters first.
109   VPrintf(1, "__msan_init %p\n", &__msan_init);
110   for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
111     VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
112             kMemoryLayout[i].end - 1);
113 
114   CheckMemoryLayoutSanity();
115 
116   if (!MEM_IS_APP(&__msan_init)) {
117     Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
118            (uptr)&__msan_init);
119     return false;
120   }
121 
122   for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
123     uptr start = kMemoryLayout[i].start;
124     uptr end = kMemoryLayout[i].end;
125     uptr size= end - start;
126     MappingDesc::Type type = kMemoryLayout[i].type;
127 
128     bool map = type == MappingDesc::SHADOW ||
129                (init_origins && type == MappingDesc::ORIGIN);
130     bool protect = type == MappingDesc::INVALID ||
131                    (!init_origins && type == MappingDesc::ORIGIN);
132     CHECK(!(map && protect));
133     if (!map && !protect)
134       CHECK(type == MappingDesc::APP);
135     if (map) {
136       if (!CheckMemoryRangeAvailability(start, size))
137         return false;
138       if ((uptr)MmapFixedNoReserve(start, size, kMemoryLayout[i].name) != start)
139         return false;
140       if (common_flags()->use_madv_dontdump)
141         DontDumpShadowMemory(start, size);
142     }
143     if (protect) {
144       if (!CheckMemoryRangeAvailability(start, size))
145         return false;
146       if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name))
147         return false;
148     }
149   }
150 
151   return true;
152 }
153 
MsanDie()154 void MsanDie() {
155   if (common_flags()->coverage)
156     __sanitizer_cov_dump();
157   if (death_callback)
158     death_callback();
159   internal__exit(flags()->exit_code);
160 }
161 
MsanAtExit(void)162 static void MsanAtExit(void) {
163   if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
164     ReportStats();
165   if (msan_report_count > 0) {
166     ReportAtExitStatistics();
167     if (flags()->exit_code) _exit(flags()->exit_code);
168   }
169 }
170 
InstallAtExitHandler()171 void InstallAtExitHandler() {
172   atexit(MsanAtExit);
173 }
174 
175 // ---------------------- TSD ---------------- {{{1
176 
177 static pthread_key_t tsd_key;
178 static bool tsd_key_inited = false;
179 
MsanTSDInit(void (* destructor)(void * tsd))180 void MsanTSDInit(void (*destructor)(void *tsd)) {
181   CHECK(!tsd_key_inited);
182   tsd_key_inited = true;
183   CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
184 }
185 
186 static THREADLOCAL MsanThread* msan_current_thread;
187 
GetCurrentThread()188 MsanThread *GetCurrentThread() {
189   return msan_current_thread;
190 }
191 
SetCurrentThread(MsanThread * t)192 void SetCurrentThread(MsanThread *t) {
193   // Make sure we do not reset the current MsanThread.
194   CHECK_EQ(0, msan_current_thread);
195   msan_current_thread = t;
196   // Make sure that MsanTSDDtor gets called at the end.
197   CHECK(tsd_key_inited);
198   pthread_setspecific(tsd_key, (void *)t);
199 }
200 
MsanTSDDtor(void * tsd)201 void MsanTSDDtor(void *tsd) {
202   MsanThread *t = (MsanThread*)tsd;
203   if (t->destructor_iterations_ > 1) {
204     t->destructor_iterations_--;
205     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
206     return;
207   }
208   msan_current_thread = nullptr;
209   // Make sure that signal handler can not see a stale current thread pointer.
210   atomic_signal_fence(memory_order_seq_cst);
211   MsanThread::TSDDtor(tsd);
212 }
213 
214 }  // namespace __msan
215 
216 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
217