Refactor shadow poisoning done by asan-rt, no funtionality changes; patch by samsonov@google.com

llvm-svn: 145505
This commit is contained in:
Kostya Serebryany 2011-11-30 18:50:23 +00:00
parent 3ecf976ca9
commit 15dd3f2500
6 changed files with 63 additions and 54 deletions

View File

@ -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);

View File

@ -32,23 +32,21 @@ typedef std::map<uintptr_t, Global> 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;
}

View File

@ -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);

View File

@ -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

View File

@ -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)

View File

@ -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) {