Skip to content

Commit

Permalink
[sanitizers] Fix internal__exit on Solaris
Browse files Browse the repository at this point in the history
`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
  • Loading branch information
rorth committed Sep 30, 2020
1 parent f33f8a2 commit dc261d2
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 13 deletions.
20 changes: 11 additions & 9 deletions compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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))
Expand Down
4 changes: 0 additions & 4 deletions compiler-rt/lib/sanitizer_common/sanitizer_solaris.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit dc261d2

Please sign in to comment.