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 has their own InitializeShadowMemory implementation.
17 #if !SANITIZER_FUCHSIA
19 # include "asan_internal.h"
20 # include "asan_mapping.h"
24 static 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
), GetPageSizeCached());
30 RoundUpTo(MEM_TO_SHADOW(addr
+ size
), GetPageSizeCached()) - 1;
33 "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(GapShadowBeg
, GapShadowEnd
,
38 "unprotected gap shadow");
41 __sanitizer::ProtectGap(addr
, size
, kZeroBaseShadowStart
,
42 kZeroBaseMaxShadowStart
);
45 static void MaybeReportLinuxPIEBug() {
46 #if SANITIZER_LINUX && \
47 (defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64)
48 Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
50 "See https://github.com/google/sanitizers/issues/856 for possible "
55 void InitializeShadowMemory() {
56 // Set the shadow memory address to uninitialized.
57 __asan_shadow_memory_dynamic_address
= kDefaultShadowSentinel
;
59 uptr shadow_start
= kLowShadowBeg
;
60 // Detect if a dynamic shadow address must used and find a available location
61 // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
62 // expands to |__asan_shadow_memory_dynamic_address| which is
63 // |kDefaultShadowSentinel|.
64 bool full_shadow_is_available
= false;
65 if (shadow_start
== kDefaultShadowSentinel
) {
66 shadow_start
= FindDynamicShadowStart();
67 if (SANITIZER_LINUX
) full_shadow_is_available
= true;
69 // Update the shadow memory address (potentially) used by instrumentation.
70 __asan_shadow_memory_dynamic_address
= shadow_start
;
72 if (kLowShadowBeg
) shadow_start
-= GetMmapGranularity();
74 if (!full_shadow_is_available
)
75 full_shadow_is_available
=
76 MemoryRangeIsAvailable(shadow_start
, kHighShadowEnd
);
78 #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
80 if (!full_shadow_is_available
) {
81 kMidMemBeg
= kLowMemEnd
< 0x3000000000ULL
? 0x3000000000ULL
: 0;
82 kMidMemEnd
= kLowMemEnd
< 0x3000000000ULL
? 0x4fffffffffULL
: 0;
86 if (Verbosity()) PrintAddressSpaceLayout();
88 if (full_shadow_is_available
) {
89 // mmap the low shadow plus at least one page at the left.
91 ReserveShadowMemoryRange(shadow_start
, kLowShadowEnd
, "low shadow");
92 // mmap the high shadow.
93 ReserveShadowMemoryRange(kHighShadowBeg
, kHighShadowEnd
, "high shadow");
95 ProtectGap(kShadowGapBeg
, kShadowGapEnd
- kShadowGapBeg
+ 1);
96 CHECK_EQ(kShadowGapEnd
, kHighShadowBeg
- 1);
97 } else if (kMidMemBeg
&&
98 MemoryRangeIsAvailable(shadow_start
, kMidMemBeg
- 1) &&
99 MemoryRangeIsAvailable(kMidMemEnd
+ 1, kHighShadowEnd
)) {
100 CHECK(kLowShadowBeg
!= kLowShadowEnd
);
101 // mmap the low shadow plus at least one page at the left.
102 ReserveShadowMemoryRange(shadow_start
, kLowShadowEnd
, "low shadow");
103 // mmap the mid shadow.
104 ReserveShadowMemoryRange(kMidShadowBeg
, kMidShadowEnd
, "mid shadow");
105 // mmap the high shadow.
106 ReserveShadowMemoryRange(kHighShadowBeg
, kHighShadowEnd
, "high shadow");
108 ProtectGap(kShadowGapBeg
, kShadowGapEnd
- kShadowGapBeg
+ 1);
109 ProtectGap(kShadowGap2Beg
, kShadowGap2End
- kShadowGap2Beg
+ 1);
110 ProtectGap(kShadowGap3Beg
, kShadowGap3End
- kShadowGap3Beg
+ 1);
113 "Shadow memory range interleaves with an existing memory mapping. "
114 "ASan cannot proceed correctly. ABORTING.\n");
115 Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
116 (void*)shadow_start
, (void*)kHighShadowEnd
);
117 MaybeReportLinuxPIEBug();
123 } // namespace __asan
125 #endif // !SANITIZER_FUCHSIA