[hwasan] Add heap tag randomization.

Summary:
Generate tags for heap allocations from a pseudo-random sequence
seeded with getrandom(), where available.

Reviewers: kcc, alekseyshl

Subscribers: kubamracek, llvm-commits

Differential Revision: https://reviews.llvm.org/D41616

llvm-svn: 321761
This commit is contained in:
Evgeniy Stepanov 2018-01-03 21:42:28 +00:00
parent febd5e3e37
commit 5e9d73c51a
3 changed files with 56 additions and 8 deletions

View File

@ -100,6 +100,9 @@ static AllocatorCache fallback_allocator_cache;
static SpinMutex fallback_mutex;
static atomic_uint8_t hwasan_allocator_tagging_enabled;
static const tag_t kFallbackAllocTag = 0xBB;
static const tag_t kFallbackFreeTag = 0xBC;
void HwasanAllocatorInit() {
atomic_store_relaxed(&hwasan_allocator_tagging_enabled,
!flags()->disable_allocator_tagging);
@ -145,10 +148,11 @@ static void *HwasanAllocate(StackTrace *stack, uptr size, uptr alignment,
if (zeroise)
internal_memset(allocated, 0, size);
void *user_ptr = (flags()->tag_in_malloc &&
atomic_load_relaxed(&hwasan_allocator_tagging_enabled))
? (void *)TagMemoryAligned((uptr)allocated, size, 0xBB)
: allocated;
void *user_ptr = allocated;
if (flags()->tag_in_malloc &&
atomic_load_relaxed(&hwasan_allocator_tagging_enabled))
user_ptr = (void *)TagMemoryAligned(
(uptr)user_ptr, size, t ? t->GenerateRandomTag() : kFallbackAllocTag);
HWASAN_MALLOC_HOOK(user_ptr, size);
return user_ptr;
@ -166,10 +170,11 @@ void HwasanDeallocate(StackTrace *stack, void *user_ptr) {
meta->free_context_id = StackDepotPut(*stack);
// This memory will not be reused by anyone else, so we are free to keep it
// poisoned.
HwasanThread *t = GetCurrentThread();
if (flags()->tag_in_free &&
atomic_load_relaxed(&hwasan_allocator_tagging_enabled))
TagMemoryAligned((uptr)p, size, 0xBC);
HwasanThread *t = GetCurrentThread();
TagMemoryAligned((uptr)p, size,
t ? t->GenerateRandomTag() : kFallbackFreeTag);
if (t) {
AllocatorCache *cache = GetAllocatorCache(&t->malloc_storage());
allocator.Deallocate(cache, p);
@ -195,8 +200,12 @@ void *HwasanReallocate(StackTrace *stack, void *user_old_p, uptr new_size,
meta->requested_size = new_size;
if (!atomic_load_relaxed(&hwasan_allocator_tagging_enabled))
return user_old_p;
if (flags()->retag_in_realloc)
return (void *)TagMemoryAligned((uptr)old_p, new_size, 0xCC);
if (flags()->retag_in_realloc) {
HwasanThread *t = GetCurrentThread();
return (void *)TagMemoryAligned(
(uptr)old_p, new_size,
t ? t->GenerateRandomTag() : kFallbackAllocTag);
}
if (new_size > old_size) {
tag_t tag = GetTagFromPointer((uptr)user_old_p);
TagMemoryAligned((uptr)old_p + old_size, new_size - old_size, tag);

View File

@ -8,6 +8,19 @@
namespace __hwasan {
static u32 RandomSeed() {
u32 seed;
do {
if (UNLIKELY(!GetRandom(reinterpret_cast<void *>(&seed), sizeof(seed),
/*blocking=*/false))) {
seed = static_cast<u32>(
(NanoTime() >> 12) ^
(reinterpret_cast<uptr>(__builtin_frame_address(0)) >> 4));
}
} while (!seed);
return seed;
}
HwasanThread *HwasanThread::Create(thread_callback_t start_routine,
void *arg) {
uptr PageSize = GetPageSizeCached();
@ -16,6 +29,7 @@ HwasanThread *HwasanThread::Create(thread_callback_t start_routine,
thread->start_routine_ = start_routine;
thread->arg_ = arg;
thread->destructor_iterations_ = GetPthreadDestructorIterations();
thread->random_state_ = RandomSeed();
return thread;
}
@ -72,4 +86,24 @@ thread_return_t HwasanThread::ThreadStart() {
return res;
}
static u32 xorshift(u32 state) {
state ^= state << 13;
state ^= state >> 17;
state ^= state << 5;
return state;
}
// Generate a (pseudo-)random non-zero tag.
tag_t HwasanThread::GenerateRandomTag() {
tag_t tag;
do {
if (!random_buffer_)
random_buffer_ = random_state_ = xorshift(random_state_);
CHECK(random_buffer_);
tag = random_buffer_ & 0xFF;
random_buffer_ >>= 8;
} while (!tag);
return tag;
}
} // namespace __hwasan

View File

@ -52,6 +52,8 @@ class HwasanThread {
HwasanThreadLocalMallocStorage &malloc_storage() { return malloc_storage_; }
tag_t GenerateRandomTag();
int destructor_iterations_;
private:
@ -70,6 +72,9 @@ class HwasanThread {
unsigned in_symbolizer_;
unsigned in_interceptor_scope_;
u32 random_state_;
u32 random_buffer_;
HwasanThreadLocalMallocStorage malloc_storage_;
};