123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125 |
- //===-- asan_shadow_setup.cpp ---------------------------------------------===//
- //
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
- // See https://llvm.org/LICENSE.txt for license information.
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is a part of AddressSanitizer, an address sanity checker.
- //
- // Set up the shadow memory.
- //===----------------------------------------------------------------------===//
- #include "sanitizer_common/sanitizer_platform.h"
- // asan_fuchsia.cpp has their own InitializeShadowMemory implementation.
- #if !SANITIZER_FUCHSIA
- # include "asan_internal.h"
- # include "asan_mapping.h"
- namespace __asan {
- static void ProtectGap(uptr addr, uptr size) {
- if (!flags()->protect_shadow_gap) {
- // The shadow gap is unprotected, so there is a chance that someone
- // is actually using this memory. Which means it needs a shadow...
- uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());
- uptr GapShadowEnd =
- RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;
- if (Verbosity())
- Printf(
- "protect_shadow_gap=0:"
- " not protecting shadow gap, allocating gap's shadow\n"
- "|| `[%p, %p]` || ShadowGap's shadow ||\n",
- (void*)GapShadowBeg, (void*)GapShadowEnd);
- ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
- "unprotected gap shadow");
- return;
- }
- __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
- kZeroBaseMaxShadowStart);
- }
- static void MaybeReportLinuxPIEBug() {
- #if SANITIZER_LINUX && \
- (defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64)
- Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
- Report(
- "See https://github.com/google/sanitizers/issues/856 for possible "
- "workarounds.\n");
- #endif
- }
- void InitializeShadowMemory() {
- // Set the shadow memory address to uninitialized.
- __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
- uptr shadow_start = kLowShadowBeg;
- // Detect if a dynamic shadow address must used and find a available location
- // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
- // expands to |__asan_shadow_memory_dynamic_address| which is
- // |kDefaultShadowSentinel|.
- bool full_shadow_is_available = false;
- if (shadow_start == kDefaultShadowSentinel) {
- shadow_start = FindDynamicShadowStart();
- if (SANITIZER_LINUX) full_shadow_is_available = true;
- }
- // Update the shadow memory address (potentially) used by instrumentation.
- __asan_shadow_memory_dynamic_address = shadow_start;
- if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
- if (!full_shadow_is_available)
- full_shadow_is_available =
- MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
- #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
- !ASAN_FIXED_MAPPING
- if (!full_shadow_is_available) {
- kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
- kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
- }
- #endif
- if (Verbosity()) PrintAddressSpaceLayout();
- if (full_shadow_is_available) {
- // mmap the low shadow plus at least one page at the left.
- if (kLowShadowBeg)
- ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
- // mmap the high shadow.
- ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
- // protect the gap.
- ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
- CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
- } else if (kMidMemBeg &&
- MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
- MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
- CHECK(kLowShadowBeg != kLowShadowEnd);
- // mmap the low shadow plus at least one page at the left.
- ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
- // mmap the mid shadow.
- ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
- // mmap the high shadow.
- ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
- // protect the gaps.
- ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
- ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
- ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
- } else {
- Report(
- "Shadow memory range interleaves with an existing memory mapping. "
- "ASan cannot proceed correctly. ABORTING.\n");
- Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
- (void*)shadow_start, (void*)kHighShadowEnd);
- MaybeReportLinuxPIEBug();
- DumpProcessMap();
- Die();
- }
- }
- } // namespace __asan
- #endif // !SANITIZER_FUCHSIA
|