1//===-- sanitizer_posix_libcdep.cc ----------------------------------------===//
2//
3// This file is distributed under the University of Illinois Open Source
4// License. See LICENSE.TXT for details.
5//
6//===----------------------------------------------------------------------===//
7//
8// This file is shared between AddressSanitizer and ThreadSanitizer
9// run-time libraries and implements libc-dependent POSIX-specific functions
10// from sanitizer_libc.h.
11//===----------------------------------------------------------------------===//
12
13#include "sanitizer_platform.h"
14
15#if SANITIZER_POSIX
16#include "sanitizer_common.h"
17#include "sanitizer_flags.h"
18#include "sanitizer_platform_limits_posix.h"
19#include "sanitizer_stacktrace.h"
20
21#include <errno.h>
22#include <pthread.h>
23#include <signal.h>
24#include <stdlib.h>
25#include <sys/mman.h>
26#include <sys/resource.h>
27#include <sys/time.h>
28#include <sys/types.h>
29#include <unistd.h>
30
31namespace __sanitizer {
32
33u32 GetUid() {
34  return getuid();
35}
36
37uptr GetThreadSelf() {
38  return (uptr)pthread_self();
39}
40
41void FlushUnneededShadowMemory(uptr addr, uptr size) {
42  madvise((void*)addr, size, MADV_DONTNEED);
43}
44
45static rlim_t getlim(int res) {
46  rlimit rlim;
47  CHECK_EQ(0, getrlimit(res, &rlim));
48  return rlim.rlim_cur;
49}
50
51static void setlim(int res, rlim_t lim) {
52  // The following magic is to prevent clang from replacing it with memset.
53  volatile struct rlimit rlim;
54  rlim.rlim_cur = lim;
55  rlim.rlim_max = lim;
56  if (setrlimit(res, (struct rlimit*)&rlim)) {
57    Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
58    Die();
59  }
60}
61
62void DisableCoreDumperIfNecessary() {
63  if (common_flags()->disable_coredump) {
64    setlim(RLIMIT_CORE, 0);
65  }
66}
67
68bool StackSizeIsUnlimited() {
69  rlim_t stack_size = getlim(RLIMIT_STACK);
70  return (stack_size == RLIM_INFINITY);
71}
72
73void SetStackSizeLimitInBytes(uptr limit) {
74  setlim(RLIMIT_STACK, (rlim_t)limit);
75  CHECK(!StackSizeIsUnlimited());
76}
77
78bool AddressSpaceIsUnlimited() {
79  rlim_t as_size = getlim(RLIMIT_AS);
80  return (as_size == RLIM_INFINITY);
81}
82
83void SetAddressSpaceUnlimited() {
84  setlim(RLIMIT_AS, RLIM_INFINITY);
85  CHECK(AddressSpaceIsUnlimited());
86}
87
88void SleepForSeconds(int seconds) {
89  sleep(seconds);
90}
91
92void SleepForMillis(int millis) {
93  usleep(millis * 1000);
94}
95
96void Abort() {
97  abort();
98}
99
100int Atexit(void (*function)(void)) {
101#ifndef SANITIZER_GO
102  return atexit(function);
103#else
104  return 0;
105#endif
106}
107
108int internal_isatty(fd_t fd) {
109  return isatty(fd);
110}
111
112#ifndef SANITIZER_GO
113// TODO(glider): different tools may require different altstack size.
114static const uptr kAltStackSize = SIGSTKSZ * 4;  // SIGSTKSZ is not enough.
115
116void SetAlternateSignalStack() {
117  stack_t altstack, oldstack;
118  CHECK_EQ(0, sigaltstack(0, &oldstack));
119  // If the alternate stack is already in place, do nothing.
120  // Android always sets an alternate stack, but it's too small for us.
121  if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
122  // TODO(glider): the mapped stack should have the MAP_STACK flag in the
123  // future. It is not required by man 2 sigaltstack now (they're using
124  // malloc()).
125  void* base = MmapOrDie(kAltStackSize, __func__);
126  altstack.ss_sp = (char*) base;
127  altstack.ss_flags = 0;
128  altstack.ss_size = kAltStackSize;
129  CHECK_EQ(0, sigaltstack(&altstack, 0));
130}
131
132void UnsetAlternateSignalStack() {
133  stack_t altstack, oldstack;
134  altstack.ss_sp = 0;
135  altstack.ss_flags = SS_DISABLE;
136  altstack.ss_size = kAltStackSize;  // Some sane value required on Darwin.
137  CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
138  UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
139}
140
141typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
142static void MaybeInstallSigaction(int signum,
143                                  SignalHandlerType handler) {
144  if (!IsDeadlySignal(signum))
145    return;
146  struct sigaction sigact;
147  internal_memset(&sigact, 0, sizeof(sigact));
148  sigact.sa_sigaction = (sa_sigaction_t)handler;
149  // Do not block the signal from being received in that signal's handler.
150  // Clients are responsible for handling this correctly.
151  sigact.sa_flags = SA_SIGINFO | SA_NODEFER;
152  if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
153  CHECK_EQ(0, internal_sigaction(signum, &sigact, 0));
154  VReport(1, "Installed the sigaction for signal %d\n", signum);
155}
156
157void InstallDeadlySignalHandlers(SignalHandlerType handler) {
158  // Set the alternate signal stack for the main thread.
159  // This will cause SetAlternateSignalStack to be called twice, but the stack
160  // will be actually set only once.
161  if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
162  MaybeInstallSigaction(SIGSEGV, handler);
163  MaybeInstallSigaction(SIGBUS, handler);
164}
165#endif  // SANITIZER_GO
166
167bool IsAccessibleMemoryRange(uptr beg, uptr size) {
168  uptr page_size = GetPageSizeCached();
169  // Checking too large memory ranges is slow.
170  CHECK_LT(size, page_size * 10);
171  int sock_pair[2];
172  if (pipe(sock_pair))
173    return false;
174  uptr bytes_written =
175      internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
176  int write_errno;
177  bool result;
178  if (internal_iserror(bytes_written, &write_errno)) {
179    CHECK_EQ(EFAULT, write_errno);
180    result = false;
181  } else {
182    result = (bytes_written == size);
183  }
184  internal_close(sock_pair[0]);
185  internal_close(sock_pair[1]);
186  return result;
187}
188
189}  // namespace __sanitizer
190
191#endif  // SANITIZER_POSIX
192