forked from OSchip/llvm-project
[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:
parent
febd5e3e37
commit
5e9d73c51a
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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_;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue