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