Skip to content
Merged
Show file tree
Hide file tree
Changes from 8 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions compiler-rt/include/sanitizer/asan_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,13 @@ void SANITIZER_CDECL __asan_handle_no_return(void);
/// trace. Returns 1 if successful, 0 if not.
int SANITIZER_CDECL __asan_update_allocation_context(void *addr);

/// Disables fake stack for the current thread.
/// Temporarily disables use-after-return detection for current thread.
void SANITIZER_CDECL __asan_disable_fake_stack(void);

/// (Re)enables fake stack for the current thread.
void SANITIZER_CDECL __asan_enable_fake_stack(void);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
21 changes: 20 additions & 1 deletion compiler-rt/lib/asan/asan_fake_stack.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,9 +225,23 @@ static void SetTLSFakeStack(FakeStack*) {}
void ResetTLSFakeStack() {}
#endif // (SANITIZER_LINUX && !SANITIZER_ANDROID) || SANITIZER_FUCHSIA

static void DisableFakeStack() {
AsanThread* t = GetCurrentThread();
if (t) {
t->SetFakeStackEnabled(false);
}
}

static void EnableFakeStack() {
AsanThread* t = GetCurrentThread();
if (t) {
t->SetFakeStackEnabled(true);
}
}

static FakeStack* GetFakeStack() {
AsanThread* t = GetCurrentThread();
if (!t)
if (!t || !t->IsFakeStackEnabled())
return nullptr;
return t->get_or_create_fake_stack();
}
Expand Down Expand Up @@ -362,4 +376,9 @@ void __asan_allocas_unpoison(uptr top, uptr bottom) {
REAL(memset)(reinterpret_cast<void*>(MemToShadow(top)), 0,
(bottom - top) / ASAN_SHADOW_GRANULARITY);
}

SANITIZER_INTERFACE_ATTRIBUTE
void __asan_disable_fake_stack() { return DisableFakeStack(); }
SANITIZER_INTERFACE_ATTRIBUTE
void __asan_enable_fake_stack() { return EnableFakeStack(); }
} // extern "C"
2 changes: 2 additions & 0 deletions compiler-rt/lib/asan/asan_interface.inc
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ INTERFACE_FUNCTION(__asan_alloca_poison)
INTERFACE_FUNCTION(__asan_allocas_unpoison)
INTERFACE_FUNCTION(__asan_before_dynamic_init)
INTERFACE_FUNCTION(__asan_describe_address)
INTERFACE_FUNCTION(__asan_disable_fake_stack)
INTERFACE_FUNCTION(__asan_enable_fake_stack)
INTERFACE_FUNCTION(__asan_exp_load1)
INTERFACE_FUNCTION(__asan_exp_load2)
INTERFACE_FUNCTION(__asan_exp_load4)
Expand Down
1 change: 1 addition & 0 deletions compiler-rt/lib/asan/asan_thread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,7 @@ FakeStack *AsanThread::AsyncSignalSafeLazyInitFakeStack() {
void AsanThread::Init(const InitOptions *options) {
DCHECK_NE(tid(), kInvalidTid);
next_stack_top_ = next_stack_bottom_ = 0;
fake_stack_enabled_ = true;
atomic_store(&stack_switching_, false, memory_order_release);
CHECK_EQ(this->stack_size(), 0U);
SetThreadStackAndTls(options);
Expand Down
7 changes: 7 additions & 0 deletions compiler-rt/lib/asan/asan_thread.h
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,12 @@ class AsanThread {
GetStartData(&data, sizeof(data));
}

bool IsFakeStackEnabled() const { return fake_stack_enabled_; }
void SetFakeStackEnabled(bool enabled) {
fake_stack_enabled_ = enabled;
ResetTLSFakeStack();
}

private:
// NOTE: There is no AsanThread constructor. It is allocated
// via mmap() and *must* be valid in zero-initialized state.
Expand Down Expand Up @@ -179,6 +185,7 @@ class AsanThread {
DTLS *dtls_;

FakeStack *fake_stack_;
bool fake_stack_enabled_;
AsanThreadLocalMallocStorage malloc_storage_;
AsanStats stats_;
bool unwinding_;
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/asan_abi/asan_abi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ void *__asan_abi_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
void **end) {
return NULL;
}
void __asan_abi_disable_fake_stack(void) {}
void __asan_abi_enable_fake_stack(void) {}

// Functions concerning poisoning and unpoisoning fake stack alloca
void __asan_abi_alloca_poison(void *addr, size_t size) {}
Expand Down
3 changes: 3 additions & 0 deletions compiler-rt/lib/asan_abi/asan_abi.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,9 @@ void *__asan_abi_load_cxx_array_cookie(void **p);
void *__asan_abi_get_current_fake_stack();
void *__asan_abi_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
void **end);
void *__asan_abi_disable_fake_stack();
void *__asan_abi_enable_fake_stack();

// Functions concerning poisoning and unpoisoning fake stack alloca
void __asan_abi_alloca_poison(void *addr, size_t size);
void __asan_abi_allocas_unpoison(void *top, void *bottom);
Expand Down
2 changes: 2 additions & 0 deletions compiler-rt/lib/asan_abi/asan_abi_shim.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,8 @@ void *__asan_addr_is_in_fake_stack(void *fake_stack, void *addr, void **beg,
void **end) {
return __asan_abi_addr_is_in_fake_stack(fake_stack, addr, beg, end);
}
void __asan_disable_fake_stack(void) { return __asan_abi_disable_fake_stack(); }
void __asan_enable_fake_stack(void) { return __asan_abi_enable_fake_stack(); }

// Functions concerning poisoning and unpoisoning fake stack alloca
void __asan_alloca_poison(uptr addr, uptr size) {
Expand Down
32 changes: 32 additions & 0 deletions compiler-rt/test/asan/TestCases/disable_fake_stack.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clangxx_asan %s -o %t && %run %t

#include "defines.h"

#include <cassert>
#include <sanitizer/asan_interface.h>

volatile uintptr_t saved;

ATTRIBUTE_NOINLINE bool IsOnRealStack(uintptr_t caller_frame) {
uintptr_t this_frame =
reinterpret_cast<uintptr_t>(__builtin_frame_address(0));
return this_frame <= saved && saved <= caller_frame;
}

ATTRIBUTE_NOINLINE bool IsOnStack() {
volatile char temp = ' ';
saved = reinterpret_cast<uintptr_t>(&temp);
return IsOnRealStack(reinterpret_cast<uintptr_t>(__builtin_frame_address(0)));
}

int main(int argc, char *argv[]) {
assert(!IsOnStack());

__asan_disable_fake_stack();
assert(IsOnStack());

__asan_enable_fake_stack();
assert(!IsOnStack());

return 0;
}
Loading