13cab2bb3Spatrick //===-- sanitizer_posix_libcdep.cpp ---------------------------------------===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //
73cab2bb3Spatrick //===----------------------------------------------------------------------===//
83cab2bb3Spatrick //
93cab2bb3Spatrick // This file is shared between AddressSanitizer and ThreadSanitizer
103cab2bb3Spatrick // run-time libraries and implements libc-dependent POSIX-specific functions
113cab2bb3Spatrick // from sanitizer_libc.h.
123cab2bb3Spatrick //===----------------------------------------------------------------------===//
133cab2bb3Spatrick 
143cab2bb3Spatrick #include "sanitizer_platform.h"
153cab2bb3Spatrick 
163cab2bb3Spatrick #if SANITIZER_POSIX
173cab2bb3Spatrick 
183cab2bb3Spatrick #include "sanitizer_common.h"
193cab2bb3Spatrick #include "sanitizer_flags.h"
203cab2bb3Spatrick #include "sanitizer_platform_limits_netbsd.h"
213cab2bb3Spatrick #include "sanitizer_platform_limits_posix.h"
223cab2bb3Spatrick #include "sanitizer_platform_limits_solaris.h"
233cab2bb3Spatrick #include "sanitizer_posix.h"
243cab2bb3Spatrick #include "sanitizer_procmaps.h"
253cab2bb3Spatrick 
263cab2bb3Spatrick #include <errno.h>
273cab2bb3Spatrick #include <fcntl.h>
283cab2bb3Spatrick #include <pthread.h>
293cab2bb3Spatrick #include <signal.h>
303cab2bb3Spatrick #include <stdlib.h>
313cab2bb3Spatrick #include <sys/mman.h>
323cab2bb3Spatrick #include <sys/resource.h>
333cab2bb3Spatrick #include <sys/stat.h>
343cab2bb3Spatrick #include <sys/time.h>
353cab2bb3Spatrick #include <sys/types.h>
363cab2bb3Spatrick #include <sys/wait.h>
373cab2bb3Spatrick #include <unistd.h>
383cab2bb3Spatrick 
393cab2bb3Spatrick #if SANITIZER_FREEBSD
403cab2bb3Spatrick // The MAP_NORESERVE define has been removed in FreeBSD 11.x, and even before
413cab2bb3Spatrick // that, it was never implemented.  So just define it to zero.
423cab2bb3Spatrick #undef MAP_NORESERVE
433cab2bb3Spatrick #define MAP_NORESERVE 0
443cab2bb3Spatrick #endif
453cab2bb3Spatrick 
463cab2bb3Spatrick typedef void (*sa_sigaction_t)(int, siginfo_t *, void *);
473cab2bb3Spatrick 
483cab2bb3Spatrick namespace __sanitizer {
493cab2bb3Spatrick 
GetUid()503cab2bb3Spatrick u32 GetUid() {
513cab2bb3Spatrick   return getuid();
523cab2bb3Spatrick }
533cab2bb3Spatrick 
GetThreadSelf()543cab2bb3Spatrick uptr GetThreadSelf() {
553cab2bb3Spatrick   return (uptr)pthread_self();
563cab2bb3Spatrick }
573cab2bb3Spatrick 
ReleaseMemoryPagesToOS(uptr beg,uptr end)583cab2bb3Spatrick void ReleaseMemoryPagesToOS(uptr beg, uptr end) {
593cab2bb3Spatrick   uptr page_size = GetPageSizeCached();
603cab2bb3Spatrick   uptr beg_aligned = RoundUpTo(beg, page_size);
613cab2bb3Spatrick   uptr end_aligned = RoundDownTo(end, page_size);
623cab2bb3Spatrick   if (beg_aligned < end_aligned)
63d89ec533Spatrick     internal_madvise(beg_aligned, end_aligned - beg_aligned,
643cab2bb3Spatrick                      SANITIZER_MADVISE_DONTNEED);
653cab2bb3Spatrick }
663cab2bb3Spatrick 
SetShadowRegionHugePageMode(uptr addr,uptr size)673cab2bb3Spatrick void SetShadowRegionHugePageMode(uptr addr, uptr size) {
683cab2bb3Spatrick #ifdef MADV_NOHUGEPAGE  // May not be defined on old systems.
693cab2bb3Spatrick   if (common_flags()->no_huge_pages_for_shadow)
70d89ec533Spatrick     internal_madvise(addr, size, MADV_NOHUGEPAGE);
713cab2bb3Spatrick   else
72d89ec533Spatrick     internal_madvise(addr, size, MADV_HUGEPAGE);
733cab2bb3Spatrick #endif  // MADV_NOHUGEPAGE
743cab2bb3Spatrick }
753cab2bb3Spatrick 
DontDumpShadowMemory(uptr addr,uptr length)763cab2bb3Spatrick bool DontDumpShadowMemory(uptr addr, uptr length) {
773cab2bb3Spatrick #if defined(MADV_DONTDUMP)
78d89ec533Spatrick   return internal_madvise(addr, length, MADV_DONTDUMP) == 0;
793cab2bb3Spatrick #elif defined(MADV_NOCORE)
80d89ec533Spatrick   return internal_madvise(addr, length, MADV_NOCORE) == 0;
813cab2bb3Spatrick #else
823cab2bb3Spatrick   return true;
833cab2bb3Spatrick #endif  // MADV_DONTDUMP
843cab2bb3Spatrick }
853cab2bb3Spatrick 
getlim(int res)863cab2bb3Spatrick static rlim_t getlim(int res) {
873cab2bb3Spatrick   rlimit rlim;
883cab2bb3Spatrick   CHECK_EQ(0, getrlimit(res, &rlim));
893cab2bb3Spatrick   return rlim.rlim_cur;
903cab2bb3Spatrick }
913cab2bb3Spatrick 
setlim(int res,rlim_t lim)923cab2bb3Spatrick static void setlim(int res, rlim_t lim) {
933cab2bb3Spatrick   struct rlimit rlim;
943cab2bb3Spatrick   if (getrlimit(res, const_cast<struct rlimit *>(&rlim))) {
953cab2bb3Spatrick     Report("ERROR: %s getrlimit() failed %d\n", SanitizerToolName, errno);
963cab2bb3Spatrick     Die();
973cab2bb3Spatrick   }
983cab2bb3Spatrick   rlim.rlim_cur = lim;
993cab2bb3Spatrick   if (setrlimit(res, const_cast<struct rlimit *>(&rlim))) {
1003cab2bb3Spatrick     Report("ERROR: %s setrlimit() failed %d\n", SanitizerToolName, errno);
1013cab2bb3Spatrick     Die();
1023cab2bb3Spatrick   }
1033cab2bb3Spatrick }
1043cab2bb3Spatrick 
DisableCoreDumperIfNecessary()1053cab2bb3Spatrick void DisableCoreDumperIfNecessary() {
1063cab2bb3Spatrick   if (common_flags()->disable_coredump) {
1073cab2bb3Spatrick     setlim(RLIMIT_CORE, 0);
1083cab2bb3Spatrick   }
1093cab2bb3Spatrick }
1103cab2bb3Spatrick 
StackSizeIsUnlimited()1113cab2bb3Spatrick bool StackSizeIsUnlimited() {
1123cab2bb3Spatrick   rlim_t stack_size = getlim(RLIMIT_STACK);
1133cab2bb3Spatrick   return (stack_size == RLIM_INFINITY);
1143cab2bb3Spatrick }
1153cab2bb3Spatrick 
SetStackSizeLimitInBytes(uptr limit)1163cab2bb3Spatrick void SetStackSizeLimitInBytes(uptr limit) {
1173cab2bb3Spatrick   setlim(RLIMIT_STACK, (rlim_t)limit);
1183cab2bb3Spatrick   CHECK(!StackSizeIsUnlimited());
1193cab2bb3Spatrick }
1203cab2bb3Spatrick 
AddressSpaceIsUnlimited()1213cab2bb3Spatrick bool AddressSpaceIsUnlimited() {
1223cab2bb3Spatrick   rlim_t as_size = getlim(RLIMIT_AS);
1233cab2bb3Spatrick   return (as_size == RLIM_INFINITY);
1243cab2bb3Spatrick }
1253cab2bb3Spatrick 
SetAddressSpaceUnlimited()1263cab2bb3Spatrick void SetAddressSpaceUnlimited() {
1273cab2bb3Spatrick   setlim(RLIMIT_AS, RLIM_INFINITY);
1283cab2bb3Spatrick   CHECK(AddressSpaceIsUnlimited());
1293cab2bb3Spatrick }
1303cab2bb3Spatrick 
Abort()1313cab2bb3Spatrick void Abort() {
1323cab2bb3Spatrick #if !SANITIZER_GO
1333cab2bb3Spatrick   // If we are handling SIGABRT, unhandle it first.
1343cab2bb3Spatrick   // TODO(vitalybuka): Check if handler belongs to sanitizer.
1353cab2bb3Spatrick   if (GetHandleSignalMode(SIGABRT) != kHandleSignalNo) {
1363cab2bb3Spatrick     struct sigaction sigact;
1373cab2bb3Spatrick     internal_memset(&sigact, 0, sizeof(sigact));
138d89ec533Spatrick     sigact.sa_handler = SIG_DFL;
1393cab2bb3Spatrick     internal_sigaction(SIGABRT, &sigact, nullptr);
1403cab2bb3Spatrick   }
1413cab2bb3Spatrick #endif
1423cab2bb3Spatrick 
1433cab2bb3Spatrick   abort();
1443cab2bb3Spatrick }
1453cab2bb3Spatrick 
Atexit(void (* function)(void))1463cab2bb3Spatrick int Atexit(void (*function)(void)) {
1473cab2bb3Spatrick #if !SANITIZER_GO
1483cab2bb3Spatrick   return atexit(function);
1493cab2bb3Spatrick #else
1503cab2bb3Spatrick   return 0;
1513cab2bb3Spatrick #endif
1523cab2bb3Spatrick }
1533cab2bb3Spatrick 
CreateDir(const char * pathname)154*810390e3Srobert bool CreateDir(const char *pathname) { return mkdir(pathname, 0755) == 0; }
155*810390e3Srobert 
SupportsColoredOutput(fd_t fd)1563cab2bb3Spatrick bool SupportsColoredOutput(fd_t fd) {
1573cab2bb3Spatrick   return isatty(fd) != 0;
1583cab2bb3Spatrick }
1593cab2bb3Spatrick 
1603cab2bb3Spatrick #if !SANITIZER_GO
1613cab2bb3Spatrick // TODO(glider): different tools may require different altstack size.
GetAltStackSize()162d89ec533Spatrick static uptr GetAltStackSize() {
163d89ec533Spatrick   // Note: since GLIBC_2.31, SIGSTKSZ may be a function call, so this may be
164d89ec533Spatrick   // more costly that you think. However GetAltStackSize is only call 2-3 times
165d89ec533Spatrick   // per thread so don't cache the evaluation.
166d89ec533Spatrick   return SIGSTKSZ * 4;
167d89ec533Spatrick }
1683cab2bb3Spatrick 
SetAlternateSignalStack()1693cab2bb3Spatrick void SetAlternateSignalStack() {
1703cab2bb3Spatrick   stack_t altstack, oldstack;
1713cab2bb3Spatrick   CHECK_EQ(0, sigaltstack(nullptr, &oldstack));
1723cab2bb3Spatrick   // If the alternate stack is already in place, do nothing.
1733cab2bb3Spatrick   // Android always sets an alternate stack, but it's too small for us.
1743cab2bb3Spatrick   if (!SANITIZER_ANDROID && !(oldstack.ss_flags & SS_DISABLE)) return;
1753cab2bb3Spatrick   // TODO(glider): the mapped stack should have the MAP_STACK flag in the
1763cab2bb3Spatrick   // future. It is not required by man 2 sigaltstack now (they're using
1773cab2bb3Spatrick   // malloc()).
178d89ec533Spatrick   altstack.ss_size = GetAltStackSize();
179d89ec533Spatrick   altstack.ss_sp = (char *)MmapOrDie(altstack.ss_size, __func__);
1803cab2bb3Spatrick   altstack.ss_flags = 0;
1813cab2bb3Spatrick   CHECK_EQ(0, sigaltstack(&altstack, nullptr));
1823cab2bb3Spatrick }
1833cab2bb3Spatrick 
UnsetAlternateSignalStack()1843cab2bb3Spatrick void UnsetAlternateSignalStack() {
1853cab2bb3Spatrick   stack_t altstack, oldstack;
1863cab2bb3Spatrick   altstack.ss_sp = nullptr;
1873cab2bb3Spatrick   altstack.ss_flags = SS_DISABLE;
188d89ec533Spatrick   altstack.ss_size = GetAltStackSize();  // Some sane value required on Darwin.
1893cab2bb3Spatrick   CHECK_EQ(0, sigaltstack(&altstack, &oldstack));
1903cab2bb3Spatrick   UnmapOrDie(oldstack.ss_sp, oldstack.ss_size);
1913cab2bb3Spatrick }
1923cab2bb3Spatrick 
MaybeInstallSigaction(int signum,SignalHandlerType handler)1933cab2bb3Spatrick static void MaybeInstallSigaction(int signum,
1943cab2bb3Spatrick                                   SignalHandlerType handler) {
1953cab2bb3Spatrick   if (GetHandleSignalMode(signum) == kHandleSignalNo) return;
1963cab2bb3Spatrick 
1973cab2bb3Spatrick   struct sigaction sigact;
1983cab2bb3Spatrick   internal_memset(&sigact, 0, sizeof(sigact));
1993cab2bb3Spatrick   sigact.sa_sigaction = (sa_sigaction_t)handler;
2003cab2bb3Spatrick   // Do not block the signal from being received in that signal's handler.
2013cab2bb3Spatrick   // Clients are responsible for handling this correctly.
2023cab2bb3Spatrick   sigact.sa_flags = SA_SIGINFO | SA_NODEFER;
2033cab2bb3Spatrick   if (common_flags()->use_sigaltstack) sigact.sa_flags |= SA_ONSTACK;
2043cab2bb3Spatrick   CHECK_EQ(0, internal_sigaction(signum, &sigact, nullptr));
2053cab2bb3Spatrick   VReport(1, "Installed the sigaction for signal %d\n", signum);
2063cab2bb3Spatrick }
2073cab2bb3Spatrick 
InstallDeadlySignalHandlers(SignalHandlerType handler)2083cab2bb3Spatrick void InstallDeadlySignalHandlers(SignalHandlerType handler) {
2093cab2bb3Spatrick   // Set the alternate signal stack for the main thread.
2103cab2bb3Spatrick   // This will cause SetAlternateSignalStack to be called twice, but the stack
2113cab2bb3Spatrick   // will be actually set only once.
2123cab2bb3Spatrick   if (common_flags()->use_sigaltstack) SetAlternateSignalStack();
2133cab2bb3Spatrick   MaybeInstallSigaction(SIGSEGV, handler);
2143cab2bb3Spatrick   MaybeInstallSigaction(SIGBUS, handler);
2153cab2bb3Spatrick   MaybeInstallSigaction(SIGABRT, handler);
2163cab2bb3Spatrick   MaybeInstallSigaction(SIGFPE, handler);
2173cab2bb3Spatrick   MaybeInstallSigaction(SIGILL, handler);
2183cab2bb3Spatrick   MaybeInstallSigaction(SIGTRAP, handler);
2193cab2bb3Spatrick }
2203cab2bb3Spatrick 
IsStackOverflow() const2213cab2bb3Spatrick bool SignalContext::IsStackOverflow() const {
2223cab2bb3Spatrick   // Access at a reasonable offset above SP, or slightly below it (to account
2233cab2bb3Spatrick   // for x86_64 or PowerPC redzone, ARM push of multiple registers, etc) is
2243cab2bb3Spatrick   // probably a stack overflow.
2253cab2bb3Spatrick #ifdef __s390__
2263cab2bb3Spatrick   // On s390, the fault address in siginfo points to start of the page, not
2273cab2bb3Spatrick   // to the precise word that was accessed.  Mask off the low bits of sp to
2283cab2bb3Spatrick   // take it into account.
2293cab2bb3Spatrick   bool IsStackAccess = addr >= (sp & ~0xFFF) && addr < sp + 0xFFFF;
2303cab2bb3Spatrick #else
2313cab2bb3Spatrick   // Let's accept up to a page size away from top of stack. Things like stack
2323cab2bb3Spatrick   // probing can trigger accesses with such large offsets.
2333cab2bb3Spatrick   bool IsStackAccess = addr + GetPageSizeCached() > sp && addr < sp + 0xFFFF;
2343cab2bb3Spatrick #endif
2353cab2bb3Spatrick 
2363cab2bb3Spatrick #if __powerpc__
2373cab2bb3Spatrick   // Large stack frames can be allocated with e.g.
2383cab2bb3Spatrick   //   lis r0,-10000
2393cab2bb3Spatrick   //   stdux r1,r1,r0 # store sp to [sp-10000] and update sp by -10000
2403cab2bb3Spatrick   // If the store faults then sp will not have been updated, so test above
2413cab2bb3Spatrick   // will not work, because the fault address will be more than just "slightly"
2423cab2bb3Spatrick   // below sp.
2433cab2bb3Spatrick   if (!IsStackAccess && IsAccessibleMemoryRange(pc, 4)) {
2443cab2bb3Spatrick     u32 inst = *(unsigned *)pc;
2453cab2bb3Spatrick     u32 ra = (inst >> 16) & 0x1F;
2463cab2bb3Spatrick     u32 opcd = inst >> 26;
2473cab2bb3Spatrick     u32 xo = (inst >> 1) & 0x3FF;
2483cab2bb3Spatrick     // Check for store-with-update to sp. The instructions we accept are:
2493cab2bb3Spatrick     //   stbu rs,d(ra)          stbux rs,ra,rb
2503cab2bb3Spatrick     //   sthu rs,d(ra)          sthux rs,ra,rb
2513cab2bb3Spatrick     //   stwu rs,d(ra)          stwux rs,ra,rb
2523cab2bb3Spatrick     //   stdu rs,ds(ra)         stdux rs,ra,rb
2533cab2bb3Spatrick     // where ra is r1 (the stack pointer).
2543cab2bb3Spatrick     if (ra == 1 &&
2553cab2bb3Spatrick         (opcd == 39 || opcd == 45 || opcd == 37 || opcd == 62 ||
2563cab2bb3Spatrick          (opcd == 31 && (xo == 247 || xo == 439 || xo == 183 || xo == 181))))
2573cab2bb3Spatrick       IsStackAccess = true;
2583cab2bb3Spatrick   }
2593cab2bb3Spatrick #endif  // __powerpc__
2603cab2bb3Spatrick 
2613cab2bb3Spatrick   // We also check si_code to filter out SEGV caused by something else other
2623cab2bb3Spatrick   // then hitting the guard page or unmapped memory, like, for example,
2633cab2bb3Spatrick   // unaligned memory access.
2643cab2bb3Spatrick   auto si = static_cast<const siginfo_t *>(siginfo);
2653cab2bb3Spatrick   return IsStackAccess &&
2663cab2bb3Spatrick          (si->si_code == si_SEGV_MAPERR || si->si_code == si_SEGV_ACCERR);
2673cab2bb3Spatrick }
2683cab2bb3Spatrick 
2693cab2bb3Spatrick #endif  // SANITIZER_GO
2703cab2bb3Spatrick 
IsAccessibleMemoryRange(uptr beg,uptr size)2713cab2bb3Spatrick bool IsAccessibleMemoryRange(uptr beg, uptr size) {
2723cab2bb3Spatrick   uptr page_size = GetPageSizeCached();
2733cab2bb3Spatrick   // Checking too large memory ranges is slow.
2743cab2bb3Spatrick   CHECK_LT(size, page_size * 10);
2753cab2bb3Spatrick   int sock_pair[2];
2763cab2bb3Spatrick   if (pipe(sock_pair))
2773cab2bb3Spatrick     return false;
2783cab2bb3Spatrick   uptr bytes_written =
2793cab2bb3Spatrick       internal_write(sock_pair[1], reinterpret_cast<void *>(beg), size);
2803cab2bb3Spatrick   int write_errno;
2813cab2bb3Spatrick   bool result;
2823cab2bb3Spatrick   if (internal_iserror(bytes_written, &write_errno)) {
2833cab2bb3Spatrick     CHECK_EQ(EFAULT, write_errno);
2843cab2bb3Spatrick     result = false;
2853cab2bb3Spatrick   } else {
2863cab2bb3Spatrick     result = (bytes_written == size);
2873cab2bb3Spatrick   }
2883cab2bb3Spatrick   internal_close(sock_pair[0]);
2893cab2bb3Spatrick   internal_close(sock_pair[1]);
2903cab2bb3Spatrick   return result;
2913cab2bb3Spatrick }
2923cab2bb3Spatrick 
PlatformPrepareForSandboxing(void * args)293*810390e3Srobert void PlatformPrepareForSandboxing(void *args) {
2943cab2bb3Spatrick   // Some kinds of sandboxes may forbid filesystem access, so we won't be able
2953cab2bb3Spatrick   // to read the file mappings from /proc/self/maps. Luckily, neither the
2963cab2bb3Spatrick   // process will be able to load additional libraries, so it's fine to use the
2973cab2bb3Spatrick   // cached mappings.
2983cab2bb3Spatrick   MemoryMappingLayout::CacheMemoryMappings();
2993cab2bb3Spatrick }
3003cab2bb3Spatrick 
MmapFixed(uptr fixed_addr,uptr size,int additional_flags,const char * name)3013cab2bb3Spatrick static bool MmapFixed(uptr fixed_addr, uptr size, int additional_flags,
3023cab2bb3Spatrick                       const char *name) {
3033cab2bb3Spatrick   size = RoundUpTo(size, GetPageSizeCached());
3043cab2bb3Spatrick   fixed_addr = RoundDownTo(fixed_addr, GetPageSizeCached());
3053cab2bb3Spatrick   uptr p =
3063cab2bb3Spatrick       MmapNamed((void *)fixed_addr, size, PROT_READ | PROT_WRITE,
3073cab2bb3Spatrick                 MAP_PRIVATE | MAP_FIXED | additional_flags | MAP_ANON, name);
3083cab2bb3Spatrick   int reserrno;
3093cab2bb3Spatrick   if (internal_iserror(p, &reserrno)) {
3103cab2bb3Spatrick     Report("ERROR: %s failed to "
3113cab2bb3Spatrick            "allocate 0x%zx (%zd) bytes at address %zx (errno: %d)\n",
3123cab2bb3Spatrick            SanitizerToolName, size, size, fixed_addr, reserrno);
3133cab2bb3Spatrick     return false;
3143cab2bb3Spatrick   }
3153cab2bb3Spatrick   IncreaseTotalMmap(size);
3163cab2bb3Spatrick   return true;
3173cab2bb3Spatrick }
3183cab2bb3Spatrick 
MmapFixedNoReserve(uptr fixed_addr,uptr size,const char * name)3193cab2bb3Spatrick bool MmapFixedNoReserve(uptr fixed_addr, uptr size, const char *name) {
3203cab2bb3Spatrick   return MmapFixed(fixed_addr, size, MAP_NORESERVE, name);
3213cab2bb3Spatrick }
3223cab2bb3Spatrick 
MmapFixedSuperNoReserve(uptr fixed_addr,uptr size,const char * name)3233cab2bb3Spatrick bool MmapFixedSuperNoReserve(uptr fixed_addr, uptr size, const char *name) {
3243cab2bb3Spatrick #if SANITIZER_FREEBSD
3253cab2bb3Spatrick   if (common_flags()->no_huge_pages_for_shadow)
3263cab2bb3Spatrick     return MmapFixedNoReserve(fixed_addr, size, name);
3273cab2bb3Spatrick   // MAP_NORESERVE is implicit with FreeBSD
3283cab2bb3Spatrick   return MmapFixed(fixed_addr, size, MAP_ALIGNED_SUPER, name);
3293cab2bb3Spatrick #else
3303cab2bb3Spatrick   bool r = MmapFixedNoReserve(fixed_addr, size, name);
3313cab2bb3Spatrick   if (r)
3323cab2bb3Spatrick     SetShadowRegionHugePageMode(fixed_addr, size);
3333cab2bb3Spatrick   return r;
3343cab2bb3Spatrick #endif
3353cab2bb3Spatrick }
3363cab2bb3Spatrick 
Init(uptr size,const char * name,uptr fixed_addr)3373cab2bb3Spatrick uptr ReservedAddressRange::Init(uptr size, const char *name, uptr fixed_addr) {
3383cab2bb3Spatrick   base_ = fixed_addr ? MmapFixedNoAccess(fixed_addr, size, name)
3393cab2bb3Spatrick                      : MmapNoAccess(size);
3403cab2bb3Spatrick   size_ = size;
3413cab2bb3Spatrick   name_ = name;
3423cab2bb3Spatrick   (void)os_handle_;  // unsupported
3433cab2bb3Spatrick   return reinterpret_cast<uptr>(base_);
3443cab2bb3Spatrick }
3453cab2bb3Spatrick 
3463cab2bb3Spatrick // Uses fixed_addr for now.
3473cab2bb3Spatrick // Will use offset instead once we've implemented this function for real.
Map(uptr fixed_addr,uptr size,const char * name)3483cab2bb3Spatrick uptr ReservedAddressRange::Map(uptr fixed_addr, uptr size, const char *name) {
3493cab2bb3Spatrick   return reinterpret_cast<uptr>(
3503cab2bb3Spatrick       MmapFixedOrDieOnFatalError(fixed_addr, size, name));
3513cab2bb3Spatrick }
3523cab2bb3Spatrick 
MapOrDie(uptr fixed_addr,uptr size,const char * name)3533cab2bb3Spatrick uptr ReservedAddressRange::MapOrDie(uptr fixed_addr, uptr size,
3543cab2bb3Spatrick                                     const char *name) {
3553cab2bb3Spatrick   return reinterpret_cast<uptr>(MmapFixedOrDie(fixed_addr, size, name));
3563cab2bb3Spatrick }
3573cab2bb3Spatrick 
Unmap(uptr addr,uptr size)3583cab2bb3Spatrick void ReservedAddressRange::Unmap(uptr addr, uptr size) {
3593cab2bb3Spatrick   CHECK_LE(size, size_);
3603cab2bb3Spatrick   if (addr == reinterpret_cast<uptr>(base_))
3613cab2bb3Spatrick     // If we unmap the whole range, just null out the base.
3623cab2bb3Spatrick     base_ = (size == size_) ? nullptr : reinterpret_cast<void*>(addr + size);
3633cab2bb3Spatrick   else
3643cab2bb3Spatrick     CHECK_EQ(addr + size, reinterpret_cast<uptr>(base_) + size_);
3653cab2bb3Spatrick   size_ -= size;
3663cab2bb3Spatrick   UnmapOrDie(reinterpret_cast<void*>(addr), size);
3673cab2bb3Spatrick }
3683cab2bb3Spatrick 
MmapFixedNoAccess(uptr fixed_addr,uptr size,const char * name)3693cab2bb3Spatrick void *MmapFixedNoAccess(uptr fixed_addr, uptr size, const char *name) {
3703cab2bb3Spatrick   return (void *)MmapNamed((void *)fixed_addr, size, PROT_NONE,
3713cab2bb3Spatrick                            MAP_PRIVATE | MAP_FIXED | MAP_NORESERVE | MAP_ANON,
3723cab2bb3Spatrick                            name);
3733cab2bb3Spatrick }
3743cab2bb3Spatrick 
MmapNoAccess(uptr size)3753cab2bb3Spatrick void *MmapNoAccess(uptr size) {
3763cab2bb3Spatrick   unsigned flags = MAP_PRIVATE | MAP_ANON | MAP_NORESERVE;
3773cab2bb3Spatrick   return (void *)internal_mmap(nullptr, size, PROT_NONE, flags, -1, 0);
3783cab2bb3Spatrick }
3793cab2bb3Spatrick 
3803cab2bb3Spatrick // This function is defined elsewhere if we intercepted pthread_attr_getstack.
3813cab2bb3Spatrick extern "C" {
3823cab2bb3Spatrick SANITIZER_WEAK_ATTRIBUTE int
3833cab2bb3Spatrick real_pthread_attr_getstack(void *attr, void **addr, size_t *size);
3843cab2bb3Spatrick } // extern "C"
3853cab2bb3Spatrick 
my_pthread_attr_getstack(void * attr,void ** addr,uptr * size)3863cab2bb3Spatrick int my_pthread_attr_getstack(void *attr, void **addr, uptr *size) {
387*810390e3Srobert #if !SANITIZER_GO && !SANITIZER_APPLE
3883cab2bb3Spatrick   if (&real_pthread_attr_getstack)
3893cab2bb3Spatrick     return real_pthread_attr_getstack((pthread_attr_t *)attr, addr,
3903cab2bb3Spatrick                                       (size_t *)size);
3913cab2bb3Spatrick #endif
3923cab2bb3Spatrick   return pthread_attr_getstack((pthread_attr_t *)attr, addr, (size_t *)size);
3933cab2bb3Spatrick }
3943cab2bb3Spatrick 
3953cab2bb3Spatrick #if !SANITIZER_GO
AdjustStackSize(void * attr_)3963cab2bb3Spatrick void AdjustStackSize(void *attr_) {
3973cab2bb3Spatrick   pthread_attr_t *attr = (pthread_attr_t *)attr_;
3983cab2bb3Spatrick   uptr stackaddr = 0;
3993cab2bb3Spatrick   uptr stacksize = 0;
4003cab2bb3Spatrick   my_pthread_attr_getstack(attr, (void**)&stackaddr, &stacksize);
4013cab2bb3Spatrick   // GLibC will return (0 - stacksize) as the stack address in the case when
4023cab2bb3Spatrick   // stacksize is set, but stackaddr is not.
4033cab2bb3Spatrick   bool stack_set = (stackaddr != 0) && (stackaddr + stacksize != 0);
4043cab2bb3Spatrick   // We place a lot of tool data into TLS, account for that.
4053cab2bb3Spatrick   const uptr minstacksize = GetTlsSize() + 128*1024;
4063cab2bb3Spatrick   if (stacksize < minstacksize) {
4073cab2bb3Spatrick     if (!stack_set) {
4083cab2bb3Spatrick       if (stacksize != 0) {
4093cab2bb3Spatrick         VPrintf(1, "Sanitizer: increasing stacksize %zu->%zu\n", stacksize,
4103cab2bb3Spatrick                 minstacksize);
4113cab2bb3Spatrick         pthread_attr_setstacksize(attr, minstacksize);
4123cab2bb3Spatrick       }
4133cab2bb3Spatrick     } else {
4143cab2bb3Spatrick       Printf("Sanitizer: pre-allocated stack size is insufficient: "
4153cab2bb3Spatrick              "%zu < %zu\n", stacksize, minstacksize);
4163cab2bb3Spatrick       Printf("Sanitizer: pthread_create is likely to fail.\n");
4173cab2bb3Spatrick     }
4183cab2bb3Spatrick   }
4193cab2bb3Spatrick }
4203cab2bb3Spatrick #endif // !SANITIZER_GO
4213cab2bb3Spatrick 
StartSubprocess(const char * program,const char * const argv[],const char * const envp[],fd_t stdin_fd,fd_t stdout_fd,fd_t stderr_fd)4223cab2bb3Spatrick pid_t StartSubprocess(const char *program, const char *const argv[],
4231f9cb04fSpatrick                       const char *const envp[], fd_t stdin_fd, fd_t stdout_fd,
4241f9cb04fSpatrick                       fd_t stderr_fd) {
4253cab2bb3Spatrick   auto file_closer = at_scope_exit([&] {
4263cab2bb3Spatrick     if (stdin_fd != kInvalidFd) {
4273cab2bb3Spatrick       internal_close(stdin_fd);
4283cab2bb3Spatrick     }
4293cab2bb3Spatrick     if (stdout_fd != kInvalidFd) {
4303cab2bb3Spatrick       internal_close(stdout_fd);
4313cab2bb3Spatrick     }
4323cab2bb3Spatrick     if (stderr_fd != kInvalidFd) {
4333cab2bb3Spatrick       internal_close(stderr_fd);
4343cab2bb3Spatrick     }
4353cab2bb3Spatrick   });
4363cab2bb3Spatrick 
4373cab2bb3Spatrick   int pid = internal_fork();
4383cab2bb3Spatrick 
4393cab2bb3Spatrick   if (pid < 0) {
4403cab2bb3Spatrick     int rverrno;
4413cab2bb3Spatrick     if (internal_iserror(pid, &rverrno)) {
4423cab2bb3Spatrick       Report("WARNING: failed to fork (errno %d)\n", rverrno);
4433cab2bb3Spatrick     }
4443cab2bb3Spatrick     return pid;
4453cab2bb3Spatrick   }
4463cab2bb3Spatrick 
4473cab2bb3Spatrick   if (pid == 0) {
4483cab2bb3Spatrick     // Child subprocess
4493cab2bb3Spatrick     if (stdin_fd != kInvalidFd) {
4503cab2bb3Spatrick       internal_close(STDIN_FILENO);
4513cab2bb3Spatrick       internal_dup2(stdin_fd, STDIN_FILENO);
4523cab2bb3Spatrick       internal_close(stdin_fd);
4533cab2bb3Spatrick     }
4543cab2bb3Spatrick     if (stdout_fd != kInvalidFd) {
4553cab2bb3Spatrick       internal_close(STDOUT_FILENO);
4563cab2bb3Spatrick       internal_dup2(stdout_fd, STDOUT_FILENO);
4573cab2bb3Spatrick       internal_close(stdout_fd);
4583cab2bb3Spatrick     }
4593cab2bb3Spatrick     if (stderr_fd != kInvalidFd) {
4603cab2bb3Spatrick       internal_close(STDERR_FILENO);
4613cab2bb3Spatrick       internal_dup2(stderr_fd, STDERR_FILENO);
4623cab2bb3Spatrick       internal_close(stderr_fd);
4633cab2bb3Spatrick     }
4643cab2bb3Spatrick 
4653cab2bb3Spatrick     for (int fd = sysconf(_SC_OPEN_MAX); fd > 2; fd--) internal_close(fd);
4663cab2bb3Spatrick 
4671f9cb04fSpatrick     internal_execve(program, const_cast<char **>(&argv[0]),
4681f9cb04fSpatrick                     const_cast<char *const *>(envp));
4693cab2bb3Spatrick     internal__exit(1);
4703cab2bb3Spatrick   }
4713cab2bb3Spatrick 
4723cab2bb3Spatrick   return pid;
4733cab2bb3Spatrick }
4743cab2bb3Spatrick 
IsProcessRunning(pid_t pid)4753cab2bb3Spatrick bool IsProcessRunning(pid_t pid) {
4763cab2bb3Spatrick   int process_status;
4773cab2bb3Spatrick   uptr waitpid_status = internal_waitpid(pid, &process_status, WNOHANG);
4783cab2bb3Spatrick   int local_errno;
4793cab2bb3Spatrick   if (internal_iserror(waitpid_status, &local_errno)) {
4803cab2bb3Spatrick     VReport(1, "Waiting on the process failed (errno %d).\n", local_errno);
4813cab2bb3Spatrick     return false;
4823cab2bb3Spatrick   }
4833cab2bb3Spatrick   return waitpid_status == 0;
4843cab2bb3Spatrick }
4853cab2bb3Spatrick 
WaitForProcess(pid_t pid)4863cab2bb3Spatrick int WaitForProcess(pid_t pid) {
4873cab2bb3Spatrick   int process_status;
4883cab2bb3Spatrick   uptr waitpid_status = internal_waitpid(pid, &process_status, 0);
4893cab2bb3Spatrick   int local_errno;
4903cab2bb3Spatrick   if (internal_iserror(waitpid_status, &local_errno)) {
4913cab2bb3Spatrick     VReport(1, "Waiting on the process failed (errno %d).\n", local_errno);
4923cab2bb3Spatrick     return -1;
4933cab2bb3Spatrick   }
4943cab2bb3Spatrick   return process_status;
4953cab2bb3Spatrick }
4963cab2bb3Spatrick 
IsStateDetached(int state)4973cab2bb3Spatrick bool IsStateDetached(int state) {
4983cab2bb3Spatrick   return state == PTHREAD_CREATE_DETACHED;
4993cab2bb3Spatrick }
5003cab2bb3Spatrick 
5013cab2bb3Spatrick } // namespace __sanitizer
5023cab2bb3Spatrick 
5033cab2bb3Spatrick #endif // SANITIZER_POSIX
504