2019-08-01 21:43:28 +08:00
|
|
|
//===-- asan_shadow_setup.cpp ---------------------------------------------===//
|
2017-07-31 14:48:34 +08:00
|
|
|
//
|
2019-01-19 16:50:56 +08:00
|
|
|
// 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
|
2017-07-31 14:48:34 +08:00
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
//
|
|
|
|
// This file is a part of AddressSanitizer, an address sanity checker.
|
|
|
|
//
|
|
|
|
// Set up the shadow memory.
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
2017-08-09 08:21:45 +08:00
|
|
|
#include "sanitizer_common/sanitizer_platform.h"
|
|
|
|
|
2021-06-15 08:52:14 +08:00
|
|
|
// asan_fuchsia.cpp has their own InitializeShadowMemory implementation.
|
|
|
|
#if !SANITIZER_FUCHSIA
|
2017-08-09 08:21:45 +08:00
|
|
|
|
2021-06-15 08:46:48 +08:00
|
|
|
# include "asan_internal.h"
|
|
|
|
# include "asan_mapping.h"
|
2017-07-31 14:48:34 +08:00
|
|
|
|
|
|
|
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",
|
2021-11-03 20:49:21 +08:00
|
|
|
(void*)GapShadowBeg, (void*)GapShadowEnd);
|
2017-07-31 14:48:34 +08:00
|
|
|
ReserveShadowMemoryRange(GapShadowBeg, GapShadowEnd,
|
|
|
|
"unprotected gap shadow");
|
|
|
|
return;
|
|
|
|
}
|
[compiler-rt][asan][hwasan] Refactor shadow setup into sanitizer_common (NFCI)
Summary:
This refactors some common support related to shadow memory setup from
asan and hwasan into sanitizer_common. This should not only reduce code
duplication but also make these facilities available for new compiler-rt
uses (e.g. heap profiling).
In most cases the separate copies of the code were either identical, or
at least functionally identical. A few notes:
In ProtectGap, the asan version checked the address against an upper
bound (kZeroBaseMaxShadowStart, which is (2^18). I have created a copy
of kZeroBaseMaxShadowStart in hwasan_mapping.h, with the same value, as
it isn't clear why that code should not do the same check. If it
shouldn't, I can remove this and guard this check so that it only
happens for asan.
In asan's InitializeShadowMemory, in the dynamic shadow case it was
setting __asan_shadow_memory_dynamic_address to 0 (which then sets both
macro SHADOW_OFFSET as well as macro kLowShadowBeg to 0) before calling
FindDynamicShadowStart(). AFAICT this is only needed because
FindDynamicShadowStart utilizes kHighShadowEnd to
get the shadow size, and kHighShadowEnd is a macro invoking
MEM_TO_SHADOW(kHighMemEnd) which in turn invokes:
(((kHighMemEnd) >> SHADOW_SCALE) + (SHADOW_OFFSET))
I.e. it computes the shadow space needed by kHighMemEnd (the shift), and
adds the offset. Since we only want the shadow space here, the earlier
setting of SHADOW_OFFSET to 0 via __asan_shadow_memory_dynamic_address
accomplishes this. In the hwasan version, it simply gets the shadow
space via "MemToShadowSize(kHighMemEnd)", where MemToShadowSize just
does the shift. I've simplified the asan handling to do the same
thing, and therefore was able to remove the setting of the SHADOW_OFFSET
via __asan_shadow_memory_dynamic_address to 0.
Reviewers: vitalybuka, kcc, eugenis
Subscribers: dberris, #sanitizers, llvm-commits, davidxl
Tags: #sanitizers
Differential Revision: https://reviews.llvm.org/D83247
2020-07-07 02:05:12 +08:00
|
|
|
__sanitizer::ProtectGap(addr, size, kZeroBaseShadowStart,
|
|
|
|
kZeroBaseMaxShadowStart);
|
2017-07-31 14:48:34 +08:00
|
|
|
}
|
|
|
|
|
2017-09-07 09:35:59 +08:00
|
|
|
static void MaybeReportLinuxPIEBug() {
|
2020-10-04 17:38:06 +08:00
|
|
|
#if SANITIZER_LINUX && \
|
|
|
|
(defined(__x86_64__) || defined(__aarch64__) || SANITIZER_RISCV64)
|
2017-09-07 09:35:59 +08:00
|
|
|
Report("This might be related to ELF_ET_DYN_BASE change in Linux 4.12.\n");
|
|
|
|
Report(
|
2017-09-29 02:19:44 +08:00
|
|
|
"See https://github.com/google/sanitizers/issues/856 for possible "
|
2017-09-07 09:35:59 +08:00
|
|
|
"workarounds.\n");
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2017-07-31 14:48:34 +08:00
|
|
|
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|.
|
2017-11-21 01:41:57 +08:00
|
|
|
bool full_shadow_is_available = false;
|
2017-07-31 14:48:34 +08:00
|
|
|
if (shadow_start == kDefaultShadowSentinel) {
|
|
|
|
shadow_start = FindDynamicShadowStart();
|
2017-11-21 01:41:57 +08:00
|
|
|
if (SANITIZER_LINUX) full_shadow_is_available = true;
|
2017-07-31 14:48:34 +08:00
|
|
|
}
|
|
|
|
// Update the shadow memory address (potentially) used by instrumentation.
|
|
|
|
__asan_shadow_memory_dynamic_address = shadow_start;
|
|
|
|
|
|
|
|
if (kLowShadowBeg) shadow_start -= GetMmapGranularity();
|
2017-11-21 01:41:57 +08:00
|
|
|
|
|
|
|
if (!full_shadow_is_available)
|
|
|
|
full_shadow_is_available =
|
|
|
|
MemoryRangeIsAvailable(shadow_start, kHighShadowEnd);
|
2017-07-31 14:48:34 +08:00
|
|
|
|
|
|
|
#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",
|
2021-11-03 20:49:21 +08:00
|
|
|
(void*)shadow_start, (void*)kHighShadowEnd);
|
2017-09-07 09:35:59 +08:00
|
|
|
MaybeReportLinuxPIEBug();
|
2017-07-31 14:48:34 +08:00
|
|
|
DumpProcessMap();
|
|
|
|
Die();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
} // namespace __asan
|
2017-08-09 08:21:45 +08:00
|
|
|
|
2021-06-15 08:52:14 +08:00
|
|
|
#endif // !SANITIZER_FUCHSIA
|