Skip to content

Commit 886b7cc

Browse files
committed
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
1 parent 6f94a03 commit 886b7cc

File tree

9 files changed

+72
-23
lines changed

9 files changed

+72
-23
lines changed

compiler-rt/include/sanitizer/hwasan_interface.h

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,15 @@
1818
#ifdef __cplusplus
1919
extern "C" {
2020
#endif
21-
// Initialize shadow but not the rest of the runtime.
21+
// Libc hook for program startup in statically linked executables.
22+
// Initializes enough of the runtime to run instrumented code. This function
23+
// should only be called in statically linked executables because it modifies
24+
// the GOT, which won't work in regular binaries because RELRO will already
25+
// have been applied by the time the function is called. This also means that
26+
// the function should be called before libc applies RELRO.
2227
// Does not call libc unless there is an error.
23-
// Can be called multiple times, or not at all (in which case shadow will
24-
// be initialized in compiler-inserted __hwasan_init() call).
25-
void __hwasan_shadow_init(void);
28+
// Can be called multiple times.
29+
void __hwasan_init_static(void);
2630

2731
// This function may be optionally provided by user and should return
2832
// a string containing HWASan runtime options. See asan_flags.h for details.

compiler-rt/lib/hwasan/hwasan.cc

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313

1414
#include "hwasan.h"
1515
#include "hwasan_checks.h"
16+
#include "hwasan_dynamic_shadow.h"
1617
#include "hwasan_poisoning.h"
1718
#include "hwasan_report.h"
1819
#include "hwasan_thread.h"
@@ -57,7 +58,7 @@ Flags *flags() {
5758
}
5859

5960
int hwasan_inited = 0;
60-
int hwasan_shadow_inited = 0;
61+
int hwasan_instrumentation_inited = 0;
6162
bool hwasan_init_is_running;
6263

6364
int hwasan_report_count = 0;
@@ -246,28 +247,39 @@ const char *GetStackFrameDescr(uptr pc) {
246247
return nullptr;
247248
}
248249

249-
} // namespace __hwasan
250-
251-
// Interface.
252-
253-
using namespace __hwasan;
254-
255-
uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol.
250+
// Prepare to run instrumented code on the main thread.
251+
void InitInstrumentation() {
252+
if (hwasan_instrumentation_inited) return;
256253

257-
void __hwasan_shadow_init() {
258-
if (hwasan_shadow_inited) return;
259254
if (!InitShadow()) {
260255
Printf("FATAL: HWAddressSanitizer cannot mmap the shadow memory.\n");
261256
DumpProcessMap();
262257
Die();
263258
}
264-
hwasan_shadow_inited = 1;
259+
260+
InitThreads();
261+
hwasanThreadList().CreateCurrentThread();
262+
263+
hwasan_instrumentation_inited = 1;
265264
}
266265

266+
} // namespace __hwasan
267+
268+
// Interface.
269+
270+
using namespace __hwasan;
271+
272+
uptr __hwasan_shadow_memory_dynamic_address; // Global interface symbol.
273+
267274
void __hwasan_init_frames(uptr beg, uptr end) {
268275
InitFrameDescriptors(beg, end);
269276
}
270277

278+
void __hwasan_init_static() {
279+
InitShadowGOT();
280+
InitInstrumentation();
281+
}
282+
271283
void __hwasan_init() {
272284
CHECK(!hwasan_init_is_running);
273285
if (hwasan_inited) return;
@@ -288,10 +300,11 @@ void __hwasan_init() {
288300

289301
DisableCoreDumperIfNecessary();
290302

291-
__hwasan_shadow_init();
303+
InitInstrumentation();
292304

293-
InitThreads();
294-
hwasanThreadList().CreateCurrentThread();
305+
// Needs to be called here because flags()->random_tags might not have been
306+
// initialized when InitInstrumentation() was called.
307+
GetCurrentThread()->InitRandomState();
295308

296309
MadviseShadow();
297310

compiler-rt/lib/hwasan/hwasan.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ extern int hwasan_report_count;
7070
bool ProtectRange(uptr beg, uptr end);
7171
bool InitShadow();
7272
void InitThreads();
73+
void InitInstrumentation();
7374
void MadviseShadow();
7475
char *GetProcSelfMaps();
7576
void InitializeInterceptors();

compiler-rt/lib/hwasan/hwasan_dynamic_shadow.cc

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@
1818
#include "sanitizer_common/sanitizer_common.h"
1919
#include "sanitizer_common/sanitizer_posix.h"
2020

21+
#include <elf.h>
22+
#include <link.h>
23+
2124
// The code in this file needs to run in an unrelocated binary. It should not
2225
// access any external symbol, including its own non-hidden globals.
2326

@@ -118,10 +121,28 @@ decltype(__hwasan_shadow)* __hwasan_premap_shadow() {
118121
INTERFACE_ATTRIBUTE __attribute__((ifunc("__hwasan_premap_shadow")))
119122
void __hwasan_shadow();
120123

124+
extern __attribute((visibility("hidden"))) ElfW(Rela) __rela_iplt_start[],
125+
__rela_iplt_end[];
126+
121127
} // extern "C"
122128

123129
namespace __hwasan {
124130

131+
void InitShadowGOT() {
132+
// Call the ifunc resolver for __hwasan_shadow and fill in its GOT entry. This
133+
// needs to be done before other ifunc resolvers (which are handled by libc)
134+
// because a resolver might read __hwasan_shadow.
135+
typedef ElfW(Addr) (*ifunc_resolver_t)(void);
136+
for (ElfW(Rela) *r = __rela_iplt_start; r != __rela_iplt_end; ++r) {
137+
ElfW(Addr)* offset = reinterpret_cast<ElfW(Addr)*>(r->r_offset);
138+
ElfW(Addr) resolver = r->r_addend;
139+
if (resolver == reinterpret_cast<ElfW(Addr)>(&__hwasan_premap_shadow)) {
140+
*offset = reinterpret_cast<ifunc_resolver_t>(resolver)();
141+
break;
142+
}
143+
}
144+
}
145+
125146
uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
126147
if (IsPremapShadowAvailable())
127148
return FindPremappedShadowStart(shadow_size_bytes);
@@ -132,10 +153,12 @@ uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
132153
#else
133154
namespace __hwasan {
134155

156+
void InitShadowGOT() {}
157+
135158
uptr FindDynamicShadowStart(uptr shadow_size_bytes) {
136159
return MapDynamicShadow(shadow_size_bytes);
137160
}
138161

139162
} // namespace __hwasan
140-
#
163+
141164
#endif // SANITIZER_ANDROID

compiler-rt/lib/hwasan/hwasan_dynamic_shadow.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
namespace __hwasan {
2121

2222
uptr FindDynamicShadowStart(uptr shadow_size_bytes);
23+
void InitShadowGOT();
2324

2425
} // namespace __hwasan
2526

compiler-rt/lib/hwasan/hwasan_interface_internal.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
extern "C" {
2121

2222
SANITIZER_INTERFACE_ATTRIBUTE
23-
void __hwasan_shadow_init();
23+
void __hwasan_init_static();
2424

2525
SANITIZER_INTERFACE_ATTRIBUTE
2626
void __hwasan_init();

compiler-rt/lib/hwasan/hwasan_linux.cc

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ void InstallAtExitHandler() {
236236
// ---------------------- TSD ---------------- {{{1
237237

238238
extern "C" void __hwasan_thread_enter() {
239-
hwasanThreadList().CreateCurrentThread();
239+
hwasanThreadList().CreateCurrentThread()->InitRandomState();
240240
}
241241

242242
extern "C" void __hwasan_thread_exit() {
@@ -289,14 +289,17 @@ uptr *GetCurrentThreadLongPtr() {
289289
#if SANITIZER_ANDROID
290290
void AndroidTestTlsSlot() {
291291
uptr kMagicValue = 0x010203040A0B0C0D;
292-
*(uptr *)get_android_tls_ptr() = kMagicValue;
292+
uptr *tls_ptr = GetCurrentThreadLongPtr();
293+
uptr old_value = *tls_ptr;
294+
*tls_ptr = kMagicValue;
293295
dlerror();
294296
if (*(uptr *)get_android_tls_ptr() != kMagicValue) {
295297
Printf(
296298
"ERROR: Incompatible version of Android: TLS_SLOT_SANITIZER(6) is used "
297299
"for dlerror().\n");
298300
Die();
299301
}
302+
*tls_ptr = old_value;
300303
}
301304
#else
302305
void AndroidTestTlsSlot() {}

compiler-rt/lib/hwasan/hwasan_thread.cc

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,13 @@ static u32 RandomSeed() {
2525
return seed;
2626
}
2727

28+
void Thread::InitRandomState() {
29+
random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
30+
}
31+
2832
void Thread::Init(uptr stack_buffer_start, uptr stack_buffer_size) {
2933
static u64 unique_id;
3034
unique_id_ = unique_id++;
31-
random_state_ = flags()->random_tags ? RandomSeed() : unique_id_;
3235
if (auto sz = flags()->heap_history_size)
3336
heap_allocations_ = HeapAllocationsRingBuffer::New(sz);
3437

compiler-rt/lib/hwasan/hwasan_thread.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ typedef __sanitizer::CompactRingBuffer<uptr> StackAllocationsRingBuffer;
2424
class Thread {
2525
public:
2626
void Init(uptr stack_buffer_start, uptr stack_buffer_size); // Must be called from the thread itself.
27+
void InitRandomState();
2728
void Destroy();
2829

2930
uptr stack_top() { return stack_top_; }

0 commit comments

Comments
 (0)