asan_shadow_setup.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  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. #include "sanitizer_common/sanitizer_platform.h"
  14. // asan_fuchsia.cpp has their own InitializeShadowMemory implementation.
  15. #if !SANITIZER_FUCHSIA
  16. # include "asan_internal.h"
  17. # include "asan_mapping.h"
  18. namespace __asan {
  19. static void ProtectGap(uptr addr, uptr size) {
  20. if (!flags()->protect_shadow_gap) {
  21. // The shadow gap is unprotected, so there is a chance that someone
  22. // is actually using this memory. Which means it needs a shadow...
  23. uptr GapShadowBeg = RoundDownTo(MEM_TO_SHADOW(addr), GetPageSizeCached());
  24. uptr GapShadowEnd =
  25. RoundUpTo(MEM_TO_SHADOW(addr + size), GetPageSizeCached()) - 1;
  26. if (Verbosity())
  27. Printf(
  28. "protect_shadow_gap=0:"
  29. " not protecting shadow gap, allocating gap's shadow\n"
  30. "|| `[%p, %p]` || ShadowGap's shadow ||\n",
  31. (void*)GapShadowBeg, (void*)GapShadowEnd);
  32. ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
  33. "unprotected gap shadow");
  34. return;
  35. }
  36. __sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
  37. kZeroBaseMaxShadowStart);
  38. }
  39. static void MaybeReportLinuxPIEBug() {
  40. #if SANITIZER_LINUX && \
  41. (defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64)
  42. Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
  43. Report(
  44. "See https://github.com/google/sanitizers/issues/856 for possible "
  45. "workarounds.\n");
  46. #endif
  47. }
  48. void InitializeShadowMemory() {
  49. // Set the shadow memory address to uninitialized.
  50. __asan_shadow_memory_dynamic_address = kDefaultShadowSentinel;
  51. uptr shadow_start = kLowShadowBeg;
  52. // Detect if a dynamic shadow address must used and find a available location
  53. // when necessary. When dynamic address is used, the macro |kLowShadowBeg|
  54. // expands to |__asan_shadow_memory_dynamic_address| which is
  55. // |kDefaultShadowSentinel|.
  56. bool full_shadow_is_available = false;
  57. if (shadow_start == kDefaultShadowSentinel) {
  58. shadow_start = FindDynamicShadowStart();
  59. if (SANITIZER_LINUX) full_shadow_is_available = true;
  60. }
  61. // Update the shadow memory address (potentially) used by instrumentation.
  62. __asan_shadow_memory_dynamic_address = shadow_start;
  63. if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
  64. if (!full_shadow_is_available)
  65. full_shadow_is_available =
  66. MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
  67. #if SANITIZER_LINUX && defined(__x86_64__) && defined(_LP64) && \
  68. !ASAN_FIXED_MAPPING
  69. if (!full_shadow_is_available) {
  70. kMidMemBeg = kLowMemEnd < 0x3000000000ULL ? 0x3000000000ULL : 0;
  71. kMidMemEnd = kLowMemEnd < 0x3000000000ULL ? 0x4fffffffffULL : 0;
  72. }
  73. #endif
  74. if (Verbosity()) PrintAddressSpaceLayout();
  75. if (full_shadow_is_available) {
  76. // mmap the low shadow plus at least one page at the left.
  77. if (kLowShadowBeg)
  78. ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
  79. // mmap the high shadow.
  80. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
  81. // protect the gap.
  82. ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
  83. CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1);
  84. } else if (kMidMemBeg &&
  85. MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) &&
  86. MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) {
  87. CHECK(kLowShadowBeg != kLowShadowEnd);
  88. // mmap the low shadow plus at least one page at the left.
  89. ReserveShadowMemoryRange(shadow_start, kLowShadowEnd, "low shadow");
  90. // mmap the mid shadow.
  91. ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow");
  92. // mmap the high shadow.
  93. ReserveShadowMemoryRange(kHighShadowBeg, kHighShadowEnd, "high shadow");
  94. // protect the gaps.
  95. ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1);
  96. ProtectGap(kShadowGap2Beg, kShadowGap2End - kShadowGap2Beg + 1);
  97. ProtectGap(kShadowGap3Beg, kShadowGap3End - kShadowGap3Beg + 1);
  98. } else {
  99. Report(
  100. "Shadow memory range interleaves with an existing memory mapping. "
  101. "ASan cannot proceed correctly. ABORTING.\n");
  102. Report("ASan shadow was supposed to be located in the [%p-%p] range.\n",
  103. (void*)shadow_start, (void*)kHighShadowEnd);
  104. MaybeReportLinuxPIEBug();
  105. DumpProcessMap();
  106. Die();
  107. }
  108. }
  109. } // namespace __asan
  110. #endif // !SANITIZER_FUCHSIA