asan_linux.cc revision ef14ff6512d7b2e20aa3206dff820b5f90285420
11e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===-- asan_linux.cc -----------------------------------------------------===// 21e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 31e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// The LLVM Compiler Infrastructure 41e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 51e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is distributed under the University of Illinois Open Source 61e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// License. See LICENSE.TXT for details. 71e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 81e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 91e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 101e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// This file is a part of AddressSanitizer, an address sanity checker. 111e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// 121e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany// Linux-specific details. 131e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany//===----------------------------------------------------------------------===// 14d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#ifdef __linux__ 151e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 16df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_interceptors.h" 171e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include "asan_internal.h" 18df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include "asan_procmaps.h" 19c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include "asan_thread.h" 201e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 21c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/time.h> 22c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <sys/resource.h> 231e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/mman.h> 241e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <sys/syscall.h> 25de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <sys/types.h> 26de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany#include <fcntl.h> 27efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany#include <link.h> 28c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany#include <pthread.h> 29df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany#include <stdio.h> 301e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany#include <unistd.h> 311e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 321e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanynamespace __asan { 331e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 341e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryanyvoid *AsanDoesNotSupportStaticLinkage() { 351e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany // This will fail to link with -static. 36efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return &_DYNAMIC; // defined in link.h 371e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 381e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 39a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanystatic void *asan_mmap(void *addr, size_t length, int prot, int flags, 401e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany int fd, uint64_t offset) { 411e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# if __WORDSIZE == 64 42de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap, addr, length, prot, flags, fd, offset); 431e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# else 44de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (void *)syscall(__NR_mmap2, addr, length, prot, flags, fd, offset); 451e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany# endif 461e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 471e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 48de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid *AsanMmapSomewhereOrDie(size_t size, const char *mem_type) { 49de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany size = RoundUpTo(size, kPageSize); 50de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany void *res = asan_mmap(0, size, 51de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany PROT_READ | PROT_WRITE, 52de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany MAP_PRIVATE | MAP_ANON, -1, 0); 53de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res == (void*)-1) { 54de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany OutOfMemoryMessageAndDie(mem_type, size); 55de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 56de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return res; 57de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 58de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 59a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedNoReserve(uintptr_t fixed_addr, size_t size) { 60a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 61a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 62a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 63a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 64a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 65a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 66a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMmapFixedReserve(uintptr_t fixed_addr, size_t size) { 67a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 68a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_READ | PROT_WRITE, 69a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED, 70a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 71a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 72a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 73a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryanyvoid *AsanMprotect(uintptr_t fixed_addr, size_t size) { 74a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany return asan_mmap((void*)fixed_addr, size, 75a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany PROT_NONE, 76a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany MAP_PRIVATE | MAP_ANON | MAP_FIXED | MAP_NORESERVE, 77a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 0, 0); 78a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany} 79a874fe5b5d67152e4e737498d532eec80940bdcdKostya Serebryany 80de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyvoid AsanUnmapOrDie(void *addr, size_t size) { 81de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (!addr || !size) return; 82de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany int res = syscall(__NR_munmap, addr, size); 83de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany if (res != 0) { 84de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany Report("Failed to unmap\n"); 85de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany ASAN_DIE; 86de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany } 87de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 88de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 89de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyssize_t AsanWrite(int fd, const void *buf, size_t count) { 90de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (ssize_t)syscall(__NR_write, fd, buf, count); 91de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 92de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 93de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanOpenReadonly(const char* filename) { 94de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return open(filename, O_RDONLY); 95de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 96de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 97de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyssize_t AsanRead(int fd, void *buf, size_t count) { 98de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return (ssize_t)syscall(__NR_read, fd, buf, count); 99de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany} 100de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany 101de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryanyint AsanClose(int fd) { 102de496f451bce322b6cde100456591f1f50ab3477Kostya Serebryany return close(fd); 1031e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} 1041e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany 105df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::AsanProcMaps() { 106df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany proc_self_maps_buff_len_ = 107df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany ReadFileToBuffer("/proc/self/maps", &proc_self_maps_buff_, 108df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &proc_self_maps_buff_mmaped_size_, 1 << 20); 109df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany CHECK(proc_self_maps_buff_len_ > 0); 110df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // AsanWrite(2, proc_self_maps_buff_, proc_self_maps_buff_len_); 111df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany Reset(); 112df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 113df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 114df499b44de81fc757a789878f07fcaf19ebb0016Kostya SerebryanyAsanProcMaps::~AsanProcMaps() { 115df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany AsanUnmapOrDie(proc_self_maps_buff_, proc_self_maps_buff_mmaped_size_); 116df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 117df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 118df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryanyvoid AsanProcMaps::Reset() { 119df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = proc_self_maps_buff_; 120df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 121df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 122efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::Next(uintptr_t *start, uintptr_t *end, 123efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t *offset, char filename[], 124df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t filename_size) { 125df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *last = proc_self_maps_buff_ + proc_self_maps_buff_len_; 126df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (current_ >= last) return false; 127df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int consumed = 0; 128df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char flags[10]; 129df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany int major, minor; 130efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t inode; 131df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany char *next_line = (char*)internal_memchr(current_, '\n', last - current_); 132df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (next_line == NULL) 133df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany next_line = last; 134df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (SScanf(current_, 135efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany "%lx-%lx %4s %lx %x:%x %ld %n", 136df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany start, end, flags, offset, &major, &minor, 137df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany &inode, &consumed) != 7) 138df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return false; 139df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ += consumed; 140df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Skip spaces. 141df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line && *current_ == ' ') 142df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 143df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany // Fill in the filename. 144df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany size_t i = 0; 145df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany while (current_ < next_line) { 146df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size - 1) 147df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i++] = *current_; 148df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_++; 149df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany } 150df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany if (filename && i < filename_size) 151df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany filename[i] = 0; 152df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany current_ = next_line + 1; 153df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany return true; 154df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany} 155df499b44de81fc757a789878f07fcaf19ebb0016Kostya Serebryany 156efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystruct DlIterateData { 157efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count; 158efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t addr; 159efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t offset; 160efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char *filename; 161efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size; 162efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany}; 163efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 164efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanystatic int dl_iterate_phdr_callback(struct dl_phdr_info *info, 165efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t size, void *raw_data) { 166efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData *data = (DlIterateData*)raw_data; 167efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany int count = data->count++; 168efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (info->dlpi_addr > data->addr) 169efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 0; 170efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (count == 0) { 171efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // The first item (the main executable) does not have a so name, 172efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany // but we can just read it from /proc/self/exe. 173efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany ssize_t path_len = readlink("/proc/self/exe", 174efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->filename, data->filename_size - 1); 175efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->filename[path_len] = 0; 176efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } else { 177efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany CHECK(info->dlpi_name); 178efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany real_strncpy(data->filename, info->dlpi_name, data->filename_size); 179efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 180efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data->offset = data->addr - info->dlpi_addr; 181efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return 1; 182efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 183efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 184efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany// Gets the object name and the offset using dl_iterate_phdr. 185efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryanybool AsanProcMaps::GetObjectNameAndOffset(uintptr_t addr, uintptr_t *offset, 186efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany char filename[], 187efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany size_t filename_size) { 188efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany DlIterateData data; 189efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.count = 0; 190efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.addr = addr; 191efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename = filename; 192efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany data.filename_size = filename_size; 193efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany if (dl_iterate_phdr(dl_iterate_phdr_callback, &data)) { 194efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany *offset = data.offset; 195efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return true; 196efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany } 197efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany return false; 198efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany} 199efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany 200c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryanyvoid AsanThread::SetThreadStackTopAndBottom() { 201c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (tid() == 0) { 202c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // This is the main thread. Libpthread may not be initialized yet. 203c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany struct rlimit rl; 204c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(getrlimit(RLIMIT_STACK, &rl) == 0); 205c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 206c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Find the mapping that contains a stack variable. 207c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany AsanProcMaps proc_maps; 208efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t start, end, offset; 209efb3fa36cf421c346e8e54054cdae4fd798edab7Kostya Serebryany uintptr_t prev_end = 0; 210c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany while (proc_maps.Next(&start, &end, &offset, NULL, 0)) { 211c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if ((uintptr_t)&rl < end) 212c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany break; 213c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany prev_end = end; 214c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 215c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK((uintptr_t)&rl >= start && (uintptr_t)&rl < end); 216c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 217c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Get stacksize from rlimit, but clip it so that it does not overlap 218c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // with other mappings. 219c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = rl.rlim_cur; 220c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > end - prev_end) 221c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = end - prev_end; 222c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) 223c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stacksize = kMaxThreadStackSize; 224c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = end; 225c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = end - stacksize; 226c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&rl)); 227c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany return; 228c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 229c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_t attr; 230c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(pthread_getattr_np(pthread_self(), &attr) == 0); 231c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany size_t stacksize = 0; 232c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany void *stackaddr = NULL; 233c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_getstack(&attr, &stackaddr, &stacksize); 234c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany pthread_attr_destroy(&attr); 235c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 236c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_top_ = (uintptr_t)stackaddr + stacksize; 237c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = (uintptr_t)stackaddr; 238c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // When running with unlimited stack size, we still want to set some limit. 239c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // The unlimited stack size is caused by 'ulimit -s unlimited'. 240c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany // Also, for some reason, GNU make spawns subrocesses with unlimited stack. 241c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany if (stacksize > kMaxThreadStackSize) { 242c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany stack_bottom_ = stack_top_ - kMaxThreadStackSize; 243c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany } 244c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany CHECK(AddrIsInStack((uintptr_t)&attr)); 245c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany} 246c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 247ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryanyvoid AsanDisableCoreDumper() { 248ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany struct rlimit nocore; 249ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany nocore.rlim_cur = 0; 250ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany nocore.rlim_max = 0; 251ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany setrlimit(RLIMIT_CORE, &nocore); 252ef14ff6512d7b2e20aa3206dff820b5f90285420Kostya Serebryany} 253c549dd7b5fa5fb97270f57067797224cee0429f2Kostya Serebryany 2541e172b4bdec57329bf904f063a29f99cddf2d85fKostya Serebryany} // namespace __asan 255d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany 256d6567c5166412f6acdde851e767c26f332d51d3dKostya Serebryany#endif // __linux__ 257