Skip to content

Commit

Permalink
[𝘀𝗽𝗿] initial version
Browse files Browse the repository at this point in the history
Created using spr 1.3.4
  • Loading branch information
zacklj89 committed Dec 1, 2023
1 parent ff96567 commit 1449b52
Show file tree
Hide file tree
Showing 3 changed files with 80 additions and 6 deletions.
11 changes: 11 additions & 0 deletions compiler-rt/lib/asan/asan_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,17 @@ void InstallAtExitCheckLeaks();
if (&__asan_on_error) \
__asan_on_error()

// Unless synchronization is used during initialization,
// race conditions can appear causing incorrect states or internal check
// failures, depending on the loading thread and when ASAN is loaded on Windows.
// From a multithreaded managed environment, if an ASAN instrumented dll
// is loading on a spawned thread, an intercepted function may be called on
// multiple threads while ASAN is still in the process of initialization. This
// can also cause the ASAN thread registry to create the "main" thread after
// another thread, resulting in a TID != 0.
//
// Two threads can also race to initialize ASAN, resulting in either incorrect
// state or internal check failures for init already running.
bool AsanInited();
bool AsanInitIsRunning(); // Used to avoid infinite recursion in __asan_init().
extern bool replace_intrin_cached;
Expand Down
51 changes: 45 additions & 6 deletions compiler-rt/lib/asan/asan_rtl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,16 +71,54 @@ static void CheckUnwind() {
}

// -------------------------- Globals --------------------- {{{1
static int asan_inited = 0;
static int asan_init_is_running = 0;
#if SANITIZER_WINDOWS
atomic_uint8_t asan_inited{0};
atomic_uint8_t asan_init_is_running{0};
#else
int asan_inited = 0;
int asan_init_is_running = 0;
#endif

void SetAsanInited(u32 val) { asan_inited = val; }
void SetAsanInited(u32 val) {
#if SANITIZER_WINDOWS
atomic_store(&asan_inited, val, memory_order_release);
#else
asan_inited = val;
#endif
}

void SetAsanInitIsRunning(u32 val) { asan_init_is_running = val; }
void SetAsanInitIsRunning(u32 val) {
#if SANITIZER_WINDOWS
atomic_store(&asan_init_is_running, val, memory_order_release);
#else
asan_init_is_running = val;
#endif
}

bool AsanInited() { return asan_inited == 1; }
bool AsanInited() {
#if SANITIZER_WINDOWS
return atomic_load(&asan_inited, memory_order_acquire) == 1;
#else
return asan_inited == 1;
#endif
}

bool AsanInitIsRunning() { return asan_init_is_running == 1; }
bool AsanInitIsRunning() {
#if SANITIZER_WINDOWS
return atomic_load(&asan_init_is_running, memory_order_acquire) == 1;
#else
return asan_init_is_running == 1;
#endif
}

void CheckAsanInitRunning() {
#if SANITIZER_WINDOWS
while (AsanInitIsRunning()) {
// If ASAN is initializing on another thread, wait for it to finish.
internal_sched_yield();
}
#endif
}

bool replace_intrin_cached;

Expand Down Expand Up @@ -391,6 +429,7 @@ void PrintAddressSpaceLayout() {
}

static void AsanInitInternal() {
CheckAsanInitRunning();
if (LIKELY(AsanInited()))
return;
SanitizerToolName = "AddressSanitizer";
Expand Down
24 changes: 24 additions & 0 deletions compiler-rt/lib/asan/asan_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ namespace __asan {

// AsanThreadContext implementation.

#if SANITIZER_WINDOWS
static atomic_uint8_t main_thread_created{0};
#endif

void AsanThreadContext::OnCreated(void *arg) {
CreateThreadContextArgs *args = static_cast<CreateThreadContextArgs *>(arg);
if (args->stack)
Expand Down Expand Up @@ -93,6 +97,12 @@ AsanThreadContext *GetThreadContextByTidLocked(u32 tid) {
AsanThread *AsanThread::Create(const void *start_data, uptr data_size,
u32 parent_tid, StackTrace *stack,
bool detached) {
#if SANITIZER_WINDOWS
while (atomic_load(&main_thread_created, memory_order_acquire) == 0) {
// If another thread is trying to be created before the main thread, wait.
internal_sched_yield();
}
#endif
uptr PageSize = GetPageSizeCached();
uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
AsanThread *thread = (AsanThread *)MmapOrDie(size, __func__);
Expand Down Expand Up @@ -288,11 +298,25 @@ void AsanThread::ThreadStart(tid_t os_id) {
}

AsanThread *CreateMainThread() {
// Depending on the loading thread, specifically in managed scenarios, the main
// thread can be created after other threads on Windows. This ensures we start
// the main thread before those threads.
# if SANITIZER_WINDOWS
uptr PageSize = GetPageSizeCached();
uptr size = RoundUpTo(sizeof(AsanThread), PageSize);
AsanThread *main_thread = (AsanThread *)MmapOrDie(size, __func__);
AsanThreadContext::CreateThreadContextArgs args = {main_thread, nullptr};
asanThreadRegistry().CreateThread(0, true, kMainTid, &args);
SetCurrentThread(main_thread);
main_thread->ThreadStart(internal_getpid());
atomic_store(&main_thread_created, 1, memory_order_release);
# else
AsanThread *main_thread = AsanThread::Create(
/* parent_tid */ kMainTid,
/* stack */ nullptr, /* detached */ true);
SetCurrentThread(main_thread);
main_thread->ThreadStart(internal_getpid());
# endif
return main_thread;
}

Expand Down

0 comments on commit 1449b52

Please sign in to comment.