13cab2bb3Spatrick //===-- msan_linux.cpp ----------------------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is a part of MemorySanitizer.
103cab2bb3Spatrick //
113cab2bb3Spatrick // Linux-, NetBSD- and FreeBSD-specific code.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick
143cab2bb3Spatrick #include "sanitizer_common/sanitizer_platform.h"
153cab2bb3Spatrick #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
163cab2bb3Spatrick
173cab2bb3Spatrick #include "msan.h"
183cab2bb3Spatrick #include "msan_report.h"
193cab2bb3Spatrick #include "msan_thread.h"
203cab2bb3Spatrick
213cab2bb3Spatrick #include <elf.h>
223cab2bb3Spatrick #include <link.h>
233cab2bb3Spatrick #include <pthread.h>
243cab2bb3Spatrick #include <stdio.h>
253cab2bb3Spatrick #include <stdlib.h>
263cab2bb3Spatrick #include <signal.h>
273cab2bb3Spatrick #include <unistd.h>
283cab2bb3Spatrick #include <unwind.h>
293cab2bb3Spatrick #include <sys/time.h>
303cab2bb3Spatrick #include <sys/resource.h>
313cab2bb3Spatrick
323cab2bb3Spatrick #include "sanitizer_common/sanitizer_common.h"
333cab2bb3Spatrick #include "sanitizer_common/sanitizer_procmaps.h"
343cab2bb3Spatrick
353cab2bb3Spatrick namespace __msan {
363cab2bb3Spatrick
ReportMapRange(const char * descr,uptr beg,uptr size)373cab2bb3Spatrick void ReportMapRange(const char *descr, uptr beg, uptr size) {
383cab2bb3Spatrick if (size > 0) {
393cab2bb3Spatrick uptr end = beg + size - 1;
40*810390e3Srobert VPrintf(1, "%s : 0x%zx - 0x%zx\n", descr, beg, end);
413cab2bb3Spatrick }
423cab2bb3Spatrick }
433cab2bb3Spatrick
CheckMemoryRangeAvailability(uptr beg,uptr size)443cab2bb3Spatrick static bool CheckMemoryRangeAvailability(uptr beg, uptr size) {
453cab2bb3Spatrick if (size > 0) {
463cab2bb3Spatrick uptr end = beg + size - 1;
473cab2bb3Spatrick if (!MemoryRangeIsAvailable(beg, end)) {
48*810390e3Srobert Printf("FATAL: Memory range 0x%zx - 0x%zx is not available.\n", beg, end);
493cab2bb3Spatrick return false;
503cab2bb3Spatrick }
513cab2bb3Spatrick }
523cab2bb3Spatrick return true;
533cab2bb3Spatrick }
543cab2bb3Spatrick
ProtectMemoryRange(uptr beg,uptr size,const char * name)553cab2bb3Spatrick static bool ProtectMemoryRange(uptr beg, uptr size, const char *name) {
563cab2bb3Spatrick if (size > 0) {
573cab2bb3Spatrick void *addr = MmapFixedNoAccess(beg, size, name);
583cab2bb3Spatrick if (beg == 0 && addr) {
593cab2bb3Spatrick // Depending on the kernel configuration, we may not be able to protect
603cab2bb3Spatrick // the page at address zero.
613cab2bb3Spatrick uptr gap = 16 * GetPageSizeCached();
623cab2bb3Spatrick beg += gap;
633cab2bb3Spatrick size -= gap;
643cab2bb3Spatrick addr = MmapFixedNoAccess(beg, size, name);
653cab2bb3Spatrick }
663cab2bb3Spatrick if ((uptr)addr != beg) {
673cab2bb3Spatrick uptr end = beg + size - 1;
68*810390e3Srobert Printf("FATAL: Cannot protect memory range 0x%zx - 0x%zx (%s).\n", beg,
69*810390e3Srobert end, name);
703cab2bb3Spatrick return false;
713cab2bb3Spatrick }
723cab2bb3Spatrick }
733cab2bb3Spatrick return true;
743cab2bb3Spatrick }
753cab2bb3Spatrick
CheckMemoryLayoutSanity()763cab2bb3Spatrick static void CheckMemoryLayoutSanity() {
773cab2bb3Spatrick uptr prev_end = 0;
783cab2bb3Spatrick for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
793cab2bb3Spatrick uptr start = kMemoryLayout[i].start;
803cab2bb3Spatrick uptr end = kMemoryLayout[i].end;
813cab2bb3Spatrick MappingDesc::Type type = kMemoryLayout[i].type;
823cab2bb3Spatrick CHECK_LT(start, end);
833cab2bb3Spatrick CHECK_EQ(prev_end, start);
843cab2bb3Spatrick CHECK(addr_is_type(start, type));
853cab2bb3Spatrick CHECK(addr_is_type((start + end) / 2, type));
863cab2bb3Spatrick CHECK(addr_is_type(end - 1, type));
873cab2bb3Spatrick if (type == MappingDesc::APP) {
883cab2bb3Spatrick uptr addr = start;
893cab2bb3Spatrick CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
903cab2bb3Spatrick CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
913cab2bb3Spatrick CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
923cab2bb3Spatrick
933cab2bb3Spatrick addr = (start + end) / 2;
943cab2bb3Spatrick CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
953cab2bb3Spatrick CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
963cab2bb3Spatrick CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
973cab2bb3Spatrick
983cab2bb3Spatrick addr = end - 1;
993cab2bb3Spatrick CHECK(MEM_IS_SHADOW(MEM_TO_SHADOW(addr)));
1003cab2bb3Spatrick CHECK(MEM_IS_ORIGIN(MEM_TO_ORIGIN(addr)));
1013cab2bb3Spatrick CHECK_EQ(MEM_TO_ORIGIN(addr), SHADOW_TO_ORIGIN(MEM_TO_SHADOW(addr)));
1023cab2bb3Spatrick }
1033cab2bb3Spatrick prev_end = end;
1043cab2bb3Spatrick }
1053cab2bb3Spatrick }
1063cab2bb3Spatrick
InitShadow(bool init_origins)1073cab2bb3Spatrick bool InitShadow(bool init_origins) {
1083cab2bb3Spatrick // Let user know mapping parameters first.
109*810390e3Srobert VPrintf(1, "__msan_init %p\n", reinterpret_cast<void *>(&__msan_init));
1103cab2bb3Spatrick for (unsigned i = 0; i < kMemoryLayoutSize; ++i)
1113cab2bb3Spatrick VPrintf(1, "%s: %zx - %zx\n", kMemoryLayout[i].name, kMemoryLayout[i].start,
1123cab2bb3Spatrick kMemoryLayout[i].end - 1);
1133cab2bb3Spatrick
1143cab2bb3Spatrick CheckMemoryLayoutSanity();
1153cab2bb3Spatrick
1163cab2bb3Spatrick if (!MEM_IS_APP(&__msan_init)) {
1173cab2bb3Spatrick Printf("FATAL: Code %p is out of application range. Non-PIE build?\n",
118*810390e3Srobert reinterpret_cast<void *>(&__msan_init));
1193cab2bb3Spatrick return false;
1203cab2bb3Spatrick }
1213cab2bb3Spatrick
1223cab2bb3Spatrick const uptr maxVirtualAddress = GetMaxUserVirtualAddress();
1233cab2bb3Spatrick
1243cab2bb3Spatrick for (unsigned i = 0; i < kMemoryLayoutSize; ++i) {
1253cab2bb3Spatrick uptr start = kMemoryLayout[i].start;
1263cab2bb3Spatrick uptr end = kMemoryLayout[i].end;
1273cab2bb3Spatrick uptr size = end - start;
1283cab2bb3Spatrick MappingDesc::Type type = kMemoryLayout[i].type;
1293cab2bb3Spatrick
1303cab2bb3Spatrick // Check if the segment should be mapped based on platform constraints.
1313cab2bb3Spatrick if (start >= maxVirtualAddress)
1323cab2bb3Spatrick continue;
1333cab2bb3Spatrick
1343cab2bb3Spatrick bool map = type == MappingDesc::SHADOW ||
1353cab2bb3Spatrick (init_origins && type == MappingDesc::ORIGIN);
1363cab2bb3Spatrick bool protect = type == MappingDesc::INVALID ||
1373cab2bb3Spatrick (!init_origins && type == MappingDesc::ORIGIN);
1383cab2bb3Spatrick CHECK(!(map && protect));
1393cab2bb3Spatrick if (!map && !protect)
1403cab2bb3Spatrick CHECK(type == MappingDesc::APP);
1413cab2bb3Spatrick if (map) {
1423cab2bb3Spatrick if (!CheckMemoryRangeAvailability(start, size))
1433cab2bb3Spatrick return false;
144d89ec533Spatrick if (!MmapFixedSuperNoReserve(start, size, kMemoryLayout[i].name))
1453cab2bb3Spatrick return false;
1463cab2bb3Spatrick if (common_flags()->use_madv_dontdump)
1473cab2bb3Spatrick DontDumpShadowMemory(start, size);
1483cab2bb3Spatrick }
1493cab2bb3Spatrick if (protect) {
1503cab2bb3Spatrick if (!CheckMemoryRangeAvailability(start, size))
1513cab2bb3Spatrick return false;
1523cab2bb3Spatrick if (!ProtectMemoryRange(start, size, kMemoryLayout[i].name))
1533cab2bb3Spatrick return false;
1543cab2bb3Spatrick }
1553cab2bb3Spatrick }
1563cab2bb3Spatrick
1573cab2bb3Spatrick return true;
1583cab2bb3Spatrick }
1593cab2bb3Spatrick
MsanAtExit(void)1603cab2bb3Spatrick static void MsanAtExit(void) {
1613cab2bb3Spatrick if (flags()->print_stats && (flags()->atexit || msan_report_count > 0))
1623cab2bb3Spatrick ReportStats();
1633cab2bb3Spatrick if (msan_report_count > 0) {
1643cab2bb3Spatrick ReportAtExitStatistics();
1653cab2bb3Spatrick if (common_flags()->exitcode)
1663cab2bb3Spatrick internal__exit(common_flags()->exitcode);
1673cab2bb3Spatrick }
1683cab2bb3Spatrick }
1693cab2bb3Spatrick
InstallAtExitHandler()1703cab2bb3Spatrick void InstallAtExitHandler() {
1713cab2bb3Spatrick atexit(MsanAtExit);
1723cab2bb3Spatrick }
1733cab2bb3Spatrick
1743cab2bb3Spatrick // ---------------------- TSD ---------------- {{{1
1753cab2bb3Spatrick
1763cab2bb3Spatrick #if SANITIZER_NETBSD
1773cab2bb3Spatrick // Thread Static Data cannot be used in early init on NetBSD.
1783cab2bb3Spatrick // Reuse the MSan TSD API for compatibility with existing code
1793cab2bb3Spatrick // with an alternative implementation.
1803cab2bb3Spatrick
1813cab2bb3Spatrick static void (*tsd_destructor)(void *tsd) = nullptr;
1823cab2bb3Spatrick
1833cab2bb3Spatrick struct tsd_key {
tsd_key__msan::tsd_key1843cab2bb3Spatrick tsd_key() : key(nullptr) {}
~tsd_key__msan::tsd_key1853cab2bb3Spatrick ~tsd_key() {
1863cab2bb3Spatrick CHECK(tsd_destructor);
1873cab2bb3Spatrick if (key)
1883cab2bb3Spatrick (*tsd_destructor)(key);
1893cab2bb3Spatrick }
1903cab2bb3Spatrick MsanThread *key;
1913cab2bb3Spatrick };
1923cab2bb3Spatrick
1933cab2bb3Spatrick static thread_local struct tsd_key key;
1943cab2bb3Spatrick
MsanTSDInit(void (* destructor)(void * tsd))1953cab2bb3Spatrick void MsanTSDInit(void (*destructor)(void *tsd)) {
1963cab2bb3Spatrick CHECK(!tsd_destructor);
1973cab2bb3Spatrick tsd_destructor = destructor;
1983cab2bb3Spatrick }
1993cab2bb3Spatrick
GetCurrentThread()2003cab2bb3Spatrick MsanThread *GetCurrentThread() {
2013cab2bb3Spatrick CHECK(tsd_destructor);
2023cab2bb3Spatrick return key.key;
2033cab2bb3Spatrick }
2043cab2bb3Spatrick
SetCurrentThread(MsanThread * tsd)2053cab2bb3Spatrick void SetCurrentThread(MsanThread *tsd) {
2063cab2bb3Spatrick CHECK(tsd_destructor);
2073cab2bb3Spatrick CHECK(tsd);
2083cab2bb3Spatrick CHECK(!key.key);
2093cab2bb3Spatrick key.key = tsd;
2103cab2bb3Spatrick }
2113cab2bb3Spatrick
MsanTSDDtor(void * tsd)2123cab2bb3Spatrick void MsanTSDDtor(void *tsd) {
2133cab2bb3Spatrick CHECK(tsd_destructor);
2143cab2bb3Spatrick CHECK_EQ(key.key, tsd);
2153cab2bb3Spatrick key.key = nullptr;
2163cab2bb3Spatrick // Make sure that signal handler can not see a stale current thread pointer.
2173cab2bb3Spatrick atomic_signal_fence(memory_order_seq_cst);
2183cab2bb3Spatrick MsanThread::TSDDtor(tsd);
2193cab2bb3Spatrick }
2203cab2bb3Spatrick #else
2213cab2bb3Spatrick static pthread_key_t tsd_key;
2223cab2bb3Spatrick static bool tsd_key_inited = false;
2233cab2bb3Spatrick
MsanTSDInit(void (* destructor)(void * tsd))2243cab2bb3Spatrick void MsanTSDInit(void (*destructor)(void *tsd)) {
2253cab2bb3Spatrick CHECK(!tsd_key_inited);
2263cab2bb3Spatrick tsd_key_inited = true;
2273cab2bb3Spatrick CHECK_EQ(0, pthread_key_create(&tsd_key, destructor));
2283cab2bb3Spatrick }
2293cab2bb3Spatrick
2303cab2bb3Spatrick static THREADLOCAL MsanThread* msan_current_thread;
2313cab2bb3Spatrick
GetCurrentThread()2323cab2bb3Spatrick MsanThread *GetCurrentThread() {
2333cab2bb3Spatrick return msan_current_thread;
2343cab2bb3Spatrick }
2353cab2bb3Spatrick
SetCurrentThread(MsanThread * t)2363cab2bb3Spatrick void SetCurrentThread(MsanThread *t) {
2373cab2bb3Spatrick // Make sure we do not reset the current MsanThread.
2383cab2bb3Spatrick CHECK_EQ(0, msan_current_thread);
2393cab2bb3Spatrick msan_current_thread = t;
2403cab2bb3Spatrick // Make sure that MsanTSDDtor gets called at the end.
2413cab2bb3Spatrick CHECK(tsd_key_inited);
2423cab2bb3Spatrick pthread_setspecific(tsd_key, (void *)t);
2433cab2bb3Spatrick }
2443cab2bb3Spatrick
MsanTSDDtor(void * tsd)2453cab2bb3Spatrick void MsanTSDDtor(void *tsd) {
2463cab2bb3Spatrick MsanThread *t = (MsanThread*)tsd;
2473cab2bb3Spatrick if (t->destructor_iterations_ > 1) {
2483cab2bb3Spatrick t->destructor_iterations_--;
2493cab2bb3Spatrick CHECK_EQ(0, pthread_setspecific(tsd_key, tsd));
2503cab2bb3Spatrick return;
2513cab2bb3Spatrick }
2523cab2bb3Spatrick msan_current_thread = nullptr;
2533cab2bb3Spatrick // Make sure that signal handler can not see a stale current thread pointer.
2543cab2bb3Spatrick atomic_signal_fence(memory_order_seq_cst);
2553cab2bb3Spatrick MsanThread::TSDDtor(tsd);
2563cab2bb3Spatrick }
2573cab2bb3Spatrick #endif
2583cab2bb3Spatrick
2593cab2bb3Spatrick } // namespace __msan
2603cab2bb3Spatrick
2613cab2bb3Spatrick #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD
262