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(¤t_); 328bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, '-'); 329a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany *end = ParseHex(¤t_); 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(¤t_); 337bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ' '); 338a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 339bb8a9511bc748d6a4fd601d713bda584ef7bb772Kostya Serebryany CHECK_EQ(*current_++, ':'); 340a4e4744778e6b3067f5cf223cf28bb586c1ecf67Kostya Serebryany ParseHex(¤t_); 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