]> git.proxmox.com Git - rustc.git/blob - src/libcompiler_builtins/compiler-rt/lib/asan/asan_linux.cc
New upstream version 1.25.0+dfsg1
[rustc.git] / src / libcompiler_builtins / compiler-rt / lib / asan / asan_linux.cc
1 //===-- 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 //===----------------------------------------------------------------------===//
14
15 #include "sanitizer_common/sanitizer_platform.h"
16 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \
17 SANITIZER_SOLARIS
18
19 #include "asan_interceptors.h"
20 #include "asan_internal.h"
21 #include "asan_premap_shadow.h"
22 #include "asan_thread.h"
23 #include "sanitizer_common/sanitizer_flags.h"
24 #include "sanitizer_common/sanitizer_freebsd.h"
25 #include "sanitizer_common/sanitizer_libc.h"
26 #include "sanitizer_common/sanitizer_procmaps.h"
27
28 #include <sys/time.h>
29 #include <sys/resource.h>
30 #include <sys/mman.h>
31 #include <sys/syscall.h>
32 #include <sys/types.h>
33 #include <dlfcn.h>
34 #include <fcntl.h>
35 #include <pthread.h>
36 #include <stdio.h>
37 #include <unistd.h>
38 #include <unwind.h>
39
40 #if SANITIZER_FREEBSD
41 #include <sys/link_elf.h>
42 #endif
43
44 #if SANITIZER_SOLARIS
45 #include <link.h>
46 #endif
47
48 #if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS
49 #include <ucontext.h>
50 extern "C" void* _DYNAMIC;
51 #elif SANITIZER_NETBSD
52 #include <link_elf.h>
53 #include <ucontext.h>
54 extern Elf_Dyn _DYNAMIC;
55 #else
56 #include <sys/ucontext.h>
57 #include <link.h>
58 #endif
59
60 // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in
61 // 32-bit mode.
62 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \
63 __FreeBSD_version <= 902001 // v9.2
64 #define ucontext_t xucontext_t
65 #endif
66
67 typedef enum {
68 ASAN_RT_VERSION_UNDEFINED = 0,
69 ASAN_RT_VERSION_DYNAMIC,
70 ASAN_RT_VERSION_STATIC,
71 } asan_rt_version_t;
72
73 // FIXME: perhaps also store abi version here?
74 extern "C" {
75 SANITIZER_INTERFACE_ATTRIBUTE
76 asan_rt_version_t __asan_rt_version;
77 }
78
79 namespace __asan {
80
81 void InitializePlatformInterceptors() {}
82 void InitializePlatformExceptionHandlers() {}
83 bool IsSystemHeapAddress (uptr addr) { return false; }
84
85 void *AsanDoesNotSupportStaticLinkage() {
86 // This will fail to link with -static.
87 return &_DYNAMIC; // defined in link.h
88 }
89
90 static void UnmapFromTo(uptr from, uptr to) {
91 CHECK(to >= from);
92 if (to == from) return;
93 uptr res = internal_munmap(reinterpret_cast<void *>(from), to - from);
94 if (UNLIKELY(internal_iserror(res))) {
95 Report(
96 "ERROR: AddresSanitizer failed to unmap 0x%zx (%zd) bytes at address "
97 "%p\n",
98 to - from, to - from, from);
99 CHECK("unable to unmap" && 0);
100 }
101 }
102
103 #if ASAN_PREMAP_SHADOW
104 uptr FindPremappedShadowStart() {
105 uptr granularity = GetMmapGranularity();
106 uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow);
107 uptr premap_shadow_size = PremapShadowSize();
108 uptr shadow_size = RoundUpTo(kHighShadowEnd, granularity);
109 // We may have mapped too much. Release extra memory.
110 UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size);
111 return shadow_start;
112 }
113 #endif
114
115 uptr FindDynamicShadowStart() {
116 #if ASAN_PREMAP_SHADOW
117 if (!PremapShadowFailed())
118 return FindPremappedShadowStart();
119 #endif
120
121 uptr granularity = GetMmapGranularity();
122 uptr alignment = granularity * 8;
123 uptr left_padding = granularity;
124 uptr shadow_size = RoundUpTo(kHighShadowEnd, granularity);
125 uptr map_size = shadow_size + left_padding + alignment;
126
127 uptr map_start = (uptr)MmapNoAccess(map_size);
128 CHECK_NE(map_start, ~(uptr)0);
129
130 uptr shadow_start = RoundUpTo(map_start + left_padding, alignment);
131 UnmapFromTo(map_start, shadow_start - left_padding);
132 UnmapFromTo(shadow_start + shadow_size, map_start + map_size);
133
134 return shadow_start;
135 }
136
137 void AsanApplyToGlobals(globals_op_fptr op, const void *needle) {
138 UNIMPLEMENTED();
139 }
140
141 #if SANITIZER_ANDROID
142 // FIXME: should we do anything for Android?
143 void AsanCheckDynamicRTPrereqs() {}
144 void AsanCheckIncompatibleRT() {}
145 #else
146 static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size,
147 void *data) {
148 VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n",
149 info->dlpi_name, info->dlpi_addr);
150
151 // Continue until the first dynamic library is found
152 if (!info->dlpi_name || info->dlpi_name[0] == 0)
153 return 0;
154
155 // Ignore vDSO
156 if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0)
157 return 0;
158
159 #if SANITIZER_FREEBSD || SANITIZER_NETBSD
160 // Ignore first entry (the main program)
161 char **p = (char **)data;
162 if (!(*p)) {
163 *p = (char *)-1;
164 return 0;
165 }
166 #endif
167
168 #if SANITIZER_SOLARIS
169 // Ignore executable on Solaris
170 if (info->dlpi_addr == 0)
171 return 0;
172 #endif
173
174 *(const char **)data = info->dlpi_name;
175 return 1;
176 }
177
178 static bool IsDynamicRTName(const char *libname) {
179 return internal_strstr(libname, "libclang_rt.asan") ||
180 internal_strstr(libname, "libasan.so");
181 }
182
183 static void ReportIncompatibleRT() {
184 Report("Your application is linked against incompatible ASan runtimes.\n");
185 Die();
186 }
187
188 void AsanCheckDynamicRTPrereqs() {
189 if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order)
190 return;
191
192 // Ensure that dynamic RT is the first DSO in the list
193 const char *first_dso_name = nullptr;
194 dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name);
195 if (first_dso_name && !IsDynamicRTName(first_dso_name)) {
196 Report("ASan runtime does not come first in initial library list; "
197 "you should either link runtime to your application or "
198 "manually preload it with LD_PRELOAD.\n");
199 Die();
200 }
201 }
202
203 void AsanCheckIncompatibleRT() {
204 if (ASAN_DYNAMIC) {
205 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
206 __asan_rt_version = ASAN_RT_VERSION_DYNAMIC;
207 } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) {
208 ReportIncompatibleRT();
209 }
210 } else {
211 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) {
212 // Ensure that dynamic runtime is not present. We should detect it
213 // as early as possible, otherwise ASan interceptors could bind to
214 // the functions in dynamic ASan runtime instead of the functions in
215 // system libraries, causing crashes later in ASan initialization.
216 MemoryMappingLayout proc_maps(/*cache_enabled*/true);
217 char filename[128];
218 MemoryMappedSegment segment(filename, sizeof(filename));
219 while (proc_maps.Next(&segment)) {
220 if (IsDynamicRTName(segment.filename)) {
221 Report("Your application is linked against "
222 "incompatible ASan runtimes.\n");
223 Die();
224 }
225 }
226 __asan_rt_version = ASAN_RT_VERSION_STATIC;
227 } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) {
228 ReportIncompatibleRT();
229 }
230 }
231 }
232 #endif // SANITIZER_ANDROID
233
234 #if !SANITIZER_ANDROID
235 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
236 ucontext_t *ucp = (ucontext_t*)context;
237 *stack = (uptr)ucp->uc_stack.ss_sp;
238 *ssize = ucp->uc_stack.ss_size;
239 }
240 #else
241 void ReadContextStack(void *context, uptr *stack, uptr *ssize) {
242 UNIMPLEMENTED();
243 }
244 #endif
245
246 void *AsanDlSymNext(const char *sym) {
247 return dlsym(RTLD_NEXT, sym);
248 }
249
250 } // namespace __asan
251
252 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD ||
253 // SANITIZER_SOLARIS