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 
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 
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 
56 static bool ProtectMemoryRange(uptr beg, uptr size) {
57   if (size > 0) {
58     uptr end = beg + size - 1;
59     if (!Mprotect(beg, size)) {
60       Printf("FATAL: Cannot protect memory range %p - %p.\n", beg, end);
61       return false;
62     }
63   }
64   return true;
65 }
66 
67 bool InitShadow(bool map_shadow, bool init_origins) {
68   // Let user know mapping parameters first.
69   VPrintf(1, "__msan_init %p\n", &__msan_init);
70   ReportMapRange("Low Memory ", kLowMemBeg, kLowMemSize);
71   ReportMapRange("Bad1       ", kBad1Beg, kBad1Size);
72   ReportMapRange("Shadow     ", kShadowBeg, kShadowSize);
73   ReportMapRange("Bad2       ", kBad2Beg, kBad2Size);
74   ReportMapRange("Origins    ", kOriginsBeg, kOriginsSize);
75   ReportMapRange("Bad3       ", kBad3Beg, kBad3Size);
76   ReportMapRange("High Memory", kHighMemBeg, kHighMemSize);
77 
78   // Check mapping sanity (the invariant).
79   CHECK_EQ(kLowMemBeg, 0);
80   CHECK_EQ(kBad1Beg, kLowMemBeg + kLowMemSize);
81   CHECK_EQ(kShadowBeg, kBad1Beg + kBad1Size);
82   CHECK_GT(kShadowSize, 0);
83   CHECK_GE(kShadowSize, kLowMemSize + kHighMemSize);
84   CHECK_EQ(kBad2Beg, kShadowBeg + kShadowSize);
85   CHECK_EQ(kOriginsBeg, kBad2Beg + kBad2Size);
86   CHECK_EQ(kOriginsSize, kShadowSize);
87   CHECK_EQ(kBad3Beg, kOriginsBeg + kOriginsSize);
88   CHECK_EQ(kHighMemBeg, kBad3Beg + kBad3Size);
89   CHECK_GT(kHighMemSize, 0);
90   CHECK_GE(kHighMemBeg + kHighMemSize, kHighMemBeg);  // Tests for no overflow.
91 
92   if (kLowMemSize > 0) {
93     CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kLowMemBeg)));
94     CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kLowMemBeg + kLowMemSize - 1)));
95     CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kLowMemBeg)));
96     CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kLowMemBeg + kLowMemSize - 1)));
97   }
98   CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kHighMemBeg)));
99   CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(kHighMemBeg + kHighMemSize - 1)));
100   CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kHighMemBeg)));
101   CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(kHighMemBeg + kHighMemSize - 1)));
102 
103   if (!MEM_IS_APP(&__msan_init)) {
104     Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
105            (uptr)&__msan_init);
106     return false;
107   }
108 
109   if (!CheckMemoryRangeAvailability(kShadowBeg, kShadowSize) ||
110       (init_origins &&
111         !CheckMemoryRangeAvailability(kOriginsBeg, kOriginsSize)) ||
112       !CheckMemoryRangeAvailability(kBad1Beg, kBad1Size) ||
113       !CheckMemoryRangeAvailability(kBad2Beg, kBad2Size) ||
114       !CheckMemoryRangeAvailability(kBad3Beg, kBad3Size)) {
115     return false;
116   }
117 
118   if (!ProtectMemoryRange(kBad1Beg, kBad1Size) ||
119       !ProtectMemoryRange(kBad2Beg, kBad2Size) ||
120       !ProtectMemoryRange(kBad3Beg, kBad3Size)) {
121     return false;
122   }
123 
124   if (map_shadow) {
125     void *shadow = MmapFixedNoReserve(kShadowBeg, kShadowSize);
126     if (shadow != (void*)kShadowBeg) return false;
127   }
128   if (init_origins) {
129     void *origins = MmapFixedNoReserve(kOriginsBeg, kOriginsSize);
130     if (origins != (void*)kOriginsBeg) return false;
131   }
132   return true;
133 }
134 
135 void MsanDie() {
136   if (common_flags()->coverage)
137     __sanitizer_cov_dump();
138   if (death_callback)
139     death_callback();
140   _exit(flags()->exit_code);
141 }
142 
143 static void MsanAtExit(void) {
144   if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
145     ReportStats();
146   if (msan_report_count > 0) {
147     ReportAtExitStatistics();
148     if (flags()->exit_code) _exit(flags()->exit_code);
149   }
150 }
151 
152 void InstallAtExitHandler() {
153   atexit(MsanAtExit);
154 }
155 
156 // ---------------------- TSD ---------------- {{{1
157 
158 static pthread_key_t tsd_key;
159 static bool tsd_key_inited = false;
160 void MsanTSDInit(void (*destructor)(void *tsd)) {
161   CHECK(!tsd_key_inited);
162   tsd_key_inited = true;
163   CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
164 }
165 
166 void *MsanTSDGet() {
167   CHECK(tsd_key_inited);
168   return pthread_getspecific(tsd_key);
169 }
170 
171 void MsanTSDSet(void *tsd) {
172   CHECK(tsd_key_inited);
173   pthread_setspecific(tsd_key, tsd);
174 }
175 
176 void MsanTSDDtor(void *tsd) {
177   MsanThread *t = (MsanThread*)tsd;
178   if (t->destructor_iterations_ > 1) {
179     t->destructor_iterations_--;
180     CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
181     return;
182   }
183   MsanThread::TSDDtor(tsd);
184 }
185 
186 }  // namespace __msan
187 
188 #endif  // SANITIZER_FREEBSD || SANITIZER_LINUX
189