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:
Peter Collingbourne 2019-01-31 23:37:12 +00:00
parent 6f94a033a7
commit 886b7cc107
9 changed files with 72 additions and 23 deletions

View File

@ -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.

View File

@ -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();

View File

@ -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();

View File

@ -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

View File

@ -20,6 +20,7 @@
namespace __hwasan {
uptr FindDynamicShadowStart(uptr shadow_size_bytes);
void InitShadowGOT();
} // namespace __hwasan

View File

@ -20,7 +20,7 @@
extern "C" {
SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_shadow_init();
void __hwasan_init_static();
SANITIZER_INTERFACE_ATTRIBUTE
void __hwasan_init();

View File

@ -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() {}

View File

@ -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);

View File

@ -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_; }