1 //===-- asan_shadow_setup.cpp ---------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file is a part of AddressSanitizer, an address sanity checker.
11 // Set up the shadow memory.
12 //===----------------------------------------------------------------------===//
14 #include "sanitizer_common/sanitizer_platform.h"
16 // asan_fuchsia.cpp and asan_rtems.cpp have their own
17 // InitializeShadowMemory implementation.
18 #if !SANITIZER_FUCHSIA && !SANITIZER_RTEMS
20 #include "asan_internal.h"
21 #include "asan_mapping.h"
25 // ---------------------- mmap -------------------- {{{1
26 // Reserve memory range [beg, end].
27 // We need to use inclusive range because end+1 may not be representable.
28 void ReserveShadowMemoryRange(uptr beg
, uptr end
, const char *name
) {
29 CHECK_EQ((beg
% GetMmapGranularity()), 0);
30 CHECK_EQ(((end
+ 1) % GetMmapGranularity()), 0);
31 uptr size
= end
- beg
+ 1;
32 DecreaseTotalMmap(size
); // Don't count the shadow against mmap_limit_mb.
33 if (!MmapFixedSuperNoReserve(beg
, size
, name
)) {
35 "ReserveShadowMemoryRange failed while trying to map 0x%zx bytes. "
36 "Perhaps you're using ulimit -v\n",
40 if (common_flags()->use_madv_dontdump
) DontDumpShadowMemory(beg
, size
);
43 static void ProtectGap(uptr addr
, uptr size
) {
44 if (!flags()->protect_shadow_gap
) {
45 // The shadow gap is unprotected, so there is a chance that someone
46 // is actually using this memory. Which means it needs a shadow...
47 uptr GapShadowBeg
= RoundDownTo(MEM_TO_SHADOW(addr
), GetPageSizeCached());
49 RoundUpTo(MEM_TO_SHADOW(addr
+ size
), GetPageSizeCached()) - 1;
52 "protect_shadow_gap=0:"
53 " not protecting shadow gap, allocating gap's shadow\n"
54 "|| `[%p, %p]` || ShadowGap's shadow ||\n",
55 GapShadowBeg
, GapShadowEnd
);
56 ReserveShadowMemoryRange(GapShadowBeg
, GapShadowEnd
,
57 "unprotected gap shadow");
60 void *res
= MmapFixedNoAccess(addr
, size
, "shadow gap");
61 if (addr
== (uptr
)res
) return;
62 // A few pages at the start of the address space can not be protected.
63 // But we really want to protect as much as possible, to prevent this memory
64 // being returned as a result of a non-FIXED mmap().
65 if (addr
== kZeroBaseShadowStart
) {
66 uptr step
= GetMmapGranularity();
67 while (size
> step
&& addr
< kZeroBaseMaxShadowStart
) {
70 void *res
= MmapFixedNoAccess(addr
, size
, "shadow gap");
71 if (addr
== (uptr
)res
) return;
76 "ERROR: Failed to protect the shadow gap. "
77 "ASan cannot proceed correctly. ABORTING.\n");
82 static void MaybeReportLinuxPIEBug() {
83 #if SANITIZER_LINUX && (defined(__x86_64__) || defined(__aarch64__))
84 Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
86 "See https://github.com/google/sanitizers/issues/856 for possible "
91 void InitializeShadowMemory() {
92 // Set the shadow memory address to uninitialized.
93 __asan_shadow_memory_dynamic_address
= kDefaultShadowSentinel
;
95 uptr shadow_start
= kLowShadowBeg
;
96 // Detect if a dynamic shadow address must used and find a available location
97 // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
98 // expands to |__asan_shadow_memory_dynamic_address| which is
99 // |kDefaultShadowSentinel|.
100 bool full_shadow_is_available
= false;
101 if (shadow_start
== kDefaultShadowSentinel
) {
102 __asan_shadow_memory_dynamic_address
= 0;
103 CHECK_EQ(0, kLowShadowBeg
);
104 shadow_start
= FindDynamicShadowStart();
105 if (SANITIZER_LINUX
) full_shadow_is_available
= true;
107 // Update the shadow memory address (potentially) used by instrumentation.
108 __asan_shadow_memory_dynamic_address
= shadow_start
;
110 if (kLowShadowBeg
) shadow_start
-= GetMmapGranularity();
112 if (!full_shadow_is_available
)
113 full_shadow_is_available
=
114 MemoryRangeIsAvailable(shadow_start
, kHighShadowEnd
);
116 #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
118 if (!full_shadow_is_available
) {
119 kMidMemBeg
= kLowMemEnd
< 0x3000000000ULL
? 0x3000000000ULL
: 0;
120 kMidMemEnd
= kLowMemEnd
< 0x3000000000ULL
? 0x4fffffffffULL
: 0;
124 if (Verbosity()) PrintAddressSpaceLayout();
126 if (full_shadow_is_available
) {
127 // mmap the low shadow plus at least one page at the left.
129 ReserveShadowMemoryRange(shadow_start
, kLowShadowEnd
, "low shadow");
130 // mmap the high shadow.
131 ReserveShadowMemoryRange(kHighShadowBeg
, kHighShadowEnd
, "high shadow");
133 ProtectGap(kShadowGapBeg
, kShadowGapEnd
- kShadowGapBeg
+ 1);
134 CHECK_EQ(kShadowGapEnd
, kHighShadowBeg
- 1);
135 } else if (kMidMemBeg
&&
136 MemoryRangeIsAvailable(shadow_start
, kMidMemBeg
- 1) &&
137 MemoryRangeIsAvailable(kMidMemEnd
+ 1, kHighShadowEnd
)) {
138 CHECK(kLowShadowBeg
!= kLowShadowEnd
);
139 // mmap the low shadow plus at least one page at the left.
140 ReserveShadowMemoryRange(shadow_start
, kLowShadowEnd
, "low shadow");
141 // mmap the mid shadow.
142 ReserveShadowMemoryRange(kMidShadowBeg
, kMidShadowEnd
, "mid shadow");
143 // mmap the high shadow.
144 ReserveShadowMemoryRange(kHighShadowBeg
, kHighShadowEnd
, "high shadow");
146 ProtectGap(kShadowGapBeg
, kShadowGapEnd
- kShadowGapBeg
+ 1);
147 ProtectGap(kShadowGap2Beg
, kShadowGap2End
- kShadowGap2Beg
+ 1);
148 ProtectGap(kShadowGap3Beg
, kShadowGap3End
- kShadowGap3Beg
+ 1);
151 "Shadow memory range interleaves with an existing memory mapping. "
152 "ASan cannot proceed correctly. ABORTING.\n");
153 Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
154 shadow_start
, kHighShadowEnd
);
155 MaybeReportLinuxPIEBug();
161 } // namespace __asan
163 #endif // !SANITIZER_FUCHSIA && !SANITIZER_RTEMS