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