1 //===-- asan_shadow_setup.cc ----------------------------------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file is a part of AddressSanitizer, an address sanity checker.
12 // Set up the shadow memory.
13 //===----------------------------------------------------------------------===//
15 #include "sanitizer_common/sanitizer_platform.h"
17 // asan_fuchsia.cc and asan_rtems.cc have their own
18 // InitializeShadowMemory implementation.
19 #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
21 #include "asan_internal.h"
22 #include "asan_mapping.h"
26 // ---------------------- mmap -------------------- {{{1
27 // Reserve memory range [beg, end].
28 // We need to use inclusive range because end+1 may not be representable.
29 void ReserveShadowMemoryRange(uptr beg, uptr end, const char *name) {
30 CHECK_EQ((beg % GetMmapGranularity()), 0);
31 CHECK_EQ(((end + 1) % GetMmapGranularity()), 0);
32 uptr size = end - beg + 1;
33 DecreaseTotalMmap(size); // Don't count the shadow against mmap_limit_mb.
34 if (!MmapFixedNoReserve(beg, size, name)) {
36 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
37 "Perhaps you're using ulimit -v\n",
41 if (common_flags()->no_huge_pages_for_shadow) NoHugePagesInRegion(beg, size);
42 if (common_flags()->use_madv_dontdump) DontDumpShadowMemory(beg, size);
45 static void ProtectGap(uptr addr, uptr size) {
46 if (!flags()->protect_shadow_gap) {
47 // The shadow gap is unprotected, so there is a chance that someone
48 // is actually using this memory. Which means it needs a shadow...
49 uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());
51 RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;
54 "protect_shadow_gap=0:"
55 " not protecting shadow gap, allocating gap's shadow\n"
56 "|| `[%p, %p]` || ShadowGap's shadow ||\n",
57 GapShadowBeg, GapShadowEnd);
58 ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
59 "unprotected gap shadow");
62 void *res = MmapFixedNoAccess(addr, size, "shadow gap");
63 if (addr == (uptr)res) return;
64 // A few pages at the start of the address space can not be protected.
65 // But we really want to protect as much as possible, to prevent this memory
66 // being returned as a result of a non-FIXED mmap().
67 if (addr == kZeroBaseShadowStart) {
68 uptr step = GetMmapGranularity();
69 while (size > step && addr < kZeroBaseMaxShadowStart) {
72 void *res = MmapFixedNoAccess(addr, size, "shadow gap");
73 if (addr == (uptr)res) return;
78 "ERROR: Failed to protect the shadow gap. "
79 "ASan cannot proceed correctly. ABORTING.\n");
84 static void MaybeReportLinuxPIEBug() {
85 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__aarch64__))
86 Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
88 "See https://github.com/google/sanitizers/issues/856 for possible "
93 void InitializeShadowMemory() {
94 // Set the shadow memory address to uninitialized.
95 __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
97 uptr shadow_start = kLowShadowBeg;
98 // Detect if a dynamic shadow address must used and find a available location
99 // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
100 // expands to |__asan_shadow_memory_dynamic_address| which is
101 // |kDefaultShadowSentinel|.
102 bool full_shadow_is_available = false;
103 if (shadow_start == kDefaultShadowSentinel) {
104 __asan_shadow_memory_dynamic_address = 0;
105 CHECK_EQ(0, kLowShadowBeg);
106 shadow_start = FindDynamicShadowStart();
107 if (SANITIZER_LINUX) full_shadow_is_available = true;
109 // Update the shadow memory address (potentially) used by instrumentation.
110 __asan_shadow_memory_dynamic_address = shadow_start;
112 if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
114 if (!full_shadow_is_available)
115 full_shadow_is_available =
116 MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
118 #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
120 if (!full_shadow_is_available) {
121 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
122 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
126 if (Verbosity()) PrintAddressSpaceLayout();
128 if (full_shadow_is_available) {
129 // mmap the low shadow plus at least one page at the left.
131 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
132 // mmap the high shadow.
133 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
135 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
136 CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
137 } else if (kMidMemBeg &&
138 MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
139 MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
140 CHECK(kLowShadowBeg != kLowShadowEnd);
141 // mmap the low shadow plus at least one page at the left.
142 ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
143 // mmap the mid shadow.
144 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
145 // mmap the high shadow.
146 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
148 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
149 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
150 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
153 "Shadow memory range interleaves with an existing memory mapping. "
154 "ASan cannot proceed correctly. ABORTING.\n");
155 Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
156 shadow_start, kHighShadowEnd);
157 MaybeReportLinuxPIEBug();
163 } // namespace __asan
165 #endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS