blob: 625f32d408dfacfc11471024a2497f23fdfcf1b6 [file] [log] [blame]
Kostya Serebryany019b76f2011-11-30 01:07:02 +00001//===-- asan_linux.cc -----------------------------------------------------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This file is a part of AddressSanitizer, an address sanity checker.
11//
12// Linux-specific details.
13//===----------------------------------------------------------------------===//
Evgeniy Stepanov0af67232013-03-19 14:33:38 +000014
15#include "sanitizer_common/sanitizer_platform.h"
Kamil Rytarowski271018d2017-12-14 20:14:29 +000016#if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
17 SANITIZER_SOLARIS
Kostya Serebryany019b76f2011-11-30 01:07:02 +000018
Kostya Serebryanycd271f52012-01-05 00:44:33 +000019#include "asan_interceptors.h"
Kostya Serebryany019b76f2011-11-30 01:07:02 +000020#include "asan_internal.h"
Evgeniy Stepanov8e7018d2017-11-20 17:41:57 +000021#include "asan_premap_shadow.h"
Kostya Serebryany78d87d32012-01-05 01:07:27 +000022#include "asan_thread.h"
Alexey Samsonov3d9adc02014-03-04 13:12:25 +000023#include "sanitizer_common/sanitizer_flags.h"
Viktor Kutuzov1f386f02014-06-15 13:56:28 +000024#include "sanitizer_common/sanitizer_freebsd.h"
Alexey Samsonov2c5fc3b2012-06-04 14:27:50 +000025#include "sanitizer_common/sanitizer_libc.h"
Alexey Samsonov28a98952012-06-07 06:15:12 +000026#include "sanitizer_common/sanitizer_procmaps.h"
Kostya Serebryany019b76f2011-11-30 01:07:02 +000027
Kostya Serebryany78d87d32012-01-05 01:07:27 +000028#include <sys/time.h>
29#include <sys/resource.h>
Kostya Serebryany019b76f2011-11-30 01:07:02 +000030#include <sys/mman.h>
31#include <sys/syscall.h>
Kostya Serebryany6c4bd802011-12-28 22:58:01 +000032#include <sys/types.h>
Evgeniy Stepanove5c34ac2014-06-06 10:57:21 +000033#include <dlfcn.h>
Kostya Serebryany6c4bd802011-12-28 22:58:01 +000034#include <fcntl.h>
Yvan Rouxcae49702018-02-07 18:27:25 +000035#include <limits.h>
Kostya Serebryany78d87d32012-01-05 01:07:27 +000036#include <pthread.h>
Kostya Serebryanycd271f52012-01-05 00:44:33 +000037#include <stdio.h>
Kostya Serebryany019b76f2011-11-30 01:07:02 +000038#include <unistd.h>
Evgeniy Stepanov84c44a82012-01-19 11:34:18 +000039#include <unwind.h>
Kostya Serebryany019b76f2011-11-30 01:07:02 +000040
Viktor Kutuzov82185a22014-04-09 13:37:19 +000041#if SANITIZER_FREEBSD
42#include <sys/link_elf.h>
43#endif
44
Kamil Rytarowski271018d2017-12-14 20:14:29 +000045#if SANITIZER_SOLARIS
46#include <link.h>
47#endif
48
49#if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
Evgeniy Stepanov6db97e82014-02-10 13:34:43 +000050#include <ucontext.h>
Alexey Samsonov56b6ee92014-04-01 13:16:30 +000051extern "C" void* _DYNAMIC;
Kamil Rytarowski4ad374e2017-08-10 18:51:51 +000052#elif SANITIZER_NETBSD
53#include <link_elf.h>
54#include <ucontext.h>
55extern Elf_Dyn _DYNAMIC;
Evgeniy Stepanov6db97e82014-02-10 13:34:43 +000056#else
Kostya Serebryany25d6c1b2012-01-06 19:11:09 +000057#include <sys/ucontext.h>
Alexey Samsonov56b6ee92014-04-01 13:16:30 +000058#include <link.h>
Kostya Serebryany25d6c1b2012-01-06 19:11:09 +000059#endif
60
Viktor Kutuzov1f386f02014-06-15 13:56:28 +000061// x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
62// 32-bit mode.
63#if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
64 __FreeBSD_version <= 902001 // v9.2
65#define ucontext_t xucontext_t
Viktor Kutuzovebb00e12014-03-12 12:44:36 +000066#endif
67
Alexey Samsonov56b6ee92014-04-01 13:16:30 +000068typedef enum {
69 ASAN_RT_VERSION_UNDEFINED = 0,
70 ASAN_RT_VERSION_DYNAMIC,
71 ASAN_RT_VERSION_STATIC,
72} asan_rt_version_t;
73
74// FIXME: perhaps also store abi version here?
75extern "C" {
76SANITIZER_INTERFACE_ATTRIBUTE
77asan_rt_version_t __asan_rt_version;
78}
Evgeniy Stepanov4cc26312012-03-26 09:48:41 +000079
Kostya Serebryany019b76f2011-11-30 01:07:02 +000080namespace __asan {
81
Timur Iskhodzhanov817ac722015-03-16 14:22:53 +000082void InitializePlatformInterceptors() {}
Etienne Bergeron1128db82016-07-11 21:40:59 +000083void InitializePlatformExceptionHandlers() {}
Etienne Bergeronfc68c2c2017-02-21 16:09:38 +000084bool IsSystemHeapAddress (uptr addr) { return false; }
Timur Iskhodzhanov817ac722015-03-16 14:22:53 +000085
Kostya Serebryany019b76f2011-11-30 01:07:02 +000086void *AsanDoesNotSupportStaticLinkage() {
87 // This will fail to link with -static.
Kostya Serebryany3b7fb102012-01-05 23:50:34 +000088 return &_DYNAMIC; // defined in link.h
Kostya Serebryany019b76f2011-11-30 01:07:02 +000089}
90
Evgeniy Stepanov8e7018d2017-11-20 17:41:57 +000091static void UnmapFromTo(uptr from, uptr to) {
92 CHECK(to >= from);
93 if (to == from) return;
94 uptr res = internal_munmap(reinterpret_cast<void *>(from), to - from);
95 if (UNLIKELY(internal_iserror(res))) {
96 Report(
97 "ERROR: AddresSanitizer failed to unmap 0x%zx (%zd) bytes at address "
98 "%p\n",
99 to - from, to - from, from);
100 CHECK("unable to unmap" && 0);
101 }
102}
103
104#if ASAN_PREMAP_SHADOW
105uptr FindPremappedShadowStart() {
106 uptr granularity = GetMmapGranularity();
107 uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
108 uptr premap_shadow_size = PremapShadowSize();
109 uptr shadow_size = RoundUpTo(kHighShadowEnd, granularity);
110 // We may have mapped too much. Release extra memory.
111 UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
112 return shadow_start;
113}
114#endif
115
Evgeniy Stepanov989299c2017-11-10 22:27:48 +0000116uptr FindDynamicShadowStart() {
Evgeniy Stepanov8e7018d2017-11-20 17:41:57 +0000117#if ASAN_PREMAP_SHADOW
118 if (!PremapShadowFailed())
119 return FindPremappedShadowStart();
120#endif
121
122 uptr granularity = GetMmapGranularity();
123 uptr alignment = granularity * 8;
124 uptr left_padding = granularity;
125 uptr shadow_size = RoundUpTo(kHighShadowEnd, granularity);
126 uptr map_size = shadow_size + left_padding + alignment;
127
128 uptr map_start = (uptr)MmapNoAccess(map_size);
129 CHECK_NE(map_start, ~(uptr)0);
130
131 uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
132 UnmapFromTo(map_start, shadow_start - left_padding);
133 UnmapFromTo(shadow_start + shadow_size, map_start + map_size);
134
135 return shadow_start;
Evgeniy Stepanov989299c2017-11-10 22:27:48 +0000136}
Kuba Mracekc1e903b2017-07-12 23:29:21 +0000137
Ryan Govostesdc91fe52016-03-28 20:28:17 +0000138void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
139 UNIMPLEMENTED();
140}
141
Alexey Samsonov2c66a222014-04-02 09:36:36 +0000142#if SANITIZER_ANDROID
143// FIXME: should we do anything for Android?
144void AsanCheckDynamicRTPrereqs() {}
145void AsanCheckIncompatibleRT() {}
146#else
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000147static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
148 void *data) {
Kamil Rytarowski271018d2017-12-14 20:14:29 +0000149 VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n",
150 info->dlpi_name, info->dlpi_addr);
151
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000152 // Continue until the first dynamic library is found
153 if (!info->dlpi_name || info->dlpi_name[0] == 0)
154 return 0;
155
Kostya Serebryany5181dd32014-06-02 10:39:40 +0000156 // Ignore vDSO
157 if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
158 return 0;
159
Dimitry Andric95af9e62017-10-24 19:45:59 +0000160#if SANITIZER_FREEBSD || SANITIZER_NETBSD
Kamil Rytarowski4ad374e2017-08-10 18:51:51 +0000161 // Ignore first entry (the main program)
162 char **p = (char **)data;
163 if (!(*p)) {
164 *p = (char *)-1;
165 return 0;
166 }
167#endif
168
Kamil Rytarowski271018d2017-12-14 20:14:29 +0000169#if SANITIZER_SOLARIS
170 // Ignore executable on Solaris
171 if (info->dlpi_addr == 0)
172 return 0;
173#endif
174
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000175 *(const char **)data = info->dlpi_name;
176 return 1;
177}
178
179static bool IsDynamicRTName(const char *libname) {
180 return internal_strstr(libname, "libclang_rt.asan") ||
181 internal_strstr(libname, "libasan.so");
182}
183
Alexey Samsonov11ff0a22014-04-02 13:09:22 +0000184static void ReportIncompatibleRT() {
185 Report("Your application is linked against incompatible ASan runtimes.\n");
186 Die();
187}
188
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000189void AsanCheckDynamicRTPrereqs() {
Maxim Ostapenkof73b73d2017-03-31 06:36:37 +0000190 if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
Yury Gribovc5243f02015-06-04 07:23:09 +0000191 return;
192
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000193 // Ensure that dynamic RT is the first DSO in the list
Vedant Kumar59ba7b82015-10-01 00:22:21 +0000194 const char *first_dso_name = nullptr;
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000195 dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
196 if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
197 Report("ASan runtime does not come first in initial library list; "
198 "you should either link runtime to your application or "
199 "manually preload it with LD_PRELOAD.\n");
200 Die();
201 }
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000202}
203
204void AsanCheckIncompatibleRT() {
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000205 if (ASAN_DYNAMIC) {
206 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
207 __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
208 } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
Alexey Samsonov11ff0a22014-04-02 13:09:22 +0000209 ReportIncompatibleRT();
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000210 }
211 } else {
Alexey Samsonov11ff0a22014-04-02 13:09:22 +0000212 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
213 // Ensure that dynamic runtime is not present. We should detect it
214 // as early as possible, otherwise ASan interceptors could bind to
215 // the functions in dynamic ASan runtime instead of the functions in
216 // system libraries, causing crashes later in ASan initialization.
217 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
Yvan Rouxcae49702018-02-07 18:27:25 +0000218 char filename[PATH_MAX];
Francis Riccif6a43292017-07-11 18:54:00 +0000219 MemoryMappedSegment segment(filename, sizeof(filename));
220 while (proc_maps.Next(&segment)) {
221 if (IsDynamicRTName(segment.filename)) {
Alexey Samsonov11ff0a22014-04-02 13:09:22 +0000222 Report("Your application is linked against "
223 "incompatible ASan runtimes.\n");
224 Die();
225 }
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000226 }
Alexey Samsonov11ff0a22014-04-02 13:09:22 +0000227 __asan_rt_version = ASAN_RT_VERSION_STATIC;
228 } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
229 ReportIncompatibleRT();
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000230 }
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000231 }
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000232}
Vedant Kumar59ba7b82015-10-01 00:22:21 +0000233#endif // SANITIZER_ANDROID
Alexey Samsonov56b6ee92014-04-01 13:16:30 +0000234
Evgeniy Stepanovd3b56602013-03-19 13:54:41 +0000235#if !SANITIZER_ANDROID
Alexey Samsonov4f1885a2013-01-17 15:45:28 +0000236void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
Alexey Samsonovaac36b32012-11-23 10:14:44 +0000237 ucontext_t *ucp = (ucontext_t*)context;
Alexey Samsonov4f1885a2013-01-17 15:45:28 +0000238 *stack = (uptr)ucp->uc_stack.ss_sp;
239 *ssize = ucp->uc_stack.ss_size;
Alexey Samsonovaac36b32012-11-23 10:14:44 +0000240}
241#else
Alexey Samsonov4f1885a2013-01-17 15:45:28 +0000242void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
Alexey Samsonov95856132013-01-18 09:20:06 +0000243 UNIMPLEMENTED();
Alexey Samsonovaac36b32012-11-23 10:14:44 +0000244}
245#endif
246
Evgeniy Stepanove5c34ac2014-06-06 10:57:21 +0000247void *AsanDlSymNext(const char *sym) {
248 return dlsym(RTLD_NEXT, sym);
249}
250
Vedant Kumar59ba7b82015-10-01 00:22:21 +0000251} // namespace __asan
Kostya Serebryany5dfa4da2011-12-01 21:40:52 +0000252
Kamil Rytarowski271018d2017-12-14 20:14:29 +0000253#endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
254 // SANITIZER_SOLARIS