brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.3 KiB · 5b3591d Raw
135 lines · cpp
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-exception6//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_FUCHSIA18 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 someone27    // is actually using this memory. Which means it needs a shadow...28    uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());29    uptr GapShadowEnd =30        RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;31    if (Verbosity())32      Printf(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");39    return;40  }41  __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,42                          kZeroBaseMaxShadowStart);43}44 45static 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");49  Report(50      "See https://github.com/google/sanitizers/issues/856 for possible "51      "workarounds.\n");52#endif53}54 55void InitializeShadowMemory() {56  // Set the shadow memory address to uninitialized.57  __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;58 59  uptr shadow_start = kLowShadowBeg;60  // Detect if a dynamic shadow address must used and find a available location61  // when necessary. When dynamic address is used, the macro |kLowShadowBeg|62  // expands to |__asan_shadow_memory_dynamic_address| which is63  // |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;68  }69  // Update the shadow memory address (potentially) used by instrumentation.70  __asan_shadow_memory_dynamic_address = shadow_start;71 72  if (kLowShadowBeg) shadow_start -= GetMmapGranularity();73 74  if (!full_shadow_is_available)75    full_shadow_is_available =76        MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);77 78#if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \79    !ASAN_FIXED_MAPPING80  if (!full_shadow_is_available) {81    kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;82    kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;83  }84#endif85 86  if (Verbosity()) PrintAddressSpaceLayout();87 88  if (full_shadow_is_available) {89    // mmap the low shadow plus at least one page at the left.90    if (kLowShadowBeg)91      ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");92    // mmap the high shadow.93    ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");94    // protect the gap.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");107    // protect the gaps.108    ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);109    ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);110    ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);111  } else {112    // ASan's mappings can usually shadow the entire address space, even with113    // maximum ASLR entropy. However:114    // - On 32-bit systems, the maximum ASLR entropy (currently up to 16-bits115    //   == 256MB) is a significant chunk of the address space; reclaiming it116    //   by disabling ASLR might allow chonky binaries to run.117    // - On 64-bit systems, some settings (e.g., for Linux, unlimited stack118    //   size plus 31+ bits of entropy) can lead to an incompatible layout.119    TryReExecWithoutASLR();120 121    Report(122        "Shadow memory range interleaves with an existing memory mapping. "123        "ASan cannot proceed correctly. ABORTING.\n");124    Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",125           (void*)shadow_start, (void*)kHighShadowEnd);126    MaybeReportLinuxPIEBug();127    DumpProcessMap();128    Die();129  }130}131 132}  // namespace __asan133 134#endif  // !SANITIZER_FUCHSIA135