-
Notifications
You must be signed in to change notification settings - Fork 13.5k
[asan] Implement address sanitizer on AIX: shadow memory #136874
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,184 @@ | ||
//===-- asan_mapping_aix64.h ------------------------------------*- C++ -*-===// | ||
// | ||
// 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. | ||
// | ||
// AIX64-specific definitions for ASan memory mapping. | ||
//===----------------------------------------------------------------------===// | ||
#ifndef ASAN_MAPPING_AIX64_H | ||
#define ASAN_MAPPING_AIX64_H | ||
|
||
// https://www.ibm.com/docs/en/aix/7.3?topic=concepts-system-memory-allocation-using-malloc-subsystem | ||
// | ||
// For 64-bit on AIX, | ||
// - Data, heap, bss region is from 0x0000 0001 0000 0000 to | ||
// 0x07ff ffff ffff ffff (1ULL << 59). | ||
// - Shared library regions is from: | ||
// 0x0900 0000 0000 0000 to 0x09ff ffff ffff ffff | ||
// or 0x0800 0000 0000 0000 to 0x08ff ffff ffff ffff ((1ULL << 52) * 2) | ||
// - mmap region is from 0x0a00 0000 0000 0000 to 0x0aff ffff ffff ffff | ||
// (1ULL << 52). | ||
// - Initial stack region is from 0x0f00 0000 0000 0000 to | ||
// 0x0fff ffff ffff ffff (1ULL << 56). | ||
// | ||
// All above ranges are too big. And after verifying on AIX,(these datas are | ||
// from experiments on AIX72, AIX OS may change this layout in future) | ||
// - the biggest heap size is 1ULL << 47. | ||
// - the biggest global variable size is 1ULL << 29. (Which may be put in shared | ||
// library data regions because global variables may be compiled to shared | ||
// libraries.) | ||
// the related address range for shared library data regions is: | ||
// 0x0900 1000 0000 0000 to 0x0900 1001 0000 0000 | ||
// or 0x0800 1000 0000 0000 to 0x0800 1001 0000 0000 (when above range is | ||
// used by system libraries.) | ||
// - the biggest mmap size is 1ULL << 46. | ||
// - the biggest stack size is 1ULL << 32. | ||
// | ||
// We don't need so big heap and mmap, calling mmap for shadow memory for such | ||
// big heap and mmap is quite slow on AIX, so to balance runtime and examinable | ||
// memory size, we use 1ULL << 39(512GB) as size for each region except mmap | ||
// region. For mmap region, aix system mmap function may return a big range | ||
// address, we allocate 1ULL << 41(2TB). | ||
// | ||
// So the reasonable user space region size is: | ||
// - Data, heap, bss is from 0x0 to 0x0000 007f ffff ffff | ||
// - Shared library data is from: | ||
// 0x0900 1000 0000 0000 to 0x0900 107f ffff ffff | ||
// or 0x0800 1000 0000 0000 to 0x0800 107f ffff ffff | ||
// - mmap is from 0x0a00 0000 0000 0000 to 0x0a00 01ff ffff ffff | ||
// - Stack is from 0x0fff ff80 0000 0000 to 0x0fff ffff ffff ffff | ||
// | ||
// AIX64 set ASAN_SHADOW_OFFSET_CONST at 0x0a01000000000000 because mmap | ||
// memory starts at 0x0a00000000000000 and shadow memory should be allocated | ||
// there. And we keep 0x0a00000000000000 to 0x0a01000000000000 For user mmap | ||
// usage. | ||
|
||
// NOTE: Users are not expected to use `mmap` specifying fixed address which is | ||
// inside the shadow memory ranges. | ||
|
||
// Default AIX64 mapping: | ||
// || `[0x0fffff8000000000, 0x0fffffffffffffff]` || HighMem || | ||
// || `[0x0a80fff000000000, 0x0a80ffffffffffff]` || HighShadow || | ||
// || `[0x0a41000000000000, 0x0a41003fffffffff]` || MidShadow || | ||
// || `[0x0a21020000000000, 0x0a21020fffffffff]` || Mid2Shadow || | ||
// || `[0x0a01020000000000, 0x0a01020fffffffff]` || Mid3Shadow || | ||
// || `[0x0a01000000000000, 0x0a01000fffffffff]` || LowShadow || | ||
// || `[0x0a00000000000000, 0x0a0001ffffffffff]` || MidMem || | ||
// || `[0x0900100000000000, 0x0900107fffffffff]` || Mid2Mem || | ||
// || `[0x0800100000000000, 0x0800107fffffffff]` || Mid3Mem || | ||
// || `[0x0000000000000000, 0x0000007fffffffff]` || LowMem || | ||
|
||
#define VMA_BITS 58 | ||
#define HIGH_BITS (64 - VMA_BITS) | ||
|
||
#define MEM_TO_SHADOW(mem) \ | ||
((((mem) << HIGH_BITS) >> (HIGH_BITS + (ASAN_SHADOW_SCALE))) + \ | ||
ASAN_SHADOW_OFFSET) | ||
|
||
#define SHADOW_TO_MEM(ptr) (__asan::ShadowToMemAIX64(ptr)) | ||
|
||
#define kLowMemBeg 0ULL | ||
#define kLowMemEnd 0x0000007fffffffffULL | ||
|
||
#define kLowShadowBeg ASAN_SHADOW_OFFSET | ||
#define kLowShadowEnd MEM_TO_SHADOW(kLowMemEnd) | ||
|
||
#define kHighMemBeg 0x0fffff8000000000ULL | ||
|
||
#define kHighShadowBeg MEM_TO_SHADOW(kHighMemBeg) | ||
#define kHighShadowEnd MEM_TO_SHADOW(kHighMemEnd) | ||
|
||
#define kMidMemBeg 0x0a00000000000000ULL | ||
#define kMidMemEnd 0x0a0001ffffffffffULL | ||
|
||
#define kMidShadowBeg MEM_TO_SHADOW(kMidMemBeg) | ||
#define kMidShadowEnd MEM_TO_SHADOW(kMidMemEnd) | ||
|
||
#define kMid2MemBeg 0x0900100000000000ULL | ||
#define kMid2MemEnd 0x0900107fffffffffULL | ||
|
||
#define kMid2ShadowBeg MEM_TO_SHADOW(kMid2MemBeg) | ||
#define kMid2ShadowEnd MEM_TO_SHADOW(kMid2MemEnd) | ||
|
||
#define kMid3MemBeg 0x0800100000000000ULL | ||
#define kMid3MemEnd 0x0800107fffffffffULL | ||
|
||
#define kMid3ShadowBeg MEM_TO_SHADOW(kMid3MemBeg) | ||
#define kMid3ShadowEnd MEM_TO_SHADOW(kMid3MemEnd) | ||
|
||
// AIX does not care about the gaps. | ||
#define kZeroBaseShadowStart 0 | ||
#define kZeroBaseMaxShadowStart 0 | ||
|
||
#define kShadowGapBeg 0 | ||
#define kShadowGapEnd 0 | ||
|
||
#define kShadowGap2Beg 0 | ||
#define kShadowGap2End 0 | ||
|
||
#define kShadowGap3Beg 0 | ||
#define kShadowGap3End 0 | ||
|
||
#define kShadowGap4Beg 0 | ||
#define kShadowGap4End 0 | ||
|
||
namespace __asan { | ||
|
||
static inline bool AddrIsInLowMem(uptr a) { | ||
PROFILE_ASAN_MAPPING(); | ||
return a <= kLowMemEnd; | ||
} | ||
|
||
static inline bool AddrIsInLowShadow(uptr a) { | ||
PROFILE_ASAN_MAPPING(); | ||
return a >= kLowShadowBeg && a <= kLowShadowEnd; | ||
} | ||
|
||
static inline bool AddrIsInMidMem(uptr a) { | ||
PROFILE_ASAN_MAPPING(); | ||
return (a >= kMidMemBeg && a <= kMidMemEnd) || | ||
(a >= kMid2MemBeg && a <= kMid2MemEnd) || | ||
(a >= kMid3MemBeg && a <= kMid3MemEnd); | ||
} | ||
|
||
static inline bool AddrIsInMidShadow(uptr a) { | ||
PROFILE_ASAN_MAPPING(); | ||
return (a >= kMidShadowBeg && a <= kMidShadowEnd) || | ||
(a >= kMid2ShadowBeg && a <= kMid2ShadowEnd) || | ||
(a >= kMid3ShadowBeg && a <= kMid3ShadowEnd); | ||
} | ||
|
||
static inline bool AddrIsInHighMem(uptr a) { | ||
PROFILE_ASAN_MAPPING(); | ||
return kHighMemBeg && a >= kHighMemBeg && a <= kHighMemEnd; | ||
} | ||
|
||
static inline bool AddrIsInHighShadow(uptr a) { | ||
PROFILE_ASAN_MAPPING(); | ||
return kHighMemBeg && a >= kHighShadowBeg && a <= kHighShadowEnd; | ||
} | ||
|
||
static inline bool AddrIsInShadowGap(uptr a) { return false; } | ||
|
||
static inline constexpr uptr ShadowToMemAIX64(uptr p) { | ||
PROFILE_ASAN_MAPPING(); | ||
p -= ASAN_SHADOW_OFFSET; | ||
p <<= ASAN_SHADOW_SCALE; | ||
if (p >= 0x3ffff8000000000ULL) { | ||
// HighMem | ||
p |= (0x03ULL << VMA_BITS); | ||
} else if (p >= 0x100000000000ULL) { | ||
// MidShadow/Mid2Shadow/Mid2Shadow | ||
p |= (0x02ULL << VMA_BITS); | ||
} | ||
return p; | ||
} | ||
|
||
} // namespace __asan | ||
|
||
#endif // ASAN_MAPPING_AIX64_H |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -55,13 +55,23 @@ static void AsanDie() { | |
WaitForDebugger(flags()->sleep_before_dying, "before dying"); | ||
|
||
if (flags()->unmap_shadow_on_exit) { | ||
#if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We don't use == 1 like here |
||
UnmapOrDie((void *)kHighShadowBeg, kHighShadowEnd - kHighShadowBeg); | ||
UnmapOrDie((void *)kMidShadowBeg, kMidShadowEnd - kMidShadowBeg); | ||
|
||
UnmapOrDie((void *)kMid2ShadowBeg, kMid2ShadowEnd - kMid2ShadowBeg); | ||
UnmapOrDie((void *)kMid3ShadowBeg, kMid3ShadowEnd - kMid3ShadowBeg); | ||
|
||
UnmapOrDie((void *)kLowShadowBeg, kLowShadowEnd - kLowShadowBeg); | ||
#else | ||
if (kMidMemBeg) { | ||
UnmapOrDie((void*)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); | ||
UnmapOrDie((void*)kMidMemEnd, kHighShadowEnd - kMidMemEnd); | ||
UnmapOrDie((void *)kLowShadowBeg, kMidMemBeg - kLowShadowBeg); | ||
UnmapOrDie((void *)kMidMemEnd, kHighShadowEnd - kMidMemEnd); | ||
} else { | ||
if (kHighShadowEnd) | ||
UnmapOrDie((void*)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); | ||
UnmapOrDie((void *)kLowShadowBeg, kHighShadowEnd - kLowShadowBeg); | ||
} | ||
#endif | ||
} | ||
} | ||
|
||
|
@@ -85,7 +95,11 @@ bool AsanInited() { | |
bool replace_intrin_cached; | ||
|
||
#if !ASAN_FIXED_MAPPING | ||
# if !(SANITIZER_AIX && __powerpc64__) | ||
uptr kHighMemEnd, kMidMemBeg, kMidMemEnd; | ||
# else | ||
uptr kHighMemEnd; | ||
# endif | ||
#endif | ||
|
||
// -------------------------- Misc ---------------- {{{1 | ||
|
@@ -341,17 +355,29 @@ void PrintAddressSpaceLayout() { | |
(void*)kHighShadowBeg, (void*)kHighShadowEnd); | ||
} | ||
if (kMidMemBeg) { | ||
// AIX shadowgap is always set to 0 for 64-bit. | ||
#if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64 | ||
Printf("|| `[%p, %p]` || ShadowGap3 ||\n", | ||
(void*)kShadowGap3Beg, (void*)kShadowGap3End); | ||
#endif | ||
Printf("|| `[%p, %p]` || MidMem ||\n", | ||
(void*)kMidMemBeg, (void*)kMidMemEnd); | ||
#if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64 | ||
Printf("|| `[%p, %p]` || ShadowGap2 ||\n", | ||
(void*)kShadowGap2Beg, (void*)kShadowGap2End); | ||
#endif | ||
Printf("|| `[%p, %p]` || MidShadow ||\n", | ||
(void*)kMidShadowBeg, (void*)kMidShadowEnd); | ||
} | ||
#if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. remove == 1 |
||
Printf("|| `[%p, %p]` || Mid2Shadow ||\n", (void *)kMid2ShadowBeg, | ||
(void *)kMid2ShadowEnd); | ||
Printf("|| `[%p, %p]` || Mid3Shadow ||\n", (void *)kMid3ShadowBeg, | ||
(void *)kMid3ShadowEnd); | ||
#else | ||
Printf("|| `[%p, %p]` || ShadowGap ||\n", | ||
(void*)kShadowGapBeg, (void*)kShadowGapEnd); | ||
#endif | ||
if (kLowShadowBeg) { | ||
Printf("|| `[%p, %p]` || LowShadow ||\n", | ||
(void*)kLowShadowBeg, (void*)kLowShadowEnd); | ||
|
@@ -371,6 +397,13 @@ void PrintAddressSpaceLayout() { | |
(void*)MEM_TO_SHADOW(kMidShadowBeg), | ||
(void*)MEM_TO_SHADOW(kMidShadowEnd)); | ||
} | ||
// On AIX, for 64-bit, there are totally 3 mid memory regions. | ||
#if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64 | ||
Printf(" %p %p", (void *)MEM_TO_SHADOW(kMid2ShadowBeg), | ||
(void *)MEM_TO_SHADOW(kMid2ShadowEnd)); | ||
Printf(" %p %p", (void *)MEM_TO_SHADOW(kMid3ShadowBeg), | ||
(void *)MEM_TO_SHADOW(kMid3ShadowEnd)); | ||
#endif | ||
Printf("\n"); | ||
Printf("redzone=%zu\n", (uptr)flags()->redzone); | ||
Printf("max_redzone=%zu\n", (uptr)flags()->max_redzone); | ||
|
@@ -386,7 +419,10 @@ void PrintAddressSpaceLayout() { | |
CHECK(ASAN_SHADOW_SCALE >= 3 && ASAN_SHADOW_SCALE <= 7); | ||
if (kMidMemBeg) | ||
CHECK(kMidShadowBeg > kLowShadowEnd && | ||
// On AIX 64-bit, we have a highly customized memory layout. | ||
#if !SANITIZER_AIX || SANITIZER_WORDSIZE != 64 | ||
kMidMemBeg > kMidShadowEnd && | ||
#endif | ||
kHighShadowBeg > kMidMemEnd); | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -91,9 +91,25 @@ void InitializeShadowMemory() { | |
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); | ||
# if SANITIZER_AIX == 1 && SANITIZER_WORDSIZE == 64 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. all this nesting is hard to read |
||
// Fox 64-bit AIX, there is a very customized memory layout, we don't have | ||
// the ability to protect all the shadow gaps. But we need to reserve | ||
// shadow memory for middle memory. | ||
if (kMidShadowBeg) | ||
ReserveShadowMemoryRange(kMidShadowBeg, kMidShadowEnd, "mid shadow"); | ||
|
||
if (kMid2ShadowBeg) | ||
ReserveShadowMemoryRange(kMid2ShadowBeg, kMid2ShadowEnd, "mid2 shadow"); | ||
|
||
if (kMid3ShadowBeg) | ||
ReserveShadowMemoryRange(kMid3ShadowBeg, kMid3ShadowEnd, "mid3 shadow"); | ||
# else | ||
if (kShadowGapBeg) { | ||
// protect the gap. | ||
ProtectGap(kShadowGapBeg, kShadowGapEnd - kShadowGapBeg + 1); | ||
CHECK_EQ(kShadowGapEnd, kHighShadowBeg - 1); | ||
} | ||
# endif | ||
} else if (kMidMemBeg && | ||
MemoryRangeIsAvailable(shadow_start, kMidMemBeg - 1) && | ||
MemoryRangeIsAvailable(kMidMemEnd + 1, kHighShadowEnd)) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
// RUN: %clang_asan -O0 %s -o %t | ||
// RUN: %env_asan_opts=verbosity=2 %run %t 2>&1 | FileCheck %s | ||
// REQUIRES: powerpc64-target-arch | ||
|
||
#include <stdio.h> | ||
|
||
int main() { | ||
// CHECK: || `[0xfffff8000000000, 0xfffffffffffffff]` || HighMem || | ||
// CHECK: || `[0xa80fff000000000, 0xa80ffffffffffff]` || HighShadow || | ||
// CHECK: || `[0xa00000000000000, 0xa0001ffffffffff]` || MidMem || | ||
// CHECK: || `[0xa41000000000000, 0xa41003fffffffff]` || MidShadow || | ||
// CHECK: || `[0xa21020000000000, 0xa21020fffffffff]` || Mid2Shadow || | ||
// CHECK: || `[0xa01020000000000, 0xa01020fffffffff]` || Mid3Shadow || | ||
// CHECK: || `[0xa01000000000000, 0xa01000fffffffff]` || LowShadow || | ||
// CHECK: || `[0x000000000000, 0x007fffffffff]` || LowMem || | ||
|
||
return 0; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just extend
if (value || SANITIZER_WINDOWS || SANITIZER_AIX ||