1 //===-- sanitizer_posix_libcdep.cc ----------------------------------------===//
3 // This file is distributed under the University of Illinois Open Source
4 // License. See LICENSE.TXT for details.
6 //===----------------------------------------------------------------------===//
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 //===----------------------------------------------------------------------===//
13 #include "sanitizer_platform.h"
17 #include "sanitizer_common.h"
18 #include "sanitizer_flags.h"
19 #include "sanitizer_platform_limits_posix.h"
20 #include "sanitizer_posix.h"
21 #include "sanitizer_procmaps.h"
22 #include "sanitizer_stacktrace.h"
23 #include "sanitizer_symbolizer.h"
31 #include <sys/resource.h>
34 #include <sys/types.h>
39 // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
40 // that, it was never implemented. So just define it to zero.
42 #define MAP_NORESERVE 0
45 typedef void (*sa_sigaction_t
)(int, siginfo_t
*, void *);
47 namespace __sanitizer
{
53 uptr
GetThreadSelf() {
54 return (uptr
)pthread_self();
57 void ReleaseMemoryToOS(uptr addr
, uptr size
) {
58 madvise((void*)addr
, size
, MADV_DONTNEED
);
61 void NoHugePagesInRegion(uptr addr
, uptr size
) {
62 #ifdef MADV_NOHUGEPAGE // May not be defined on old systems.
63 madvise((void *)addr
, size
, MADV_NOHUGEPAGE
);
64 #endif // MADV_NOHUGEPAGE
67 void DontDumpShadowMemory(uptr addr
, uptr length
) {
69 madvise((void *)addr
, length
, MADV_DONTDUMP
);
73 static rlim_t
getlim(int res
) {
75 CHECK_EQ(0, getrlimit(res
, &rlim
));
79 static void setlim(int res
, rlim_t lim
) {
80 // The following magic is to prevent clang from replacing it with memset.
81 volatile struct rlimit rlim
;
84 if (setrlimit(res
, const_cast<struct rlimit
*>(&rlim
))) {
85 Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName
, errno
);
90 void DisableCoreDumperIfNecessary() {
91 if (common_flags()->disable_coredump
) {
92 setlim(RLIMIT_CORE
, 0);
96 bool StackSizeIsUnlimited() {
97 rlim_t stack_size
= getlim(RLIMIT_STACK
);
98 return (stack_size
== RLIM_INFINITY
);
101 uptr
GetStackSizeLimitInBytes() {
102 return (uptr
)getlim(RLIMIT_STACK
);
105 void SetStackSizeLimitInBytes(uptr limit
) {
106 setlim(RLIMIT_STACK
, (rlim_t
)limit
);
107 CHECK(!StackSizeIsUnlimited());
110 bool AddressSpaceIsUnlimited() {
111 rlim_t as_size
= getlim(RLIMIT_AS
);
112 return (as_size
== RLIM_INFINITY
);
115 void SetAddressSpaceUnlimited() {
116 setlim(RLIMIT_AS
, RLIM_INFINITY
);
117 CHECK(AddressSpaceIsUnlimited());
120 void SleepForSeconds(int seconds
) {
124 void SleepForMillis(int millis
) {
125 usleep(millis
* 1000);
130 // If we are handling SIGABRT, unhandle it first.
131 if (IsHandledDeadlySignal(SIGABRT
)) {
132 struct sigaction sigact
;
133 internal_memset(&sigact
, 0, sizeof(sigact
));
134 sigact
.sa_sigaction
= (sa_sigaction_t
)SIG_DFL
;
135 internal_sigaction(SIGABRT
, &sigact
, nullptr);
142 int Atexit(void (*function
)(void)) {
144 return atexit(function
);
150 bool SupportsColoredOutput(fd_t fd
) {
151 return isatty(fd
) != 0;
155 // TODO(glider): different tools may require different altstack size.
156 static const uptr kAltStackSize
= SIGSTKSZ
* 4; // SIGSTKSZ is not enough.
158 void SetAlternateSignalStack() {
159 stack_t altstack
, oldstack
;
160 CHECK_EQ(0, sigaltstack(nullptr, &oldstack
));
161 // If the alternate stack is already in place, do nothing.
162 // Android always sets an alternate stack, but it's too small for us.
163 if (!SANITIZER_ANDROID
&& !(oldstack
.ss_flags
& SS_DISABLE
)) return;
164 // TODO(glider): the mapped stack should have the MAP_STACK flag in the
165 // future. It is not required by man 2 sigaltstack now (they're using
167 void* base
= MmapOrDie(kAltStackSize
, __func__
);
168 altstack
.ss_sp
= (char*) base
;
169 altstack
.ss_flags
= 0;
170 altstack
.ss_size
= kAltStackSize
;
171 CHECK_EQ(0, sigaltstack(&altstack
, nullptr));
174 void UnsetAlternateSignalStack() {
175 stack_t altstack
, oldstack
;
176 altstack
.ss_sp
= nullptr;
177 altstack
.ss_flags
= SS_DISABLE
;
178 altstack
.ss_size
= kAltStackSize
; // Some sane value required on Darwin.
179 CHECK_EQ(0, sigaltstack(&altstack
, &oldstack
));
180 UnmapOrDie(oldstack
.ss_sp
, oldstack
.ss_size
);
183 static void MaybeInstallSigaction(int signum
,
184 SignalHandlerType handler
) {
185 if (!IsHandledDeadlySignal(signum
))
187 struct sigaction sigact
;
188 internal_memset(&sigact
, 0, sizeof(sigact
));
189 sigact
.sa_sigaction
= (sa_sigaction_t
)handler
;
190 // Do not block the signal from being received in that signal's handler.
191 // Clients are responsible for handling this correctly.
192 sigact
.sa_flags
= SA_SIGINFO
| SA_NODEFER
;
193 if (common_flags()->use_sigaltstack
) sigact
.sa_flags
|= SA_ONSTACK
;
194 CHECK_EQ(0, internal_sigaction(signum
, &sigact
, nullptr));
195 VReport(1, "Installed the sigaction for signal %d\n", signum
);
198 void InstallDeadlySignalHandlers(SignalHandlerType handler
) {
199 // Set the alternate signal stack for the main thread.
200 // This will cause SetAlternateSignalStack to be called twice, but the stack
201 // will be actually set only once.
202 if (common_flags()->use_sigaltstack
) SetAlternateSignalStack();
203 MaybeInstallSigaction(SIGSEGV
, handler
);
204 MaybeInstallSigaction(SIGBUS
, handler
);
205 MaybeInstallSigaction(SIGABRT
, handler
);
206 MaybeInstallSigaction(SIGFPE
, handler
);
207 MaybeInstallSigaction(SIGILL
, handler
);
209 #endif // SANITIZER_GO
211 bool IsAccessibleMemoryRange(uptr beg
, uptr size
) {
212 uptr page_size
= GetPageSizeCached();
213 // Checking too large memory ranges is slow.
214 CHECK_LT(size
, page_size
* 10);
219 internal_write(sock_pair
[1], reinterpret_cast<void *>(beg
), size
);
222 if (internal_iserror(bytes_written
, &write_errno
)) {
223 CHECK_EQ(EFAULT
, write_errno
);
226 result
= (bytes_written
== size
);
228 internal_close(sock_pair
[0]);
229 internal_close(sock_pair
[1]);
233 void PrepareForSandboxing(__sanitizer_sandbox_arguments
*args
) {
234 // Some kinds of sandboxes may forbid filesystem access, so we won't be able
235 // to read the file mappings from /proc/self/maps. Luckily, neither the
236 // process will be able to load additional libraries, so it's fine to use the
238 MemoryMappingLayout::CacheMemoryMappings();
239 // Same for /proc/self/exe in the symbolizer.
241 Symbolizer::GetOrInit()->PrepareForSandboxing();
242 CovPrepareForSandboxing(args
);
246 #if SANITIZER_ANDROID || SANITIZER_GO
247 int GetNamedMappingFd(const char *name
, uptr size
) {
251 int GetNamedMappingFd(const char *name
, uptr size
) {
252 if (!common_flags()->decorate_proc_maps
)
255 CHECK(internal_strlen(name
) < sizeof(shmname
) - 10);
256 internal_snprintf(shmname
, sizeof(shmname
), "%zu [%s]", internal_getpid(),
258 int fd
= shm_open(shmname
, O_RDWR
| O_CREAT
| O_TRUNC
, S_IRWXU
);
260 int res
= internal_ftruncate(fd
, size
);
262 res
= shm_unlink(shmname
);
268 void *MmapFixedNoReserve(uptr fixed_addr
, uptr size
, const char *name
) {
269 int fd
= name
? GetNamedMappingFd(name
, size
) : -1;
270 unsigned flags
= MAP_PRIVATE
| MAP_FIXED
| MAP_NORESERVE
;
271 if (fd
== -1) flags
|= MAP_ANON
;
273 uptr PageSize
= GetPageSizeCached();
274 uptr p
= internal_mmap((void *)(fixed_addr
& ~(PageSize
- 1)),
275 RoundUpTo(size
, PageSize
), PROT_READ
| PROT_WRITE
,
278 if (internal_iserror(p
, &reserrno
))
279 Report("ERROR: %s failed to "
280 "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
281 SanitizerToolName
, size
, size
, fixed_addr
, reserrno
);
282 IncreaseTotalMmap(size
);
286 void *MmapFixedNoAccess(uptr fixed_addr
, uptr size
, const char *name
) {
287 int fd
= name
? GetNamedMappingFd(name
, size
) : -1;
288 unsigned flags
= MAP_PRIVATE
| MAP_FIXED
| MAP_NORESERVE
;
289 if (fd
== -1) flags
|= MAP_ANON
;
291 return (void *)internal_mmap((void *)fixed_addr
, size
, PROT_NONE
, flags
, fd
,
295 void *MmapNoAccess(uptr size
) {
296 unsigned flags
= MAP_PRIVATE
| MAP_ANON
| MAP_NORESERVE
;
297 return (void *)internal_mmap(nullptr, size
, PROT_NONE
, flags
, -1, 0);
300 // This function is defined elsewhere if we intercepted pthread_attr_getstack.
302 SANITIZER_WEAK_ATTRIBUTE
int
303 real_pthread_attr_getstack(void *attr
, void **addr
, size_t *size
);
306 int my_pthread_attr_getstack(void *attr
, void **addr
, uptr
*size
) {
307 #if !SANITIZER_GO && !SANITIZER_MAC
308 if (&real_pthread_attr_getstack
)
309 return real_pthread_attr_getstack((pthread_attr_t
*)attr
, addr
,
312 return pthread_attr_getstack((pthread_attr_t
*)attr
, addr
, (size_t *)size
);
316 void AdjustStackSize(void *attr_
) {
317 pthread_attr_t
*attr
= (pthread_attr_t
*)attr_
;
320 my_pthread_attr_getstack(attr
, (void**)&stackaddr
, &stacksize
);
321 // GLibC will return (0 - stacksize) as the stack address in the case when
322 // stacksize is set, but stackaddr is not.
323 bool stack_set
= (stackaddr
!= 0) && (stackaddr
+ stacksize
!= 0);
324 // We place a lot of tool data into TLS, account for that.
325 const uptr minstacksize
= GetTlsSize() + 128*1024;
326 if (stacksize
< minstacksize
) {
328 if (stacksize
!= 0) {
329 VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize
,
331 pthread_attr_setstacksize(attr
, minstacksize
);
334 Printf("Sanitizer: pre-allocated stack size is insufficient: "
335 "%zu < %zu\n", stacksize
, minstacksize
);
336 Printf("Sanitizer: pthread_create is likely to fail.\n");
340 #endif // !SANITIZER_GO
342 pid_t
StartSubprocess(const char *program
, const char *const argv
[],
343 fd_t stdin_fd
, fd_t stdout_fd
, fd_t stderr_fd
) {
344 auto file_closer
= at_scope_exit([&] {
345 if (stdin_fd
!= kInvalidFd
) {
346 internal_close(stdin_fd
);
348 if (stdout_fd
!= kInvalidFd
) {
349 internal_close(stdout_fd
);
351 if (stderr_fd
!= kInvalidFd
) {
352 internal_close(stderr_fd
);
356 int pid
= internal_fork();
360 if (internal_iserror(pid
, &rverrno
)) {
361 Report("WARNING: failed to fork (errno %d)\n", rverrno
);
368 if (stdin_fd
!= kInvalidFd
) {
369 internal_close(STDIN_FILENO
);
370 internal_dup2(stdin_fd
, STDIN_FILENO
);
371 internal_close(stdin_fd
);
373 if (stdout_fd
!= kInvalidFd
) {
374 internal_close(STDOUT_FILENO
);
375 internal_dup2(stdout_fd
, STDOUT_FILENO
);
376 internal_close(stdout_fd
);
378 if (stderr_fd
!= kInvalidFd
) {
379 internal_close(STDERR_FILENO
);
380 internal_dup2(stderr_fd
, STDERR_FILENO
);
381 internal_close(stderr_fd
);
384 for (int fd
= sysconf(_SC_OPEN_MAX
); fd
> 2; fd
--) internal_close(fd
);
386 execv(program
, const_cast<char **>(&argv
[0]));
393 bool IsProcessRunning(pid_t pid
) {
395 uptr waitpid_status
= internal_waitpid(pid
, &process_status
, WNOHANG
);
397 if (internal_iserror(waitpid_status
, &local_errno
)) {
398 VReport(1, "Waiting on the process failed (errno %d).\n", local_errno
);
401 return waitpid_status
== 0;
404 int WaitForProcess(pid_t pid
) {
406 uptr waitpid_status
= internal_waitpid(pid
, &process_status
, 0);
408 if (internal_iserror(waitpid_status
, &local_errno
)) {
409 VReport(1, "Waiting on the process failed (errno %d).\n", local_errno
);
412 return process_status
;
415 } // namespace __sanitizer
417 #endif // SANITIZER_POSIX