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