xref: /aosp_15_r20/external/compiler-rt/lib/msan/msan_linux.cc (revision 7c3d14c8b49c529e04be81a3ce6f5cc23712e4c6)
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