123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192 |
- //===-- sanitizer_posix_libcdep.cc ----------------------------------------===//
- //
- // This file is distributed under the University of Illinois Open Source
- // License. See LICENSE.TXT for details.
- //
- //===----------------------------------------------------------------------===//
- //
- // This file is shared between AddressSanitizer and ThreadSanitizer
- // run-time libraries and implements libc-dependent POSIX-specific functions
- // from sanitizer_libc.h.
- //===----------------------------------------------------------------------===//
- #include "sanitizer_platform.h"
- #if SANITIZER_POSIX
- #include "sanitizer_common.h"
- #include "sanitizer_flags.h"
- #include "sanitizer_platform_limits_posix.h"
- #include "sanitizer_stacktrace.h"
- #include <errno.h>
- #include <pthread.h>
- #include <signal.h>
- #include <stdlib.h>
- #include <sys/mman.h>
- #include <sys/resource.h>
- #include <sys/time.h>
- #include <sys/types.h>
- #include <unistd.h>
- namespace __sanitizer {
- u32 GetUid() {
- return getuid();
- }
- uptr GetThreadSelf() {
- return (uptr)pthread_self();
- }
- void FlushUnneededShadowMemory(uptr addr, uptr size) {
- madvise((void*)addr, size, MADV_DONTNEED);
- }
- static rlim_t getlim(int res) {
- rlimit rlim;
- CHECK_EQ(0, getrlimit(res, &rlim));
- return rlim.rlim_cur;
- }
- static void setlim(int res, rlim_t lim) {
- // The following magic is to prevent clang from replacing it with memset.
- volatile struct rlimit rlim;
- rlim.rlim_cur = lim;
- rlim.rlim_max = lim;
- if (setrlimit(res, (struct rlimit*)&rlim)) {
- Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
- Die();
- }
- }
- void DisableCoreDumperIfNecessary() {
- if (common_flags()->disable_coredump) {
- setlim(RLIMIT_CORE, 0);
- }
- }
- bool StackSizeIsUnlimited() {
- rlim_t stack_size = getlim(RLIMIT_STACK);
- return (stack_size == RLIM_INFINITY);
- }
- void SetStackSizeLimitInBytes(uptr limit) {
- setlim(RLIMIT_STACK, (rlim_t)limit);
- CHECK(!StackSizeIsUnlimited());
- }
- bool AddressSpaceIsUnlimited() {
- rlim_t as_size = getlim(RLIMIT_AS);
- return (as_size == RLIM_INFINITY);
- }
- void SetAddressSpaceUnlimited() {
- setlim(RLIMIT_AS, RLIM_INFINITY);
- CHECK(AddressSpaceIsUnlimited());
- }
- void SleepForSeconds(int seconds) {
- sleep(seconds);
- }
- void SleepForMillis(int millis) {
- usleep(millis * 1000);
- }
- void Abort() {
- abort();
- }
- int Atexit(void (*function)(void)) {
- #ifndef SANITIZER_GO
- return atexit(function);
- #else
- return 0;
- #endif
- }
- int internal_isatty(fd_t fd) {
- return isatty(fd);
- }
- #ifndef SANITIZER_GO
- // TODO(glider): different tools may require different altstack size.
- static const uptr kAltStackSize = SIGSTKSZ * 4; // SIGSTKSZ is not enough.
- void SetAlternateSignalStack() {
- stack_t altstack, oldstack;
- CHECK_EQ(0, sigaltstack(0, &oldstack));
- // If the alternate stack is already in place, do nothing.
- // Android always sets an alternate stack, but it's too small for us.
- if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
- // TODO(glider): the mapped stack should have the MAP_STACK flag in the
- // future. It is not required by man 2 sigaltstack now (they're using
- // malloc()).
- void* base = MmapOrDie(kAltStackSize, __func__);
- altstack.ss_sp = (char*) base;
- altstack.ss_flags = 0;
- altstack.ss_size = kAltStackSize;
- CHECK_EQ(0, sigaltstack(&altstack, 0));
- }
- void UnsetAlternateSignalStack() {
- stack_t altstack, oldstack;
- altstack.ss_sp = 0;
- altstack.ss_flags = SS_DISABLE;
- altstack.ss_size = kAltStackSize; // Some sane value required on Darwin.
- CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
- UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
- }
- typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
- static void MaybeInstallSigaction(int signum,
- SignalHandlerType handler) {
- if (!IsDeadlySignal(signum))
- return;
- struct sigaction sigact;
- internal_memset(&sigact, 0, sizeof(sigact));
- sigact.sa_sigaction = (sa_sigaction_t)handler;
- // Do not block the signal from being received in that signal's handler.
- // Clients are responsible for handling this correctly.
- sigact.sa_flags = SA_SIGINFO | SA_NODEFER;
- if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
- CHECK_EQ(0, internal_sigaction(signum, &sigact, 0));
- VReport(1, "Installed the sigaction for signal %d\n", signum);
- }
- void InstallDeadlySignalHandlers(SignalHandlerType handler) {
- // Set the alternate signal stack for the main thread.
- // This will cause SetAlternateSignalStack to be called twice, but the stack
- // will be actually set only once.
- if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
- MaybeInstallSigaction(SIGSEGV, handler);
- MaybeInstallSigaction(SIGBUS, handler);
- }
- #endif // SANITIZER_GO
- bool IsAccessibleMemoryRange(uptr beg, uptr size) {
- uptr page_size = GetPageSizeCached();
- // Checking too large memory ranges is slow.
- CHECK_LT(size, page_size * 10);
- int sock_pair[2];
- if (pipe(sock_pair))
- return false;
- uptr bytes_written =
- internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
- int write_errno;
- bool result;
- if (internal_iserror(bytes_written, &write_errno)) {
- CHECK_EQ(EFAULT, write_errno);
- result = false;
- } else {
- result = (bytes_written == size);
- }
- internal_close(sock_pair[0]);
- internal_close(sock_pair[1]);
- return result;
- }
- } // namespace __sanitizer
- #endif // SANITIZER_POSIX
|