Files
clang-p2996/compiler-rt/test/hwasan/TestCases/thread-uaf.c
Matt Morehouse 846ec2c3cc [HWASan] Ensure RNG is initialized in GenerateRandomTag
Fixes a CHECK-failure caused by glibc's pthread_getattr_np
implementation calling realloc.  Essentially, Thread::GenerateRandomTag
gets called during Thread::Init and before Thread::InitRandomState:

  HWAddressSanitizer: CHECK failed: hwasan_thread.cpp:134 "((random_buffer_)) != (0)" (0x0, 0x0) (tid=314)
    #0 0x55845475a662 in __hwasan::CheckUnwind()
    #1 0x558454778797 in __sanitizer::CheckFailed(char const*, int, char const*, unsigned long long, unsigned long long)
    #2 0x558454766461 in __hwasan::Thread::GenerateRandomTag(unsigned long)
    #3 0x55845475c58b in __hwasan::HwasanAllocate(__sanitizer::StackTrace*, unsigned long, unsigned long, bool)
    #4 0x55845475c80a in __hwasan::hwasan_realloc(void*, unsigned long, __sanitizer::StackTrace*)
    #5 0x5584547608aa in realloc
    #6 0x7f6f3a3d8c2c in pthread_getattr_np
    #7 0x5584547790dc in __sanitizer::GetThreadStackTopAndBottom(bool, unsigned long*, unsigned long*)
    #8 0x558454779651 in __sanitizer::GetThreadStackAndTls(bool, unsigned long*, unsigned long*, unsigned long*, unsigned long*)
    #9 0x558454761bca in __hwasan::Thread::InitStackAndTls(__hwasan::Thread::InitState const*)
    #10 0x558454761e5c in __hwasan::HwasanThreadList::CreateCurrentThread(__hwasan::Thread::InitState const*)
    #11 0x55845476184f in __hwasan_thread_enter
    #12 0x558454760def in HwasanThreadStartFunc(void*)
    #13 0x7f6f3a3d6fa2 in start_thread
    #14 0x7f6f3a15b4ce in __clone

Also reverts 7a3fb71c3c, as it's now
unneeded.

Reviewed By: vitalybuka

Differential Revision: https://reviews.llvm.org/D113045
2021-11-09 07:01:55 -08:00

60 lines
1.5 KiB
C

// Tests UAF detection where Allocate/Deallocate/Use
// happen in separate threads.
// RUN: %clang_hwasan %s -o %t && not %run %t 2>&1 | FileCheck %s
// REQUIRES: stable-runtime
#include <pthread.h>
#include <stdlib.h>
#include <stdio.h>
#include <sanitizer/hwasan_interface.h>
char *volatile x;
int state;
void *Allocate(void *arg) {
x = (char*)malloc(10);
__sync_fetch_and_add(&state, 1);
while (__sync_fetch_and_add(&state, 0) != 3) {}
return NULL;
}
void *Deallocate(void *arg) {
free(x);
__sync_fetch_and_add(&state, 1);
while (__sync_fetch_and_add(&state, 0) != 3) {}
return NULL;
}
void *Use(void *arg) {
x[5] = 42;
// CHECK: ERROR: HWAddressSanitizer: tag-mismatch on address
// CHECK: WRITE of size 1 {{.*}} in thread T3
// CHECK: thread-uaf.c:[[@LINE-3]]
// CHECK: Cause: use-after-free
// CHECK: freed by thread T2 here
// CHECK: in Deallocate
// CHECK: previously allocated here:
// CHECK: in Allocate
// CHECK-DAG: Thread: T2 0x
// CHECK-DAG: Thread: T3 0x
// CHECK-DAG: Thread: T0 0x
// CHECK-DAG: Thread: T1 0x
__sync_fetch_and_add(&state, 1);
return NULL;
}
int main() {
__hwasan_enable_allocator_tagging();
pthread_t t1, t2, t3;
pthread_create(&t1, NULL, Allocate, NULL);
while (__sync_fetch_and_add(&state, 0) != 1) {}
pthread_create(&t2, NULL, Deallocate, NULL);
while (__sync_fetch_and_add(&state, 0) != 2) {}
pthread_create(&t3, NULL, Use, NULL);
pthread_join(t1, NULL);
pthread_join(t2, NULL);
pthread_join(t3, NULL);
}