diff --git a/compiler-rt/lib/asan/asan_allocator.cc b/compiler-rt/lib/asan/asan_allocator.cc index d573e0150ea0..70576ff7f676 100644 --- a/compiler-rt/lib/asan/asan_allocator.cc +++ b/compiler-rt/lib/asan/asan_allocator.cc @@ -119,25 +119,15 @@ static inline uint8_t SizeToSizeClass(size_t size) { return res; } -static void PoisonShadow(uintptr_t mem, size_t size, uint8_t poison) { - CHECK(IsAligned(mem, SHADOW_GRANULARITY)); - CHECK(IsAligned(mem + size, SHADOW_GRANULARITY)); - uintptr_t shadow_beg = MemToShadow(mem); - uintptr_t shadow_end = MemToShadow(mem + size); - real_memset((void*)shadow_beg, poison, shadow_end - shadow_beg); -} - // Given REDZONE bytes, we need to mark first size bytes // as addressable and the rest REDZONE-size bytes as unaddressable. -static void PoisonMemoryPartialRightRedzone(uintptr_t mem, size_t size) { +static void PoisonHeapPartialRightRedzone(uintptr_t mem, size_t size) { CHECK(size <= REDZONE); CHECK(IsAligned(mem, REDZONE)); CHECK(IsPowerOfTwo(SHADOW_GRANULARITY)); CHECK(IsPowerOfTwo(REDZONE)); CHECK(REDZONE >= SHADOW_GRANULARITY); - uint8_t *shadow = (uint8_t*)MemToShadow(mem); - PoisonShadowPartialRightRedzone(shadow, size, - REDZONE, SHADOW_GRANULARITY, + PoisonShadowPartialRightRedzone(mem, size, REDZONE, kAsanHeapRightRedzoneMagic); } @@ -687,8 +677,8 @@ static uint8_t *Allocate(size_t alignment, size_t size, AsanStackTrace *stack) { m->compressed_alloc_stack_size()); PoisonShadow(addr, rounded_size, 0); if (size < rounded_size) { - PoisonMemoryPartialRightRedzone(addr + rounded_size - REDZONE, - size & (REDZONE - 1)); + PoisonHeapPartialRightRedzone(addr + rounded_size - REDZONE, + size & (REDZONE - 1)); } if (size <= FLAG_max_malloc_fill_size) { real_memset((void*)addr, 0, rounded_size); diff --git a/compiler-rt/lib/asan/asan_globals.cc b/compiler-rt/lib/asan/asan_globals.cc index ab4a10c64686..ac89d755e44a 100644 --- a/compiler-rt/lib/asan/asan_globals.cc +++ b/compiler-rt/lib/asan/asan_globals.cc @@ -32,23 +32,21 @@ typedef std::map MapOfGlobals; static MapOfGlobals *g_all_globals = NULL; void PoisonRedZones(const Global &g) { - uintptr_t shadow = MemToShadow(g.beg); - size_t ShadowRZSize = kGlobalAndStackRedzone >> SHADOW_SCALE; - CHECK(ShadowRZSize == 1 || ShadowRZSize == 2 || ShadowRZSize == 4); + size_t shadow_rz_size = kGlobalAndStackRedzone >> SHADOW_SCALE; + CHECK(shadow_rz_size == 1 || shadow_rz_size == 2 || shadow_rz_size == 4); // full right redzone - uintptr_t right_rz2_offset = ShadowRZSize * + size_t g_aligned_size = kGlobalAndStackRedzone * ((g.size + kGlobalAndStackRedzone - 1) / kGlobalAndStackRedzone); - real_memset((uint8_t*)shadow + right_rz2_offset, - kAsanGlobalRedzoneMagic, ShadowRZSize); + PoisonShadow(g.beg + g_aligned_size, + kGlobalAndStackRedzone, kAsanGlobalRedzoneMagic); if ((g.size % kGlobalAndStackRedzone) != 0) { // partial right redzone - uint64_t right_rz1_offset = - ShadowRZSize * (g.size / kGlobalAndStackRedzone); - CHECK(right_rz1_offset == right_rz2_offset - ShadowRZSize); - PoisonShadowPartialRightRedzone((uint8_t*)(shadow + right_rz1_offset), + uint64_t g_aligned_down_size = kGlobalAndStackRedzone * + (g.size / kGlobalAndStackRedzone); + CHECK(g_aligned_down_size == g_aligned_size - kGlobalAndStackRedzone); + PoisonShadowPartialRightRedzone(g.beg + g_aligned_down_size, g.size % kGlobalAndStackRedzone, kGlobalAndStackRedzone, - SHADOW_GRANULARITY, kAsanGlobalRedzoneMagic); } } @@ -116,6 +114,7 @@ static void RegisterGlobal(const Global *g) { if (FLAG_report_globals >= 2) Printf("Added Global: beg=%p size=%ld name=%s\n", g->beg, g->size, g->name); + CHECK(AddrIsAlignedByGranularity(g->beg)); PoisonRedZones(*g); (*g_all_globals)[g->beg] = *g; } diff --git a/compiler-rt/lib/asan/asan_internal.h b/compiler-rt/lib/asan/asan_internal.h index 1de6eb175f02..2c643035e41f 100644 --- a/compiler-rt/lib/asan/asan_internal.h +++ b/compiler-rt/lib/asan/asan_internal.h @@ -36,28 +36,39 @@ namespace __asan { class AsanThread; struct AsanStackTrace; -// asan_rtl.cc +// asan_rtl.cc void CheckFailed(const char *cond, const char *file, int line); void ShowStatsAndAbort(); -// asan_globals.cc +// asan_globals.cc bool DescribeAddrIfGlobal(uintptr_t addr); -// asan_malloc_linux.cc / asan_malloc_mac.cc +// asan_malloc_linux.cc / asan_malloc_mac.cc void ReplaceSystemMalloc(); -// asan_linux.cc / asan_mac.cc +// asan_linux.cc / asan_mac.cc void *AsanDoesNotSupportStaticLinkage(); void *asan_mmap(void *addr, size_t length, int prot, int flags, int fd, uint64_t offset); ssize_t asan_write(int fd, const void *buf, size_t count); -// asan_printf.cc +// asan_printf.cc void RawWrite(const char *buffer); int SNPrint(char *buffer, size_t length, const char *format, ...); void Printf(const char *format, ...); void Report(const char *format, ...); +// asan_poisoning.cc +// Poisons the shadow memory for "size" bytes starting from "addr". +void PoisonShadow(uintptr_t addr, size_t size, uint8_t value); +// Poisons the shadow memory for "redzone_size" bytes starting from +// "addr + size". +void PoisonShadowPartialRightRedzone(uintptr_t addr, + uintptr_t size, + uintptr_t redzone_size, + uint8_t value); + + extern size_t FLAG_quarantine_size; extern int FLAG_demangle; extern bool FLAG_symbolize; @@ -134,26 +145,6 @@ const int kAsanGlobalRedzoneMagic = 0xf9; static const uintptr_t kCurrentStackFrameMagic = 0x41B58AB3; static const uintptr_t kRetiredStackFrameMagic = 0x45E0360E; -// Poison the shadow memory which corresponds to 'redzone_size' bytes -// of the original memory, where first 'size' bytes are addressable. -static inline void -PoisonShadowPartialRightRedzone(unsigned char *shadow, - uintptr_t size, - uintptr_t redzone_size, - uintptr_t shadow_granularity, - unsigned char magic) { - for (uintptr_t i = 0; i < redzone_size; - i+= shadow_granularity, shadow++) { - if (i + shadow_granularity <= size) { - *shadow = 0; // fully addressable - } else if (i >= size) { - *shadow = (shadow_granularity == 128) ? 0xff : magic; // unaddressable - } else { - *shadow = size - i; // first size-i bytes are addressable - } - } -} - // -------------------------- Atomic ---------------- {{{1 static inline int AtomicInc(int *a) { if (!FLAG_mt) return ++(*a); diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index 064cea92e3b8..63aba10a22f6 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -91,6 +91,10 @@ static inline bool AddrIsInShadow(uintptr_t a) { return AddrIsInLowShadow(a) || AddrIsInHighShadow(a); } +static inline bool AddrIsAlignedByGranularity(uintptr_t a) { + return (a & (SHADOW_GRANULARITY - 1)) == 0; +} + } // namespace __asan #endif // ASAN_MAPPING_H diff --git a/compiler-rt/lib/asan/asan_poisoning.cc b/compiler-rt/lib/asan/asan_poisoning.cc index 151b7508c5a1..06811053c38f 100644 --- a/compiler-rt/lib/asan/asan_poisoning.cc +++ b/compiler-rt/lib/asan/asan_poisoning.cc @@ -9,7 +9,7 @@ // // This file is a part of AddressSanitizer, an address sanity checker. // -// Memory poisoning that can be made by user application. +// Shadow memory poisoning by ASan RTL and by user application. //===----------------------------------------------------------------------===// #include "asan_interceptors.h" @@ -21,6 +21,33 @@ namespace __asan { +void PoisonShadow(uintptr_t addr, size_t size, uint8_t value) { + CHECK(AddrIsAlignedByGranularity(addr)); + CHECK(AddrIsAlignedByGranularity(addr + size)); + uintptr_t shadow_beg = MemToShadow(addr); + uintptr_t shadow_end = MemToShadow(addr + size); + real_memset((void*)shadow_beg, value, shadow_end - shadow_beg); +} + +void PoisonShadowPartialRightRedzone(uintptr_t addr, + uintptr_t size, + uintptr_t redzone_size, + uint8_t value) { + CHECK(AddrIsAlignedByGranularity(addr)); + uint8_t *shadow = (uint8_t*)MemToShadow(addr); + for (uintptr_t i = 0; i < redzone_size; + i += SHADOW_GRANULARITY, shadow++) { + if (i + SHADOW_GRANULARITY <= size) { + *shadow = 0; // fully addressable + } else if (i >= size) { + *shadow = (SHADOW_GRANULARITY == 128) ? 0xff : value; // unaddressable + } else { + *shadow = size - i; // first size-i bytes are addressable + } + } +} + + struct ShadowSegmentEndpoint { uint8_t *chunk; int8_t offset; // in [0, SHADOW_GRANULARITY) diff --git a/compiler-rt/lib/asan/asan_rtl.cc b/compiler-rt/lib/asan/asan_rtl.cc index a2cfb2afa05d..bb9c7b1d62cd 100644 --- a/compiler-rt/lib/asan/asan_rtl.cc +++ b/compiler-rt/lib/asan/asan_rtl.cc @@ -469,9 +469,7 @@ static void UnpoisonStackFromHereToTop() { CHECK(curr_thread); uintptr_t top = curr_thread->stack_top(); uintptr_t bottom = ((uintptr_t)&local_stack - kPageSize) & ~(kPageSize-1); - uintptr_t top_shadow = MemToShadow(top); - uintptr_t bot_shadow = MemToShadow(bottom); - real_memset((void*)bot_shadow, 0, top_shadow - bot_shadow); + PoisonShadow(bottom, top - bottom, 0); } extern "C" void WRAP(longjmp)(void *env, int val) {