diff options
author | Julian Lettner <jlettner@apple.com> | 2019-07-09 16:49:43 +0000 |
---|---|---|
committer | Julian Lettner <jlettner@apple.com> | 2019-07-09 16:49:43 +0000 |
commit | 10066ac8293fa4fe31d0fb8d9cc6fbea92387e3f (patch) | |
tree | 4e29ec54e4ae4d9479be65dfca6702cc8bfa4789 | |
parent | 2c2d33f437730449a70cfc3e007356173f6c0fee (diff) | |
download | compiler-rt-10066ac8293fa4fe31d0fb8d9cc6fbea92387e3f.tar.gz |
[TSan] Improve handling of stack pointer mangling in {set,long}jmp, pt.8
Refine longjmp key management. For Linux, re-implement key retrieval in
C (instead of assembly). Removal of `InitializeGuardPtr` and a final
round of cleanups will be done in the next commit.
Reviewed By: dvyukov
Differential Revision: https://reviews.llvm.org/D64092
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@365513 91177308-0d34-0410-b5e6-96231b3b80d8
-rw-r--r-- | lib/tsan/rtl/tsan_platform_linux.cc | 50 | ||||
-rw-r--r-- | lib/tsan/rtl/tsan_platform_mac.cc | 11 |
2 files changed, 51 insertions, 10 deletions
diff --git a/lib/tsan/rtl/tsan_platform_linux.cc b/lib/tsan/rtl/tsan_platform_linux.cc index 71f6f4872..1373037ed 100644 --- a/lib/tsan/rtl/tsan_platform_linux.cc +++ b/lib/tsan/rtl/tsan_platform_linux.cc @@ -68,12 +68,17 @@ void *__libc_stack_end = 0; #endif #if SANITIZER_LINUX && defined(__aarch64__) -void InitializeGuardPtr() __attribute__((visibility("hidden"))); +__tsan::uptr InitializeGuardPtr() __attribute__((visibility("hidden"))); extern "C" __tsan::uptr _tsan_pointer_chk_guard; #endif namespace __tsan { +#if SANITIZER_LINUX && defined(__aarch64__) +static void InitializeLongjmpXorKey(); +static uptr longjmp_xor_key; +#endif + #ifdef TSAN_RUNTIME_VMA // Runtime detected VMA size. uptr vmaSize; @@ -285,7 +290,25 @@ void InitializePlatform() { reexec = true; } // Initialize the guard pointer used in {sig}{set,long}jump. - InitializeGuardPtr(); + longjmp_xor_key = InitializeGuardPtr(); + uptr old_value = longjmp_xor_key; + InitializeLongjmpXorKey(); + CHECK_EQ(longjmp_xor_key, old_value); + // If the above check fails for you, please contact me (jlettner@apple.com) + // and let me know the values of the two differing keys. Please also set a + // breakpoint on `InitializeGuardPtr` and `InitializeLongjmpXorKey` and tell + // me the stack pointer (SP) values that go into the XOR operation (where we + // derive the key): + // + // InitializeLongjmpXorKey: + // uptr sp = (uptr)__builtin_frame_address(0); + // + // InitializeGuardPtr (in tsan_rtl_aarch64.S): + // mov x0, sp + // ... + // eor x0, x0, x1 + // + // Then feel free to comment out the call to `InitializeLongjmpXorKey`. #endif if (reexec) ReExec(); @@ -353,9 +376,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) { # endif #elif defined(__aarch64__) # if SANITIZER_LINUX - // TODO(yln): fix this - // return mangled_sp ^ _tsan_pointer_chk_guard; - return mangled_sp; + return mangled_sp ^ longjmp_xor_key; # else return mangled_sp; # endif @@ -394,6 +415,25 @@ uptr ExtractLongJmpSp(uptr *env) { return UnmangleLongJmpSp(mangled_sp); } +#if SANITIZER_LINUX && defined(__aarch64__) +// GLIBC mangles the function pointers in jmp_buf (used in {set,long}*jmp +// functions) by XORing them with a random key. For AArch64 it is a global +// variable rather than a TCB one (as for x86_64/powerpc). We obtain the key by +// issuing a setjmp and XORing the SP pointer values to derive the key. +static void InitializeLongjmpXorKey() { + // 1. Call REAL(setjmp), which stores the mangled SP in env. + jump_buf env; + REAL(setjmp)(env); + + // 2. Retrieve mangled/vanilla SP. + uptr mangled_sp = ((uptr *)&env)[LONG_JMP_SP_ENV_SLOT]; + uptr sp = (uptr)__builtin_frame_address(0); + + // 3. xor SPs to obtain key. + longjmp_xor_key = mangled_sp ^ sp; +} +#endif + void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) { // Check that the thr object is in tls; const uptr thr_beg = (uptr)thr; diff --git a/lib/tsan/rtl/tsan_platform_mac.cc b/lib/tsan/rtl/tsan_platform_mac.cc index e43a9ec34..0c2d2aa93 100644 --- a/lib/tsan/rtl/tsan_platform_mac.cc +++ b/lib/tsan/rtl/tsan_platform_mac.cc @@ -238,8 +238,7 @@ void InitializePlatformEarly() { #endif } -static const uptr kPthreadSetjmpXorKeySlot = 0x7; -extern "C" uptr __tsan_darwin_setjmp_xor_key = 0; +static uptr longjmp_xor_key = 0; void InitializePlatform() { DisableCoreDumperIfNecessary(); @@ -254,8 +253,9 @@ void InitializePlatform() { #endif if (GetMacosVersion() >= MACOS_VERSION_MOJAVE) { - __tsan_darwin_setjmp_xor_key = - (uptr)pthread_getspecific(kPthreadSetjmpXorKeySlot); + // Libsystem currently uses a process-global key; this might change. + const unsigned kTLSLongjmpXorKeySlot = 0x7; + longjmp_xor_key = (uptr)pthread_getspecific(kTLSLongjmpXorKeySlot); } } @@ -268,7 +268,8 @@ void InitializePlatform() { uptr ExtractLongJmpSp(uptr *env) { uptr mangled_sp = env[LONG_JMP_SP_ENV_SLOT]; - return mangled_sp ^ __tsan_darwin_setjmp_xor_key; + uptr sp = mangled_sp ^ longjmp_xor_key; + return sp; } #if !SANITIZER_GO |