From dc261d23d07cccfa7b10a3d1a43903138aee94dc Mon Sep 17 00:00:00 2001 From: Rainer Orth Date: Wed, 30 Sep 2020 16:30:18 +0200 Subject: [PATCH] [sanitizers] Fix internal__exit on Solaris `TestCases/log-path_test.cpp` currently `FAIL`s on Solaris: $ env ASAN_OPTIONS=log_path=`for((i=0;i<10000;i++)); do echo -n $i; done` ./log-path_test.cpp.tmp ==5031==ERROR: Path is too long: 01234567... Segmentation Fault (core dumped) The `SEGV` happens here: Thread 2 received signal SIGSEGV, Segmentation fault. [Switching to Thread 1 (LWP 1)] 0x00000000 in ?? () (gdb) where #0 0x00000000 in ?? () #1 0x080a1e63 in __interceptor__exit (status=1) at /vol/gcc/src/llvm/llvm/local/projects/compiler-rt/lib/asan/../sanitizer_common/sanitizer_common_interceptors.inc:3808 #2 0x08135ea8 in __sanitizer::internal__exit (exitcode=1) at /vol/gcc/src/llvm/llvm/local/projects/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cc:139 when `__interceptor__exit` tries to call `__interception::real__exit` which is `NULL` at this point because the interceptors haven't been initialized yet. Ultimately, the problem lies elsewhere, however: `internal__exit` in `sanitizer_solaris.cpp` calls `_exit` itself since there doesn't exit a non-intercepted version in `libc`. Using the `syscall` interface instead isn't usually an option on Solaris because that interface isn't stable. However, in the case of `SYS_exit` it can be used nonetheless: `SYS_exit` has remained unchanged since at least Solaris 2.5.1 in 1996, and this is what this patch does. Tested on `amd64-pc-solaris2.11`. Differential Revision: https://reviews.llvm.org/D88404 --- .../lib/sanitizer_common/sanitizer_linux.cpp | 20 ++++++++++--------- .../sanitizer_common/sanitizer_solaris.cpp | 4 ---- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp index 0b53210b807732..0e48062828a4b3 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp @@ -426,15 +426,6 @@ uptr internal_sched_yield() { return internal_syscall(SYSCALL(sched_yield)); } -void internal__exit(int exitcode) { -#if SANITIZER_FREEBSD || SANITIZER_OPENBSD - internal_syscall(SYSCALL(exit), exitcode); -#else - internal_syscall(SYSCALL(exit_group), exitcode); -#endif - Die(); // Unreachable. -} - unsigned int internal_sleep(unsigned int seconds) { struct timespec ts; ts.tv_sec = seconds; @@ -451,6 +442,17 @@ uptr internal_execve(const char *filename, char *const argv[], } #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD +#if !SANITIZER_NETBSD +void internal__exit(int exitcode) { +#if SANITIZER_FREEBSD || SANITIZER_OPENBSD || SANITIZER_SOLARIS + internal_syscall(SYSCALL(exit), exitcode); +#else + internal_syscall(SYSCALL(exit_group), exitcode); +#endif + Die(); // Unreachable. +} +#endif // !SANITIZER_NETBSD + // ----------------- sanitizer_common.h bool FileExists(const char *filename) { if (ShouldMockFailureToOpen(filename)) diff --git a/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp b/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp index 7f9a3e936da729..8789dcd10a9543 100644 --- a/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp +++ b/compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp @@ -160,10 +160,6 @@ DECLARE__REAL_AND_INTERNAL(uptr, sched_yield, void) { return sched_yield(); } -DECLARE__REAL_AND_INTERNAL(void, _exit, int exitcode) { - _exit(exitcode); -} - DECLARE__REAL_AND_INTERNAL(uptr, execve, const char *filename, char *const argv[], char *const envp[]) { return _REAL(execve)(filename, argv, envp);