1//===-- asan_shadow_setup.cpp ---------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file is a part of AddressSanitizer, an address sanity checker.
10//
11// Set up the shadow memory.
12//===----------------------------------------------------------------------===//
13
14#include "sanitizer_common/sanitizer_platform.h"
15
16// asan_fuchsia.cpp has their own InitializeShadowMemory implementation.
17#if !SANITIZER_FUCHSIA
18
19# include "asan_internal.h"
20# include "asan_mapping.h"
21
22namespace __asan {
23
24static void ProtectGap(uptr addr, uptr size) {
25 if (!flags()->protect_shadow_gap) {
26 // The shadow gap is unprotected, so there is a chance that someone
27 // is actually using this memory. Which means it needs a shadow...
28 uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), boundary: GetPageSizeCached());
29 uptr GapShadowEnd =
30 RoundUpTo(MEM_TO_SHADOW(addr + size), boundary: GetPageSizeCached()) - 1;
31 if (Verbosity())
32 Printf(
33 format: "protect_shadow_gap=0:"
34 " not protecting shadow gap, allocating gap's shadow\n"
35 "|| `[%p, %p]` || ShadowGap's shadow ||\n",
36 (void*)GapShadowBeg, (void*)GapShadowEnd);
37 ReserveShadowMemoryRange(beg: GapShadowBeg, end: GapShadowEnd,
38 name: "unprotected gap shadow");
39 return;
40 }
41 VReport(2, "ProtectGap %p sz=%p\n", (void*)addr, (void*)size);
42 __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
43 kZeroBaseMaxShadowStart);
44}
45
46static void MaybeReportLinuxPIEBug() {
47#if SANITIZER_LINUX && \
48 (defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64)
49 Report(format: "This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
50 Report(
51 format: "See https://github.com/google/sanitizers/issues/856 for possible "
52 "workarounds.\n");
53#endif
54}
55
56void InitializeShadowMemory() {
57 // Set the shadow memory address to uninitialized.
58 __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
59
60 uptr shadow_start = kLowShadowBeg;
61 // Detect if a dynamic shadow address must used and find a available location
62 // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
63 // expands to |__asan_shadow_memory_dynamic_address| which is
64 // |kDefaultShadowSentinel|.
65 bool full_shadow_is_available = false;
66 if (shadow_start == kDefaultShadowSentinel) {
67 shadow_start = FindDynamicShadowStart();
68 if (SANITIZER_LINUX) full_shadow_is_available = true;
69 }
70 // Update the shadow memory address (potentially) used by instrumentation.
71 __asan_shadow_memory_dynamic_address = shadow_start;
72
73 if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
74
75 if (!full_shadow_is_available)
76 full_shadow_is_available =
77 MemoryRangeIsAvailable(range_start: shadow_start, kHighShadowEnd);
78
79#if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
80 !ASAN_FIXED_MAPPING
81 if (!full_shadow_is_available) {
82 kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
83 kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
84 }
85#endif
86
87 if (Verbosity()) PrintAddressSpaceLayout();
88
89 if (full_shadow_is_available && kGaplessShadow) {
90 // Normally, the shadow memory overlaps with the memory mappable
91 // by the application, so we split shadow into "low" and "high"
92 // with a protected gap in the middle (the shadow of the shadow).
93 //
94 // However, on some platforms, we can map the shadow above
95 // the space normally addressable by the application. On these
96 // platforms, we do not need a gap.
97
98 // In the "gapless" configuration, there is only one shadow mapping
99 // which covers all app memory i.e. from kLowMemBeg to kHighMemEnd.
100 ReserveShadowMemoryRange(beg: shadow_start, kHighShadowEnd, name: "shadow");
101
102 // kLowShadowEnd, kHighShadowBeg are defined assuming there is a gap,
103 // and this affects calls such as AddrIsInLowMem and AddrIsInHighMem.
104 //
105 // We want all of application memory to be in the "low mem" region and all
106 // of the shadow to be in the "low shadow" region. However, kLowMemEnd
107 // is defined differently in terms of the shadow base, which is always above
108 // the actual app mem max (i.e. >4TB, kHighMemEnd). This means
109 // (kLowMemBeg, kLowMemEnd) is a slight over-approximation of the low app
110 // memory. However, it's still good enough for us because it includes
111 // all app memory and no shadow memory, which we assert here.
112 CHECK_GE(kLowMemEnd, kHighMemEnd);
113 CHECK_LT(kLowMemEnd, kLowShadowBeg);
114 CHECK_GE(kLowShadowEnd, kHighShadowEnd);
115
116 // We don't use the "high mem" region, so we expect beg > end, to ensure
117 // that AddrIsInHighMem/AddrIsInHighShadow always fails.
118 CHECK_GT(kHighMemBeg, kHighMemEnd);
119 CHECK_GT(kHighShadowBeg, kHighShadowEnd);
120
121 // The shadow of the shadow may still technically be mappable by the
122 // sanitizers or other tools, so we protect it here just to be safe.
123 ProtectGap(
124 MEM_TO_SHADOW(kLowShadowBeg),
125 MEM_TO_SHADOW(kHighShadowEnd) - MEM_TO_SHADOW(kLowShadowBeg) + 1);
126 } else if (full_shadow_is_available) {
127 // mmap the low shadow plus at least one page at the left.
128 if (kLowShadowBeg)
129 ReserveShadowMemoryRange(beg: shadow_start, kLowShadowEnd, name: "low shadow");
130 // mmap the high shadow and protect the gap.
131 // On targets where the shadow offset sits above all addressable memory
132 // (e.g. Alpha's 42-bit user VAS with offset 0x70000000000), the shadow of
133 // the highest address exceeds the highest address itself, so there is no
134 // high memory region. Skip both the high-shadow reservation and the gap
135 // protect.
136 if (MEM_TO_SHADOW(GetMaxUserVirtualAddress()) <
137 GetMaxUserVirtualAddress()) {
138 DCHECK_LE(kHighMemBeg, kHighMemEnd);
139 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, name: "high shadow");
140 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
141 CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
142 }
143 } else if (kMidMemBeg &&
144 MemoryRangeIsAvailable(range_start: shadow_start, range_end: kMidMemBeg - 1) &&
145 MemoryRangeIsAvailable(range_start: kMidMemEnd + 1, kHighShadowEnd)) {
146 CHECK(kLowShadowBeg != kLowShadowEnd);
147 // mmap the low shadow plus at least one page at the left.
148 ReserveShadowMemoryRange(beg: shadow_start, kLowShadowEnd, name: "low shadow");
149 // mmap the mid shadow.
150 ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, name: "mid shadow");
151 // mmap the high shadow.
152 ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, name: "high shadow");
153 // protect the gaps.
154 ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
155 ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
156 ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
157 } else {
158 // ASan's mappings can usually shadow the entire address space, even with
159 // maximum ASLR entropy. However:
160 // - On 32-bit systems, the maximum ASLR entropy (currently up to 16-bits
161 // == 256MB) is a significant chunk of the address space; reclaiming it
162 // by disabling ASLR might allow chonky binaries to run.
163 // - On 64-bit systems, some settings (e.g., for Linux, unlimited stack
164 // size plus 31+ bits of entropy) can lead to an incompatible layout.
165 TryReExecWithoutASLR();
166
167 Report(
168 format: "Shadow memory range interleaves with an existing memory mapping. "
169 "ASan cannot proceed correctly. ABORTING.\n");
170 Report(format: "ASan shadow was supposed to be located in the [%p-%p] range.\n",
171 (void*)shadow_start, (void*)kHighShadowEnd);
172 MaybeReportLinuxPIEBug();
173 DumpProcessMap();
174 Die();
175 }
176}
177
178} // namespace __asan
179
180#endif // !SANITIZER_FUCHSIA
181