From 888951aaca583bcce85b42ea6166416db8f96fe0 Mon Sep 17 00:00:00 2001 From: Dan Liew Date: Fri, 26 Jun 2020 16:14:22 -0700 Subject: [PATCH] Disable interception of sigaltstack on i386 macOS. Summary: 28c91219c7e introduced an interceptor for `sigaltstack`. It turns out this broke `setjmp` on i386 macOS. This is because the implementation of `setjmp` on i386 macOS is written in assembly and makes the assumption that the call to `sigaltstack` does not clobber any registers. Presumably that assumption was made because it's a system call. In particular `setjmp` assumes that before and after the call that `%ecx` will contain a pointer the `jmp_buf`. The current interceptor breaks this assumption because it's written in C++ and `%ecx` is not a callee-saved register. This could be fixed by writing a trampoline interceptor to the existing interceptor in assembly that ensures all the registers are preserved. However, this is a lot of work for very little gain. Instead this patch just disables the interceptor on i386 macOS. For other Darwin architectures it currently appears to be safe to intercept `sigaltstack` using the current implementation because: * `setjmp` for x86_64 saves the pointer `jmp_buf` to the stack before calling `sigaltstack`. * `setjmp` for armv7/arm64/arm64_32/arm64e appears to not call `sigaltstack` at all. This patch should unbreak (once they are re-enabled) the following tests: ``` AddressSanitizer-Unit :: ./Asan-i386-calls-Test/AddressSanitizer.LongJmpTest AddressSanitizer-Unit :: ./Asan-i386-calls-Test/AddressSanitizer.SigLongJmpTest AddressSanitizer-Unit :: ./Asan-i386-inline-Test/AddressSanitizer.LongJmpTest AddressSanitizer-Unit :: ./Asan-i386-inline-Test/AddressSanitizer.SigLongJmpTest AddressSanitizer-i386-darwin :: TestCases/longjmp.cpp ``` This patch introduces a `SANITIZER_I386` macro for convenience. rdar://problem/62141412 Reviewers: kubamracek, yln, eugenis Subscribers: kristof.beyls, #sanitizers, llvm-commits Tags: #sanitizers Differential Revision: https://reviews.llvm.org/D82691 --- compiler-rt/lib/sanitizer_common/sanitizer_platform.h | 6 ++++++ .../lib/sanitizer_common/sanitizer_platform_interceptors.h | 5 ++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h index c68bfa258755..f0b1e04d1dd6 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform.h @@ -132,6 +132,12 @@ # define SANITIZER_X32 0 #endif +#if defined(__i386__) || defined(_M_IX86) +# define SANITIZER_I386 1 +#else +# define SANITIZER_I386 0 +#endif + #if defined(__mips__) # define SANITIZER_MIPS 1 # if defined(__mips64) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h index fb0dbfb2e9ae..a5fcbadb2597 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h +++ b/compiler-rt/lib/sanitizer_common/sanitizer_platform_interceptors.h @@ -597,7 +597,10 @@ #define SANITIZER_INTERCEPT_QSORT \ (SI_POSIX && !SI_IOSSIM && !SI_WATCHOS && !SI_TVOS && !SI_ANDROID) #define SANITIZER_INTERCEPT_QSORT_R (SI_LINUX && !SI_ANDROID) -#define SANITIZER_INTERCEPT_SIGALTSTACK SI_POSIX +// sigaltstack on i386 macOS cannot be intercepted due to setjmp() +// calling it and assuming that it does not clobber registers. +#define SANITIZER_INTERCEPT_SIGALTSTACK \ + (SI_POSIX && !(SANITIZER_MAC && SANITIZER_I386)) #define SANITIZER_INTERCEPT_UNAME (SI_POSIX && !SI_FREEBSD) #define SANITIZER_INTERCEPT___XUNAME SI_FREEBSD