forked from OSchip/llvm-project
Reland "[TSan] Improve handling of stack pointer mangling in {set,long}jmp, pt.8"
Fix compilation errors related to `SANITIZER_GO` `#ifdef`s. 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 > llvm-svn: 365513 llvm-svn: 365560
This commit is contained in:
parent
90148db02a
commit
ba9eb48318
|
@ -68,12 +68,17 @@ void *__libc_stack_end = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if SANITIZER_LINUX && defined(__aarch64__)
|
#if SANITIZER_LINUX && defined(__aarch64__)
|
||||||
void InitializeGuardPtr() __attribute__((visibility("hidden")));
|
__tsan::uptr InitializeGuardPtr() __attribute__((visibility("hidden")));
|
||||||
extern "C" __tsan::uptr _tsan_pointer_chk_guard;
|
extern "C" __tsan::uptr _tsan_pointer_chk_guard;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace __tsan {
|
namespace __tsan {
|
||||||
|
|
||||||
|
#if SANITIZER_LINUX && defined(__aarch64__) && !SANITIZER_GO
|
||||||
|
static void InitializeLongjmpXorKey();
|
||||||
|
static uptr longjmp_xor_key;
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef TSAN_RUNTIME_VMA
|
#ifdef TSAN_RUNTIME_VMA
|
||||||
// Runtime detected VMA size.
|
// Runtime detected VMA size.
|
||||||
uptr vmaSize;
|
uptr vmaSize;
|
||||||
|
@ -249,7 +254,8 @@ void InitializePlatform() {
|
||||||
// Go maps shadow memory lazily and works fine with limited address space.
|
// Go maps shadow memory lazily and works fine with limited address space.
|
||||||
// Unlimited stack is not a problem as well, because the executable
|
// Unlimited stack is not a problem as well, because the executable
|
||||||
// is not compiled with -pie.
|
// is not compiled with -pie.
|
||||||
if (!SANITIZER_GO) {
|
#if !SANITIZER_GO
|
||||||
|
{
|
||||||
bool reexec = false;
|
bool reexec = false;
|
||||||
// TSan doesn't play well with unlimited stack size (as stack
|
// TSan doesn't play well with unlimited stack size (as stack
|
||||||
// overlaps with shadow memory). If we detect unlimited stack size,
|
// overlaps with shadow memory). If we detect unlimited stack size,
|
||||||
|
@ -285,16 +291,33 @@ void InitializePlatform() {
|
||||||
reexec = true;
|
reexec = true;
|
||||||
}
|
}
|
||||||
// Initialize the guard pointer used in {sig}{set,long}jump.
|
// 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
|
#endif
|
||||||
if (reexec)
|
if (reexec)
|
||||||
ReExec();
|
ReExec();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !SANITIZER_GO
|
|
||||||
CheckAndProtect();
|
CheckAndProtect();
|
||||||
InitTlsSize();
|
InitTlsSize();
|
||||||
#endif
|
#endif // !SANITIZER_GO
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !SANITIZER_GO
|
#if !SANITIZER_GO
|
||||||
|
@ -353,9 +376,7 @@ static uptr UnmangleLongJmpSp(uptr mangled_sp) {
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__aarch64__)
|
#elif defined(__aarch64__)
|
||||||
# if SANITIZER_LINUX
|
# if SANITIZER_LINUX
|
||||||
// TODO(yln): fix this
|
return mangled_sp ^ longjmp_xor_key;
|
||||||
// return mangled_sp ^ _tsan_pointer_chk_guard;
|
|
||||||
return mangled_sp;
|
|
||||||
# else
|
# else
|
||||||
return mangled_sp;
|
return mangled_sp;
|
||||||
# endif
|
# endif
|
||||||
|
@ -394,6 +415,27 @@ uptr ExtractLongJmpSp(uptr *env) {
|
||||||
return UnmangleLongJmpSp(mangled_sp);
|
return UnmangleLongJmpSp(mangled_sp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if SANITIZER_LINUX && defined(__aarch64__)
|
||||||
|
#include "interception/interception.h"
|
||||||
|
DECLARE_REAL(int, setjmp, void* env);
|
||||||
|
// 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.
|
||||||
|
jmp_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) {
|
void ImitateTlsWrite(ThreadState *thr, uptr tls_addr, uptr tls_size) {
|
||||||
// Check that the thr object is in tls;
|
// Check that the thr object is in tls;
|
||||||
const uptr thr_beg = (uptr)thr;
|
const uptr thr_beg = (uptr)thr;
|
||||||
|
@ -421,7 +463,7 @@ int call_pthread_cancel_with_cleanup(int(*fn)(void *c, void *m,
|
||||||
pthread_cleanup_pop(0);
|
pthread_cleanup_pop(0);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
#endif
|
#endif // !SANITIZER_GO
|
||||||
|
|
||||||
#if !SANITIZER_GO
|
#if !SANITIZER_GO
|
||||||
void ReplaceSystemMalloc() { }
|
void ReplaceSystemMalloc() { }
|
||||||
|
|
Loading…
Reference in New Issue