1a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//===-- asan_linux.cc -----------------------------------------------------===//
2a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//
3a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//                     The LLVM Compiler Infrastructure
4a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//
5a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// This file is distributed under the University of Illinois Open Source
6a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// License. See LICENSE.TXT for details.
7a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//
8a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//===----------------------------------------------------------------------===//
9a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//
10a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker.
11a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//
12a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany// Posix-specific details.
13a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany//===----------------------------------------------------------------------===//
14a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#if defined(__linux__) || defined(__APPLE__)
15a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
16a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_internal.h"
17a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_interceptors.h"
18c99f70044d64482adbc1053f04b32bdbf0d4c057Evgeniy Stepanov#include "asan_mapping.h"
197354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov#include "asan_report.h"
20a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_stack.h"
21a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include "asan_thread_registry.h"
222221f553886c37401b5d84923634ebf04bc482f1Alexey Samsonov#include "sanitizer_common/sanitizer_libc.h"
236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common/sanitizer_procmaps.h"
24a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
25cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany#include <pthread.h>
26a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include <signal.h>
27b823e3c5f7891dbbde1eb288237f5f3d5ed64d85Alexey Samsonov#include <stdlib.h>
28a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include <sys/time.h>
29a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#include <sys/resource.h>
300ecf5eb729dd81a43f8585cb438d3cb2a35899edKostya Serebryany#include <unistd.h>
31a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
323f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryanystatic const uptr kAltStackSize = SIGSTKSZ * 4;  // SIGSTKSZ is not enough.
33f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko
34a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanynamespace __asan {
35a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
36a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanystatic void MaybeInstallSigaction(int signum,
37a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany                                  void (*handler)(int, siginfo_t *, void *)) {
38a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  if (!AsanInterceptsSignal(signum))
39a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany    return;
40a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  struct sigaction sigact;
4109672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  REAL(memset)(&sigact, 0, sizeof(sigact));
42a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  sigact.sa_sigaction = handler;
43a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  sigact.sa_flags = SA_SIGINFO;
44cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
4509672caefb5694f1981a1712fdefa44840a95e67Alexey Samsonov  CHECK(0 == REAL(sigaction)(signum, &sigact, 0));
46cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity >= 1) {
47a87bdaa1eab379ae4d9a24456f41f8ae36ba33f6Alexander Potapenko    Report("Installed the sigaction for signal %d\n", signum);
48a87bdaa1eab379ae4d9a24456f41f8ae36ba33f6Alexander Potapenko  }
49a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany}
50a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
51a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanystatic void     ASAN_OnSIGSEGV(int, siginfo_t *siginfo, void *context) {
523f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr addr = (uptr)siginfo->si_addr;
53a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  // Write the first message using the bullet-proof write.
5447657ce6cbac2fa93d0fd765c5d2872443b50e87Alexey Samsonov  if (13 != internal_write(2, "ASAN:SIGSEGV\n", 13)) Die();
553f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  uptr pc, sp, bp;
56a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  GetPcSpBp(context, &pc, &sp, &bp);
577354509ec8a37262c5ea0c54f99afee8a5116ce5Alexey Samsonov  ReportSIGSEGV(pc, sp, bp, addr);
58a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany}
59a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
60f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenkovoid SetAlternateSignalStack() {
61f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  stack_t altstack, oldstack;
623f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  CHECK(0 == sigaltstack(0, &oldstack));
63f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // If the alternate stack is already in place, do nothing.
64f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  if ((oldstack.ss_flags & SS_DISABLE) == 0) return;
65f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // TODO(glider): the mapped stack should have the MAP_STACK flag in the
66f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // future. It is not required by man 2 sigaltstack now (they're using
67f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // malloc()).
68a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov  void* base = MmapOrDie(kAltStackSize, __FUNCTION__);
69f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  altstack.ss_sp = base;
70f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  altstack.ss_flags = 0;
71f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  altstack.ss_size = kAltStackSize;
723f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  CHECK(0 == sigaltstack(&altstack, 0));
73cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->verbosity > 0) {
74f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko    Report("Alternative stack for T%d set: [%p,%p)\n",
75e0cff0bc20ae51790c8edfbceb817e18ebf5355eKostya Serebryany           asanThreadRegistry().GetCurrentTidOrInvalid(),
76f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko           altstack.ss_sp, (char*)altstack.ss_sp + altstack.ss_size);
77f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  }
78f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko}
79f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko
80f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenkovoid UnsetAlternateSignalStack() {
81f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  stack_t altstack, oldstack;
823f4c3875c42078e22c7e5356c5746fd18756d958Kostya Serebryany  altstack.ss_sp = 0;
83f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  altstack.ss_flags = SS_DISABLE;
84f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  altstack.ss_size = 0;
85f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  CHECK(0 == sigaltstack(&altstack, &oldstack));
86a25b3463477d2a825df4f656001fc07c594b35acAlexey Samsonov  UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
87f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko}
88f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko
89a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryanyvoid InstallSignalHandlers() {
90f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // Set the alternate signal stack for the main thread.
91f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // This will cause SetAlternateSignalStack to be called twice, but the stack
92f03d8afc8b8dd072c4e2884a7475ee28ac5f3f41Alexander Potapenko  // will be actually set only once.
93cb8c4dce691097718d5af41b36899b72ef4b1d84Alexey Samsonov  if (flags()->use_sigaltstack) SetAlternateSignalStack();
94a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  MaybeInstallSigaction(SIGSEGV, ASAN_OnSIGSEGV);
95a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany  MaybeInstallSigaction(SIGBUS, ASAN_OnSIGSEGV);
96a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany}
97a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
98cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany// ---------------------- TSD ---------------- {{{1
99cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany
100cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanystatic pthread_key_t tsd_key;
101cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanystatic bool tsd_key_inited = false;
102f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryanyvoid AsanTSDInit(void (*destructor)(void *tsd)) {
103cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany  CHECK(!tsd_key_inited);
104cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany  tsd_key_inited = true;
105f58f998066db0231e521169d2f50af439ceecb49Kostya Serebryany  CHECK(0 == pthread_key_create(&tsd_key, destructor));
106cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany}
107cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany
108cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanyvoid *AsanTSDGet() {
109cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany  CHECK(tsd_key_inited);
110cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany  return pthread_getspecific(tsd_key);
111cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany}
112cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany
113cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryanyvoid AsanTSDSet(void *tsd) {
114cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany  CHECK(tsd_key_inited);
115cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany  pthread_setspecific(tsd_key, tsd);
116cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany}
117cc4e6862c6a8f8f3ead96bd32b815184a36fadedKostya Serebryany
118a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany}  // namespace __asan
119a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany
120a7e760a53bc43b8e09bfdf5cd6f215267ba99729Kostya Serebryany#endif  // __linux__ || __APPLE_
121