forked from OSchip/llvm-project
hwasan: Add __hwasan_init_static() function.
This function initializes enough of the runtime to be able to run instrumented code in a statically linked executable. It replaces __hwasan_shadow_init() which wasn't doing enough initialization for instrumented code that uses either TLS or IFUNC to work. Differential Revision: https://reviews.llvm.org/D57490 llvm-svn: 352816
This commit is contained in:
parent
6f94a033a7
commit
886b7cc107
|
@ -18,11 +18,15 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
// Initialize shadow but not the rest of the runtime.
|
||||
// Libc hook for program startup in statically linked executables.
|
||||
// Initializes enough of the runtime to run instrumented code. This function
|
||||
// should only be called in statically linked executables because it modifies
|
||||
// the GOT, which won't work in regular binaries because RELRO will already
|
||||
// have been applied by the time the function is called. This also means that
|
||||
// the function should be called before libc applies RELRO.
|
||||
// Does not call libc unless there is an error.
|
||||
// Can be called multiple times, or not at all (in which case shadow will
|
||||
// be initialized in compiler-inserted __hwasan_init() call).
|
||||
void __hwasan_shadow_init(void);
|
||||
// Can be called multiple times.
|
||||
void __hwasan_init_static(void);
|
||||
|
||||
// This function may be optionally provided by user and should return
|
||||
// a string containing HWASan runtime options. See asan_flags.h for details.
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
|
||||
#include "hwasan.h"
|
||||
#include "hwasan_checks.h"
|
||||
#include "hwasan_dynamic_shadow.h"
|
||||
#include "hwasan_poisoning.h"
|
||||
#include "hwasan_report.h"
|
||||
#include "hwasan_thread.h"
|
||||
|
@ -57,7 +58,7 @@ Flags *flags() {
|
|||
}
|
||||
|
||||
int hwasan_inited = 0;
|
||||
int hwasan_shadow_inited = 0;
|
||||
int hwasan_instrumentation_inited = 0;
|
||||
bool hwasan_init_is_running;
|
||||
|
||||
int hwasan_report_count = 0;
|
||||
|
@ -246,6 +247,22 @@ const char *GetStackFrameDescr(uptr pc) {
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
// Prepare to run instrumented code on the main thread.
|
||||
void InitInstrumentation() {
|
||||
if (hwasan_instrumentation_inited) return;
|
||||
|
||||
if (!InitShadow()) {
|
||||
Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
|
||||
DumpProcessMap();
|
||||
Die();
|
||||
}
|
||||
|
||||
InitThreads();
|
||||
hwasanThreadList().CreateCurrentThread();
|
||||
|
||||
hwasan_instrumentation_inited = 1;
|
||||
}
|
||||
|
||||
} // namespace __hwasan
|
||||
|
||||
// Interface.
|
||||
|
@ -254,20 +271,15 @@ using namespace __hwasan;
|
|||
|
||||
uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol.
|
||||
|
||||
void __hwasan_shadow_init() {
|
||||
if (hwasan_shadow_inited) return;
|
||||
if (!InitShadow()) {
|
||||
Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
|
||||
DumpProcessMap();
|
||||
Die();
|
||||
}
|
||||
hwasan_shadow_inited = 1;
|
||||
}
|
||||
|
||||
void __hwasan_init_frames(uptr beg, uptr end) {
|
||||
InitFrameDescriptors(beg, end);
|
||||
}
|
||||
|
||||
void __hwasan_init_static() {
|
||||
InitShadowGOT();
|
||||
InitInstrumentation();
|
||||
}
|
||||
|
||||
void __hwasan_init() {
|
||||
CHECK(!hwasan_init_is_running);
|
||||
if (hwasan_inited) return;
|
||||
|
@ -288,10 +300,11 @@ void __hwasan_init() {
|
|||
|
||||
DisableCoreDumperIfNecessary();
|
||||
|
||||
__hwasan_shadow_init();
|
||||
InitInstrumentation();
|
||||
|
||||
InitThreads();
|
||||
hwasanThreadList().CreateCurrentThread();
|
||||
// Needs to be called here because flags()->random_tags might not have been
|
||||
// initialized when InitInstrumentation() was called.
|
||||
GetCurrentThread()->InitRandomState();
|
||||
|
||||
MadviseShadow();
|
||||
|
||||
|
|
|
@ -70,6 +70,7 @@ extern int hwasan_report_count;
|
|||
bool ProtectRange(uptr beg, uptr end);
|
||||
bool InitShadow();
|
||||
void InitThreads();
|
||||
void InitInstrumentation();
|
||||
void MadviseShadow();
|
||||
char *GetProcSelfMaps();
|
||||
void InitializeInterceptors();
|
||||
|
|
|
@ -18,6 +18,9 @@
|
|||
#include "sanitizer_common/sanitizer_common.h"
|
||||
#include "sanitizer_common/sanitizer_posix.h"
|
||||
|
||||
#include <elf.h>
|
||||
#include <link.h>
|
||||
|
||||
// The code in this file needs to run in an unrelocated binary. It should not
|
||||
// access any external symbol, including its own non-hidden globals.
|
||||
|
||||
|
@ -118,10 +121,28 @@ decltype(__hwasan_shadow)* __hwasan_premap_shadow() {
|
|||
INTERFACE_ATTRIBUTE __attribute__((ifunc("__hwasan_premap_shadow")))
|
||||
void __hwasan_shadow();
|
||||
|
||||
extern __attribute((visibility("hidden"))) ElfW(Rela) __rela_iplt_start[],
|
||||
__rela_iplt_end[];
|
||||
|
||||
} // extern "C"
|
||||
|
||||
namespace __hwasan {
|
||||
|
||||
void InitShadowGOT() {
|
||||
// Call the ifunc resolver for __hwasan_shadow and fill in its GOT entry. This
|
||||
// needs to be done before other ifunc resolvers (which are handled by libc)
|
||||
// because a resolver might read __hwasan_shadow.
|
||||
typedef ElfW(Addr) (*ifunc_resolver_t)(void);
|
||||
for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) {
|
||||
ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
|
||||
ElfW(Addr) resolver = r->r_addend;
|
||||
if (resolver == reinterpret_cast<ElfW(Addr)>(&__hwasan_premap_shadow)) {
|
||||
*offset = reinterpret_cast<ifunc_resolver_t>(resolver)();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
|
||||
if (IsPremapShadowAvailable())
|
||||
return FindPremappedShadowStart(shadow_size_bytes);
|
||||
|
@ -132,10 +153,12 @@ uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
|
|||
#else
|
||||
namespace __hwasan {
|
||||
|
||||
void InitShadowGOT() {}
|
||||
|
||||
uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
|
||||
return MapDynamicShadow(shadow_size_bytes);
|
||||
}
|
||||
|
||||
} // namespace __hwasan
|
||||
#
|
||||
|
||||
#endif // SANITIZER_ANDROID
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
namespace __hwasan {
|
||||
|
||||
uptr FindDynamicShadowStart(uptr shadow_size_bytes);
|
||||
void InitShadowGOT();
|
||||
|
||||
} // namespace __hwasan
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
extern "C" {
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __hwasan_shadow_init();
|
||||
void __hwasan_init_static();
|
||||
|
||||
SANITIZER_INTERFACE_ATTRIBUTE
|
||||
void __hwasan_init();
|
||||
|
|
|
@ -236,7 +236,7 @@ void InstallAtExitHandler() {
|
|||
// ---------------------- TSD ---------------- {{{1
|
||||
|
||||
extern "C" void __hwasan_thread_enter() {
|
||||
hwasanThreadList().CreateCurrentThread();
|
||||
hwasanThreadList().CreateCurrentThread()->InitRandomState();
|
||||
}
|
||||
|
||||
extern "C" void __hwasan_thread_exit() {
|
||||
|
@ -289,7 +289,9 @@ uptr *GetCurrentThreadLongPtr() {
|
|||
#if SANITIZER_ANDROID
|
||||
void AndroidTestTlsSlot() {
|
||||
uptr kMagicValue = 0x010203040A0B0C0D;
|
||||
*(uptr *)get_android_tls_ptr() = kMagicValue;
|
||||
uptr *tls_ptr = GetCurrentThreadLongPtr();
|
||||
uptr old_value = *tls_ptr;
|
||||
*tls_ptr = kMagicValue;
|
||||
dlerror();
|
||||
if (*(uptr *)get_android_tls_ptr() != kMagicValue) {
|
||||
Printf(
|
||||
|
@ -297,6 +299,7 @@ void AndroidTestTlsSlot() {
|
|||
"for dlerror().\n");
|
||||
Die();
|
||||
}
|
||||
*tls_ptr = old_value;
|
||||
}
|
||||
#else
|
||||
void AndroidTestTlsSlot() {}
|
||||
|
|
|
@ -25,10 +25,13 @@ static u32 RandomSeed() {
|
|||
return seed;
|
||||
}
|
||||
|
||||
void Thread::InitRandomState() {
|
||||
random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
|
||||
}
|
||||
|
||||
void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size) {
|
||||
static u64 unique_id;
|
||||
unique_id_ = unique_id++;
|
||||
random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
|
||||
if (auto sz = flags()->heap_history_size)
|
||||
heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@ typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer;
|
|||
class Thread {
|
||||
public:
|
||||
void Init(uptr stack_buffer_start, uptr stack_buffer_size); // Must be called from the thread itself.
|
||||
void InitRandomState();
|
||||
void Destroy();
|
||||
|
||||
uptr stack_top() { return stack_top_; }
|
||||
|
|
Loading…
Reference in New Issue