summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJulian Lettner <jlettner@apple.com>2019-07-09 16:49:43 +0000
committerJulian Lettner <jlettner@apple.com>2019-07-09 16:49:43 +0000
commit10066ac8293fa4fe31d0fb8d9cc6fbea92387e3f (patch)
tree4e29ec54e4ae4d9479be65dfca6702cc8bfa4789
parent2c2d33f437730449a70cfc3e007356173f6c0fee (diff)
downloadcompiler-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.cc50
-rw-r--r--lib/tsan/rtl/tsan_platform_mac.cc11
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