sanitizer_linux.cc revision 25742574510cfb41b97e32f63f107fbb9b328d13
1ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===-- sanitizer_linux.cc ------------------------------------------------===//
2ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
3ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//                     The LLVM Compiler Infrastructure
4ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
5ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is distributed under the University of Illinois Open Source
6ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// License. See LICENSE.TXT for details.
7ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
8ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
9ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//
10ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// This file is shared between AddressSanitizer and ThreadSanitizer
11ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// run-time libraries and implements linux-specific functions from
12ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov// sanitizer_libc.h.
13ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov//===----------------------------------------------------------------------===//
14ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#ifdef __linux__
15ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
166895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_common.h"
1794b5036ee6ba866e1702848855b6d687d1e70afaAlexey Samsonov#include "sanitizer_internal_defs.h"
18ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include "sanitizer_libc.h"
1993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko#include "sanitizer_mutex.h"
20a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#include "sanitizer_placement_new.h"
216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov#include "sanitizer_procmaps.h"
22ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
23c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <fcntl.h>
24e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <pthread.h>
250969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov#include <sched.h>
26ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/mman.h>
27e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/resource.h>
28c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov#include <sys/stat.h>
29ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/syscall.h>
30e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov#include <sys/time.h>
31ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <sys/types.h>
32ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#include <unistd.h>
333334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov#include <errno.h>
34dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany#include <sys/prctl.h>
35ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
369d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany// Are we using 32-bit or 64-bit syscalls?
375af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany// x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32
3808bfe4988de493dd3e61d02759b3f19c42f8fb78Kostya Serebryany// but it still needs to use 64-bit syscalls.
395af39e50366f1aacbebc284f572f08ad1ad07357Kostya Serebryany#if defined(__x86_64__) || SANITIZER_WORDSIZE == 64
409d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 1
419d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#else
429d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany# define SANITIZER_LINUX_USES_64BIT_SYSCALLS 0
439d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#endif
449d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany
45ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovnamespace __sanitizer {
46ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
47e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// --------------- sanitizer_libc.h
48ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonovvoid *internal_mmap(void *addr, uptr length, int prot, int flags,
49ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov                    int fd, u64 offset) {
509d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
51ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset);
52ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#else
53ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov  return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset);
54ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif
55ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}
56ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
571f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonovint internal_munmap(void *addr, uptr length) {
581f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov  return syscall(__NR_munmap, addr, length);
591f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov}
601f11d31faa5ed89b74f7d543b1182fe8de198be5Alexey Samsonov
61a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovint internal_close(fd_t fd) {
62a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov  return syscall(__NR_close, fd);
63a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
64a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
65c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonovfd_t internal_open(const char *filename, bool write) {
66c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov  return syscall(__NR_open, filename,
679b8a9c1b1ce4659457178ff4c0838ac1b35ca9dcKostya Serebryany      write ? O_WRONLY | O_CREAT /*| O_CLOEXEC*/ : O_RDONLY, 0660);
68c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov}
69c5d465136b911bf925f2a631e2b79f1c03e8a1b0Alexey Samsonov
70a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_read(fd_t fd, void *buf, uptr count) {
713334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
723334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  HANDLE_EINTR(res, (sptr)syscall(__NR_read, fd, buf, count));
733334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
74a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
75a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
76a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonovuptr internal_write(fd_t fd, const void *buf, uptr count) {
773334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  sptr res;
783334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  HANDLE_EINTR(res, (sptr)syscall(__NR_write, fd, buf, count));
793334e12d33261cb8f211f2f49f28ddfa027a40c3Evgeniy Stepanov  return res;
80a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov}
81a56aefd2e01940fcf88d1426f9de3d5e4b1ee203Alexey Samsonov
828e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovuptr internal_filesize(fd_t fd) {
839d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
84a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat st;
858e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  if (syscall(__NR_fstat, fd, &st))
868e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov    return -1;
87a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#else
88a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  struct stat64 st;
89a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov  if (syscall(__NR_fstat64, fd, &st))
90a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov    return -1;
91a68633fb76208137ccb807914df52758ee5ca6f0Alexey Samsonov#endif
928e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return (uptr)st.st_size;
938e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
948e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
958e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonovint internal_dup2(int oldfd, int newfd) {
968e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov  return syscall(__NR_dup2, oldfd, newfd);
978e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov}
988e820fcf7aafeb8101322182d742fcf99255d972Alexey Samsonov
99d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonovuptr internal_readlink(const char *path, char *buf, uptr bufsize) {
100d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov  return (uptr)syscall(__NR_readlink, path, buf, bufsize);
101d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov}
102d1b8f588d6b712b6ff2b3d58c73d71614f520122Alexey Samsonov
1030969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonovint internal_sched_yield() {
1040969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov  return syscall(__NR_sched_yield);
1050969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov}
1060969bcf2c936126b1f6e636b978aade8fc207437Alexey Samsonov
107e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_common.h
10893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonovbool FileExists(const char *filename) {
1099d0dbbaf33e5c2fe280f141e30be497d62b703a8Kostya Serebryany#if SANITIZER_LINUX_USES_64BIT_SYSCALLS
11093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat st;
11193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  if (syscall(__NR_stat, filename, &st))
11293b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
11393b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#else
11493b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  struct stat64 st;
11593b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  if (syscall(__NR_stat64, filename, &st))
11693b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov    return false;
11793b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov#endif
11893b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  // Sanity check: filename is a regular file.
11993b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov  return S_ISREG(st.st_mode);
12093b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov}
12193b4cafd631b661b4b612ccdc0938f7f1e1c86d6Alexey Samsonov
122e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukovuptr GetTid() {
123e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov  return syscall(__NR_gettid);
124e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov}
125e0023f74ea88efee329f68391b70f8adc6b21617Dmitry Vyukov
126ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonovvoid GetThreadStackTopAndBottom(bool at_initialization, uptr *stack_top,
127e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov                                uptr *stack_bottom) {
128e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  static const uptr kMaxThreadStackSize = 256 * (1 << 20);  // 256M
129e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_top);
130e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stack_bottom);
131ed996f79710f532bf231537e44d5c8c9c9d57e8dAlexey Samsonov  if (at_initialization) {
132e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // This is the main thread. Libpthread may not be initialized yet.
133e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    struct rlimit rl;
1346985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany    CHECK_EQ(getrlimit(RLIMIT_STACK, &rl), 0);
135e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
136e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Find the mapping that contains a stack variable.
137e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov    MemoryMappingLayout proc_maps;
138e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr start, end, offset;
139e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr prev_end = 0;
140e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    while (proc_maps.Next(&start, &end, &offset, 0, 0)) {
141e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      if ((uptr)&rl < end)
142e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov        break;
143e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      prev_end = end;
144e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    }
145e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    CHECK((uptr)&rl >= start && (uptr)&rl < end);
146e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
147e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Get stacksize from rlimit, but clip it so that it does not overlap
148e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // with other mappings.
149e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    uptr stacksize = rl.rlim_cur;
150e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    if (stacksize > end - prev_end)
151e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      stacksize = end - prev_end;
152e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // When running with unlimited stack size, we still want to set some limit.
153e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // The unlimited stack size is caused by 'ulimit -s unlimited'.
154e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    // Also, for some reason, GNU make spawns subprocesses with unlimited stack.
155e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    if (stacksize > kMaxThreadStackSize)
156e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov      stacksize = kMaxThreadStackSize;
157e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    *stack_top = end;
158e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    *stack_bottom = end - stacksize;
159e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov    return;
160e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  }
161e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_t attr;
1626985085c4860bf945358f227ddba26511ae770e9Kostya Serebryany  CHECK_EQ(pthread_getattr_np(pthread_self(), &attr), 0);
163e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  uptr stacksize = 0;
164e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  void *stackaddr = 0;
165e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_getstack(&attr, &stackaddr, (size_t*)&stacksize);
166e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  pthread_attr_destroy(&attr);
167e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
168e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_top = (uptr)stackaddr + stacksize;
169e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  *stack_bottom = (uptr)stackaddr;
170e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov  CHECK(stacksize < kMaxThreadStackSize);  // Sanity check.
171e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov}
172e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov
1733dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// Like getenv, but reads env directly from /proc and does not use libc.
1743dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov// This function should be called first inside __asan_init.
1753dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonovconst char *GetEnv(const char *name) {
1763dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static char *environ;
1773dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static uptr len;
1783dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  static bool inited;
1793dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!inited) {
1803dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    inited = true;
1813dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    uptr environ_size;
1823dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    len = ReadFileToBuffer("/proc/self/environ",
1833dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov                           &environ, &environ_size, 1 << 26);
1843dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
1853dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  if (!environ || len == 0) return 0;
1863dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  uptr namelen = internal_strlen(name);
1873dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  const char *p = environ;
1883dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  while (*p != '\0') {  // will happen at the \0\0 that terminates the buffer
1893dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    // proc file has the format NAME=value\0NAME=value\0NAME=value\0...
1903dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    const char* endp =
1913dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov        (char*)internal_memchr(p, '\0', len - (p - environ));
1923dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    if (endp == 0)  // this entry isn't NUL terminated
1933dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return 0;
1943dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=')  // Match.
1953dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov      return p + namelen + 1;  // point after =
1963dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov    p = endp + 1;
1973dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  }
1983dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov  return 0;  // Not found.
1993dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov}
2003dbeabb3446f203156ae03d957de9bdf50933ae4Alexey Samsonov
201d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonovvoid ReExec() {
202d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  static const int kMaxArgv = 100;
203d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  InternalScopedBuffer<char*> argv(kMaxArgv + 1);
204d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  static char *buff;
205d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  uptr buff_size = 0;
206d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  ReadFileToBuffer("/proc/self/cmdline", &buff, &buff_size, 1024 * 1024);
207d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  argv[0] = buff;
208d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  int argc, i;
209d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  for (argc = 1, i = 1; ; i++) {
210d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    if (buff[i] == 0) {
211d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      if (buff[i+1] == 0) break;
212d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      argv[argc] = &buff[i+1];
213d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      CHECK_LE(argc, kMaxArgv);  // FIXME: make this more flexible.
214d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov      argc++;
215d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov    }
216d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  }
217d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  argv[argc] = 0;
218d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov  execv(argv[0], argv.data());
219d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov}
220d7e5bb4043adf4756e6f8cfe0f5a3165b185474dAlexey Samsonov
22125742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenkovoid PrepareForSandboxing() {
22225742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // Some kinds of sandboxes may forbid filesystem access, so we won't be able
22325742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // to read the file mappings from /proc/self/maps. Luckily, neither the
22425742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // process will be able to load additional libraries, so it's fine to use the
22525742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  // cached mappings.
22625742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko  MemoryMappingLayout::CacheMemoryMappings();
22725742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko}
22825742574510cfb41b97e32f63f107fbb9b328d13Alexander Potapenko
229e5931fd7d2a74fd7fb60bd8d7f644cca51a24364Alexey Samsonov// ----------------- sanitizer_procmaps.h
230286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov// Linker initialized.
231286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry VyukovProcSelfMapsBuff MemoryMappingLayout::cached_proc_self_maps_;
232ad91267d45fef531c1082ab7974e4cc78aba5280Alexander PotapenkoStaticSpinMutex MemoryMappingLayout::cache_lock_;  // Linker initialized.
23393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
234e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::MemoryMappingLayout() {
235ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  proc_self_maps_.len =
236ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      ReadFileToBuffer("/proc/self/maps", &proc_self_maps_.data,
237ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                       &proc_self_maps_.mmaped_size, 1 << 26);
238ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (proc_self_maps_.mmaped_size == 0) {
23993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko    LoadFromCache();
240ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    CHECK_GT(proc_self_maps_.len, 0);
24193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
242ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  // internal_write(2, proc_self_maps_.data, proc_self_maps_.len);
2436895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  Reset();
24493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // FIXME: in the future we may want to cache the mappings on demand only.
24593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  CacheMemoryMappings();
2466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
248e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey SamsonovMemoryMappingLayout::~MemoryMappingLayout() {
2497385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  // Only unmap the buffer if it is different from the cached one. Otherwise
2507385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  // it will be unmapped when the cache is refreshed.
2517385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  if (proc_self_maps_.data != cached_proc_self_maps_.data) {
2527385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko    UnmapOrDie(proc_self_maps_.data, proc_self_maps_.mmaped_size);
2537385f8b8b8723064910cf9737dc929e90aeac548Alexander Potapenko  }
2546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
256e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovvoid MemoryMappingLayout::Reset() {
257ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  current_ = proc_self_maps_.data;
2586895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
2596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
26093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko// static
26193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::CacheMemoryMappings() {
26293da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  SpinMutexLock l(&cache_lock_);
26393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  // Don't invalidate the cache if the mappings are unavailable.
264ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  ProcSelfMapsBuff old_proc_self_maps;
265ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  old_proc_self_maps = cached_proc_self_maps_;
266ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  cached_proc_self_maps_.len =
267ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      ReadFileToBuffer("/proc/self/maps", &cached_proc_self_maps_.data,
268ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                       &cached_proc_self_maps_.mmaped_size, 1 << 26);
269ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (cached_proc_self_maps_.mmaped_size == 0) {
270ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    cached_proc_self_maps_ = old_proc_self_maps;
27193da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  } else {
272ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko    if (old_proc_self_maps.mmaped_size) {
273ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko      UnmapOrDie(old_proc_self_maps.data,
274ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko                 old_proc_self_maps.mmaped_size);
27593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko    }
27693da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
27793da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
27893da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
27993da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenkovoid MemoryMappingLayout::LoadFromCache() {
28093da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  SpinMutexLock l(&cache_lock_);
281ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  if (cached_proc_self_maps_.data) {
282286dd3f8afe6700e5dd9b0bdb7afd23121c98c12Dmitry Vyukov    proc_self_maps_ = cached_proc_self_maps_;
28393da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko  }
28493da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko}
28593da8b6a5e0ed2ca621897504c5d06449b3d7077Alexander Potapenko
286a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany// Parse a hex value in str and update str.
287a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic uptr ParseHex(char **str) {
288a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  uptr x = 0;
289a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  char *s;
290a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  for (s = *str; ; s++) {
291a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    char c = *s;
292a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    uptr v = 0;
293a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    if (c >= '0' && c <= '9')
294a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - '0';
295a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else if (c >= 'a' && c <= 'f')
296a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - 'a' + 10;
297a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else if (c >= 'A' && c <= 'F')
298a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      v = c - 'A' + 10;
299a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    else
300a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany      break;
301a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    x = x * 16 + v;
302a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  }
303a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *str = s;
304a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return x;
305a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
306a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
307a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsOnOf(char c, char c1, char c2) {
308a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return c == c1 || c == c2;
309a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
310a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
311a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryanystatic bool IsDecimal(char c) {
312a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  return c >= '0' && c <= '9';
313a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany}
314a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany
315e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::Next(uptr *start, uptr *end, uptr *offset,
316e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                               char filename[], uptr filename_size) {
317ad91267d45fef531c1082ab7974e4cc78aba5280Alexander Potapenko  char *last = proc_self_maps_.data + proc_self_maps_.len;
3186895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (current_ >= last) return false;
3196895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr dummy;
3206895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!start) start = &dummy;
3216895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!end) end = &dummy;
3226895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (!offset) offset = &dummy;
3236895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  char *next_line = (char*)internal_memchr(current_, '\n', last - current_);
3246895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (next_line == 0)
3256895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    next_line = last;
326a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  // Example: 08048000-08056000 r-xp 00000000 03:0c 64593   /foo/bar
327a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *start = ParseHex(&current_);
328bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, '-');
329a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *end = ParseHex(&current_);
330bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
331a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  CHECK(IsOnOf(*current_++, '-', 'r'));
332a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  CHECK(IsOnOf(*current_++, '-', 'w'));
333a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  CHECK(IsOnOf(*current_++, '-', 'x'));
334a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  CHECK(IsOnOf(*current_++, 's', 'p'));
335bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
336a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  *offset = ParseHex(&current_);
337bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
338a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  ParseHex(&current_);
339bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ':');
340a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  ParseHex(&current_);
341bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
342a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany  while (IsDecimal(*current_))
343a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany    current_++;
344bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany  CHECK_EQ(*current_++, ' ');
3456895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Skip spaces.
3466895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line && *current_ == ' ')
3476895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
3486895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  // Fill in the filename.
3496895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  uptr i = 0;
3506895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  while (current_ < next_line) {
3516895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    if (filename && i < filename_size - 1)
3526895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov      filename[i++] = *current_;
3536895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    current_++;
3546895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  }
3556895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  if (filename && i < filename_size)
3566895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov    filename[i] = 0;
3576895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  current_ = next_line + 1;
3586895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return true;
3596895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3606895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
361e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov// Gets the object name and the offset by walking MemoryMappingLayout.
362e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonovbool MemoryMappingLayout::GetObjectNameAndOffset(uptr addr, uptr *offset,
363e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 char filename[],
364e1f5dac9296df08ff83ae5fca51ce4da995b55cfAlexey Samsonov                                                 uptr filename_size) {
3656895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov  return IterateForObjectNameAndOffset(addr, offset, filename, filename_size);
3666895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov}
3676895adc39c4e09371154c8037366ad4464163ed0Alexey Samsonov
368dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerSetThreadName(const char *name) {
3691ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov  return 0 == prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0);  // NOLINT
370dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany}
371dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
372dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryanybool SanitizerGetThreadName(char *name, int max_len) {
373dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  char buff[17];
3741ec519c604021162de8bdb8d433fbad1c5033200Dmitry Vyukov  if (prctl(PR_GET_NAME, (unsigned long)buff, 0, 0, 0))  // NOLINT
375dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany    return false;
376dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  internal_strncpy(name, buff, max_len);
377dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  name[max_len] = 0;
378dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany  return true;
379dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany}
380dddb18b7be36fe1843c8b98a8d9d7614aef5ce8dKostya Serebryany
381ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov}  // namespace __sanitizer
382ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov
383ae4d9caa4f47fa6abcd641719e9f520622940c17Alexey Samsonov#endif  // __linux__
384