[PATCH] D64092: [TSan] Improve handling of stack pointer mangling in {set,long}jmp, pt.8

Julian Lettner via Phabricator via llvm-commits llvm-commits at lists.llvm.org
Tue Jul 2 11:58:49 PDT 2019


yln created this revision.
yln added a reviewer: dvyukov.
Herald added subscribers: llvm-commits, Sanitizers, jfb, kubamracek.
Herald added projects: Sanitizers, LLVM.

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.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D64092

Files:
  compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
  compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc


Index: compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc
+++ compiler-rt/lib/tsan/rtl/tsan_platform_mac.cc
@@ -238,8 +238,7 @@
 #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 @@
 #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 @@
 
 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
Index: compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
===================================================================
--- compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
+++ compiler-rt/lib/tsan/rtl/tsan_platform_linux.cc
@@ -74,6 +74,11 @@
 
 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;
@@ -286,6 +291,8 @@
     }
     // Initialize the guard pointer used in {sig}{set,long}jump.
     InitializeGuardPtr();
+    InitializeLongjmpXorKey();
+    CHECK_EQ(longjmp_xor_key, _tsan_pointer_chk_guard);
 #endif
     if (reexec)
       ReExec();
@@ -392,6 +399,25 @@
   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;


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D64092.207599.patch
Type: text/x-patch
Size: 2743 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20190702/c514ab76/attachment.bin>


More information about the llvm-commits mailing list