File: | compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp |
Warning: | line 377, column 3 Undefined or garbage value returned to caller |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- sanitizer_linux.cpp -----------------------------------------------===// | |||
2 | // | |||
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. | |||
4 | // See https://llvm.org/LICENSE.txt for license information. | |||
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | |||
6 | // | |||
7 | //===----------------------------------------------------------------------===// | |||
8 | // | |||
9 | // This file is shared between AddressSanitizer and ThreadSanitizer | |||
10 | // run-time libraries and implements linux-specific functions from | |||
11 | // sanitizer_libc.h. | |||
12 | //===----------------------------------------------------------------------===// | |||
13 | ||||
14 | #include "sanitizer_platform.h" | |||
15 | ||||
16 | #if SANITIZER_FREEBSD0 || SANITIZER_LINUX1 || SANITIZER_NETBSD0 || \ | |||
17 | SANITIZER_SOLARIS0 | |||
18 | ||||
19 | #include "sanitizer_common.h" | |||
20 | #include "sanitizer_flags.h" | |||
21 | #include "sanitizer_getauxval.h" | |||
22 | #include "sanitizer_internal_defs.h" | |||
23 | #include "sanitizer_libc.h" | |||
24 | #include "sanitizer_linux.h" | |||
25 | #include "sanitizer_mutex.h" | |||
26 | #include "sanitizer_placement_new.h" | |||
27 | #include "sanitizer_procmaps.h" | |||
28 | ||||
29 | #if SANITIZER_LINUX1 && !SANITIZER_GO0 | |||
30 | #include <asm/param.h> | |||
31 | #endif | |||
32 | ||||
33 | // For mips64, syscall(__NR_stat) fills the buffer in the 'struct kernel_stat' | |||
34 | // format. Struct kernel_stat is defined as 'struct stat' in asm/stat.h. To | |||
35 | // access stat from asm/stat.h, without conflicting with definition in | |||
36 | // sys/stat.h, we use this trick. | |||
37 | #if defined(__mips64) | |||
38 | #include <asm/unistd.h> | |||
39 | #include <sys/types.h> | |||
40 | #define stat kernel_stat | |||
41 | #if SANITIZER_GO0 | |||
42 | #undef st_atimest_atim.tv_sec | |||
43 | #undef st_mtimest_mtim.tv_sec | |||
44 | #undef st_ctimest_ctim.tv_sec | |||
45 | #define st_atimest_atim.tv_sec st_atim | |||
46 | #define st_mtimest_mtim.tv_sec st_mtim | |||
47 | #define st_ctimest_ctim.tv_sec st_ctim | |||
48 | #endif | |||
49 | #include <asm/stat.h> | |||
50 | #undef stat | |||
51 | #endif | |||
52 | ||||
53 | #include <dlfcn.h> | |||
54 | #include <errno(*__errno_location ()).h> | |||
55 | #include <fcntl.h> | |||
56 | #include <link.h> | |||
57 | #include <pthread.h> | |||
58 | #include <sched.h> | |||
59 | #include <signal.h> | |||
60 | #include <sys/mman.h> | |||
61 | #include <sys/param.h> | |||
62 | #if !SANITIZER_SOLARIS0 | |||
63 | #include <sys/ptrace.h> | |||
64 | #endif | |||
65 | #include <sys/resource.h> | |||
66 | #include <sys/stat.h> | |||
67 | #include <sys/syscall.h> | |||
68 | #include <sys/time.h> | |||
69 | #include <sys/types.h> | |||
70 | #include <ucontext.h> | |||
71 | #include <unistd.h> | |||
72 | ||||
73 | #if SANITIZER_LINUX1 | |||
74 | #include <sys/utsname.h> | |||
75 | #endif | |||
76 | ||||
77 | #if SANITIZER_LINUX1 && !SANITIZER_ANDROID0 | |||
78 | #include <sys/personality.h> | |||
79 | #endif | |||
80 | ||||
81 | #if SANITIZER_FREEBSD0 | |||
82 | #include <sys/exec.h> | |||
83 | #include <sys/sysctl.h> | |||
84 | #include <machine/atomic.h> | |||
85 | extern "C" { | |||
86 | // <sys/umtx.h> must be included after <errno.h> and <sys/types.h> on | |||
87 | // FreeBSD 9.2 and 10.0. | |||
88 | #include <sys/umtx.h> | |||
89 | } | |||
90 | #include <sys/thr.h> | |||
91 | #endif // SANITIZER_FREEBSD | |||
92 | ||||
93 | #if SANITIZER_NETBSD0 | |||
94 | #include <limits.h> // For NAME_MAX | |||
95 | #include <sys/sysctl.h> | |||
96 | #include <sys/exec.h> | |||
97 | extern struct ps_strings *__ps_strings; | |||
98 | #endif // SANITIZER_NETBSD | |||
99 | ||||
100 | #if SANITIZER_SOLARIS0 | |||
101 | #include <stdlib.h> | |||
102 | #include <thread.h> | |||
103 | #define environ _environ | |||
104 | #endif | |||
105 | ||||
106 | extern char **environ; | |||
107 | ||||
108 | #if SANITIZER_LINUX1 | |||
109 | // <linux/time.h> | |||
110 | struct kernel_timeval { | |||
111 | long tv_sec; | |||
112 | long tv_usec; | |||
113 | }; | |||
114 | ||||
115 | // <linux/futex.h> is broken on some linux distributions. | |||
116 | const int FUTEX_WAIT = 0; | |||
117 | const int FUTEX_WAKE = 1; | |||
118 | const int FUTEX_PRIVATE_FLAG = 128; | |||
119 | const int FUTEX_WAIT_PRIVATE = FUTEX_WAIT | FUTEX_PRIVATE_FLAG; | |||
120 | const int FUTEX_WAKE_PRIVATE = FUTEX_WAKE | FUTEX_PRIVATE_FLAG; | |||
121 | #endif // SANITIZER_LINUX | |||
122 | ||||
123 | // Are we using 32-bit or 64-bit Linux syscalls? | |||
124 | // x32 (which defines __x86_64__) has SANITIZER_WORDSIZE == 32 | |||
125 | // but it still needs to use 64-bit syscalls. | |||
126 | #if SANITIZER_LINUX1 && (defined(__x86_64__1) || defined(__powerpc64__) || \ | |||
127 | SANITIZER_WORDSIZE64 == 64) | |||
128 | # define SANITIZER_LINUX_USES_64BIT_SYSCALLS1 1 | |||
129 | #else | |||
130 | # define SANITIZER_LINUX_USES_64BIT_SYSCALLS1 0 | |||
131 | #endif | |||
132 | ||||
133 | // Note : FreeBSD had implemented both | |||
134 | // Linux apis, available from | |||
135 | // future 12.x version most likely | |||
136 | #if SANITIZER_LINUX1 && defined(__NR_getrandom318) | |||
137 | # if !defined(GRND_NONBLOCK1) | |||
138 | # define GRND_NONBLOCK1 1 | |||
139 | # endif | |||
140 | # define SANITIZER_USE_GETRANDOM1 1 | |||
141 | #else | |||
142 | # define SANITIZER_USE_GETRANDOM1 0 | |||
143 | #endif // SANITIZER_LINUX && defined(__NR_getrandom) | |||
144 | ||||
145 | #if SANITIZER_FREEBSD0 && __FreeBSD_version >= 1200000 | |||
146 | # define SANITIZER_USE_GETENTROPY0 1 | |||
147 | #else | |||
148 | # define SANITIZER_USE_GETENTROPY0 0 | |||
149 | #endif | |||
150 | ||||
151 | namespace __sanitizer { | |||
152 | ||||
153 | #if SANITIZER_LINUX1 && defined(__x86_64__1) | |||
154 | #include "sanitizer_syscall_linux_x86_64.inc" | |||
155 | #elif SANITIZER_LINUX1 && SANITIZER_RISCV640 | |||
156 | #include "sanitizer_syscall_linux_riscv64.inc" | |||
157 | #elif SANITIZER_LINUX1 && defined(__aarch64__) | |||
158 | #include "sanitizer_syscall_linux_aarch64.inc" | |||
159 | #elif SANITIZER_LINUX1 && defined(__arm__) | |||
160 | #include "sanitizer_syscall_linux_arm.inc" | |||
161 | #else | |||
162 | #include "sanitizer_syscall_generic.inc" | |||
163 | #endif | |||
164 | ||||
165 | // --------------- sanitizer_libc.h | |||
166 | #if !SANITIZER_SOLARIS0 && !SANITIZER_NETBSD0 | |||
167 | #if !SANITIZER_S3900 | |||
168 | uptr internal_mmap(void *addr, uptr length, int prot, int flags, int fd, | |||
169 | u64 offset) { | |||
170 | #if SANITIZER_FREEBSD0 || SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||
171 | return internal_syscall(SYSCALL(mmap)9, (uptr)addr, length, prot, flags, fd, | |||
172 | offset); | |||
173 | #else | |||
174 | // mmap2 specifies file offset in 4096-byte units. | |||
175 | CHECK(IsAligned(offset, 4096))do { __sanitizer::u64 v1 = (__sanitizer::u64)((IsAligned(offset , 4096))); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 175, "(" "(IsAligned(offset, 4096))" ") " "!=" " (" "0" ")" , v1, v2); } while (false); | |||
176 | return internal_syscall(SYSCALL(mmap2)__NR_mmap2, addr, length, prot, flags, fd, | |||
177 | offset / 4096); | |||
178 | #endif | |||
179 | } | |||
180 | #endif // !SANITIZER_S390 | |||
181 | ||||
182 | uptr internal_munmap(void *addr, uptr length) { | |||
183 | return internal_syscall(SYSCALL(munmap)11, (uptr)addr, length); | |||
184 | } | |||
185 | ||||
186 | int internal_mprotect(void *addr, uptr length, int prot) { | |||
187 | return internal_syscall(SYSCALL(mprotect)10, (uptr)addr, length, prot); | |||
188 | } | |||
189 | ||||
190 | int internal_madvise(uptr addr, uptr length, int advice) { | |||
191 | return internal_syscall(SYSCALL(madvise)28, addr, length, advice); | |||
192 | } | |||
193 | ||||
194 | uptr internal_close(fd_t fd) { | |||
195 | return internal_syscall(SYSCALL(close)3, fd); | |||
196 | } | |||
197 | ||||
198 | uptr internal_open(const char *filename, int flags) { | |||
199 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
200 | return internal_syscall(SYSCALL(openat)257, AT_FDCWD-100, (uptr)filename, flags); | |||
201 | #else | |||
202 | return internal_syscall(SYSCALL(open)2, (uptr)filename, flags); | |||
203 | #endif | |||
204 | } | |||
205 | ||||
206 | uptr internal_open(const char *filename, int flags, u32 mode) { | |||
207 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
208 | return internal_syscall(SYSCALL(openat)257, AT_FDCWD-100, (uptr)filename, flags, | |||
209 | mode); | |||
210 | #else | |||
211 | return internal_syscall(SYSCALL(open)2, (uptr)filename, flags, mode); | |||
212 | #endif | |||
213 | } | |||
214 | ||||
215 | uptr internal_read(fd_t fd, void *buf, uptr count) { | |||
216 | sptr res; | |||
217 | HANDLE_EINTR(res,{ int rverrno; do { res = ((sptr)internal_syscall(0, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); } | |||
218 | (sptr)internal_syscall(SYSCALL(read), fd, (uptr)buf, count)){ int rverrno; do { res = ((sptr)internal_syscall(0, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); }; | |||
219 | return res; | |||
220 | } | |||
221 | ||||
222 | uptr internal_write(fd_t fd, const void *buf, uptr count) { | |||
223 | sptr res; | |||
224 | HANDLE_EINTR(res,{ int rverrno; do { res = ((sptr)internal_syscall(1, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); } | |||
225 | (sptr)internal_syscall(SYSCALL(write), fd, (uptr)buf, count)){ int rverrno; do { res = ((sptr)internal_syscall(1, fd, (uptr )buf, count)); } while (internal_iserror(res, &rverrno) && rverrno == 4); }; | |||
226 | return res; | |||
227 | } | |||
228 | ||||
229 | uptr internal_ftruncate(fd_t fd, uptr size) { | |||
230 | sptr res; | |||
231 | HANDLE_EINTR(res, (sptr)internal_syscall(SYSCALL(ftruncate), fd,{ int rverrno; do { res = ((sptr)internal_syscall(77, fd, (OFF_T )size)); } while (internal_iserror(res, &rverrno) && rverrno == 4); } | |||
232 | (OFF_T)size)){ int rverrno; do { res = ((sptr)internal_syscall(77, fd, (OFF_T )size)); } while (internal_iserror(res, &rverrno) && rverrno == 4); }; | |||
233 | return res; | |||
234 | } | |||
235 | ||||
236 | #if !SANITIZER_LINUX_USES_64BIT_SYSCALLS1 && SANITIZER_LINUX1 | |||
237 | static void stat64_to_stat(struct stat64 *in, struct stat *out) { | |||
238 | internal_memset(out, 0, sizeof(*out)); | |||
239 | out->st_dev = in->st_dev; | |||
240 | out->st_ino = in->st_ino; | |||
241 | out->st_mode = in->st_mode; | |||
242 | out->st_nlink = in->st_nlink; | |||
243 | out->st_uid = in->st_uid; | |||
244 | out->st_gid = in->st_gid; | |||
245 | out->st_rdev = in->st_rdev; | |||
246 | out->st_size = in->st_size; | |||
247 | out->st_blksize = in->st_blksize; | |||
248 | out->st_blocks = in->st_blocks; | |||
249 | out->st_atimest_atim.tv_sec = in->st_atimest_atim.tv_sec; | |||
250 | out->st_mtimest_mtim.tv_sec = in->st_mtimest_mtim.tv_sec; | |||
251 | out->st_ctimest_ctim.tv_sec = in->st_ctimest_ctim.tv_sec; | |||
252 | } | |||
253 | #endif | |||
254 | ||||
255 | #if defined(__mips64) | |||
256 | // Undefine compatibility macros from <sys/stat.h> | |||
257 | // so that they would not clash with the kernel_stat | |||
258 | // st_[a|m|c]time fields | |||
259 | #if !SANITIZER_GO0 | |||
260 | #undef st_atimest_atim.tv_sec | |||
261 | #undef st_mtimest_mtim.tv_sec | |||
262 | #undef st_ctimest_ctim.tv_sec | |||
263 | #endif | |||
264 | #if defined(SANITIZER_ANDROID0) | |||
265 | // Bionic sys/stat.h defines additional macros | |||
266 | // for compatibility with the old NDKs and | |||
267 | // they clash with the kernel_stat structure | |||
268 | // st_[a|m|c]time_nsec fields. | |||
269 | #undef st_atime_nsec | |||
270 | #undef st_mtime_nsec | |||
271 | #undef st_ctime_nsec | |||
272 | #endif | |||
273 | static void kernel_stat_to_stat(struct kernel_stat *in, struct stat *out) { | |||
274 | internal_memset(out, 0, sizeof(*out)); | |||
275 | out->st_dev = in->st_dev; | |||
276 | out->st_ino = in->st_ino; | |||
277 | out->st_mode = in->st_mode; | |||
278 | out->st_nlink = in->st_nlink; | |||
279 | out->st_uid = in->st_uid; | |||
280 | out->st_gid = in->st_gid; | |||
281 | out->st_rdev = in->st_rdev; | |||
282 | out->st_size = in->st_size; | |||
283 | out->st_blksize = in->st_blksize; | |||
284 | out->st_blocks = in->st_blocks; | |||
285 | #if defined(__USE_MISC1) || \ | |||
286 | defined(__USE_XOPEN2K81) || \ | |||
287 | defined(SANITIZER_ANDROID0) | |||
288 | out->st_atim.tv_sec = in->st_atimest_atim.tv_sec; | |||
289 | out->st_atim.tv_nsec = in->st_atime_nsec; | |||
290 | out->st_mtim.tv_sec = in->st_mtimest_mtim.tv_sec; | |||
291 | out->st_mtim.tv_nsec = in->st_mtime_nsec; | |||
292 | out->st_ctim.tv_sec = in->st_ctimest_ctim.tv_sec; | |||
293 | out->st_ctim.tv_nsec = in->st_ctime_nsec; | |||
294 | #else | |||
295 | out->st_atimest_atim.tv_sec = in->st_atimest_atim.tv_sec; | |||
296 | out->st_atimensec = in->st_atime_nsec; | |||
297 | out->st_mtimest_mtim.tv_sec = in->st_mtimest_mtim.tv_sec; | |||
298 | out->st_mtimensec = in->st_mtime_nsec; | |||
299 | out->st_ctimest_ctim.tv_sec = in->st_ctimest_ctim.tv_sec; | |||
300 | out->st_atimensec = in->st_ctime_nsec; | |||
301 | #endif | |||
302 | } | |||
303 | #endif | |||
304 | ||||
305 | uptr internal_stat(const char *path, void *buf) { | |||
306 | #if SANITIZER_FREEBSD0 | |||
307 | return internal_syscall(SYSCALL(fstatat)__NR_fstatat, AT_FDCWD-100, (uptr)path, (uptr)buf, 0); | |||
308 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
309 | return internal_syscall(SYSCALL(newfstatat)262, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||
310 | 0); | |||
311 | #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||
312 | # if defined(__mips64) | |||
313 | // For mips64, stat syscall fills buffer in the format of kernel_stat | |||
314 | struct kernel_stat kbuf; | |||
315 | int res = internal_syscall(SYSCALL(stat)4, path, &kbuf); | |||
316 | kernel_stat_to_stat(&kbuf, (struct stat *)buf); | |||
317 | return res; | |||
318 | # else | |||
319 | return internal_syscall(SYSCALL(stat)4, (uptr)path, (uptr)buf); | |||
320 | # endif | |||
321 | #else | |||
322 | struct stat64 buf64; | |||
323 | int res = internal_syscall(SYSCALL(stat64)__NR_stat64, path, &buf64); | |||
324 | stat64_to_stat(&buf64, (struct stat *)buf); | |||
325 | return res; | |||
326 | #endif | |||
327 | } | |||
328 | ||||
329 | uptr internal_lstat(const char *path, void *buf) { | |||
330 | #if SANITIZER_FREEBSD0 | |||
331 | return internal_syscall(SYSCALL(fstatat)__NR_fstatat, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||
332 | AT_SYMLINK_NOFOLLOW0x100); | |||
333 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
334 | return internal_syscall(SYSCALL(newfstatat)262, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||
335 | AT_SYMLINK_NOFOLLOW0x100); | |||
336 | #elif SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||
337 | # if SANITIZER_MIPS640 | |||
338 | // For mips64, lstat syscall fills buffer in the format of kernel_stat | |||
339 | struct kernel_stat kbuf; | |||
340 | int res = internal_syscall(SYSCALL(lstat)6, path, &kbuf); | |||
341 | kernel_stat_to_stat(&kbuf, (struct stat *)buf); | |||
342 | return res; | |||
343 | # else | |||
344 | return internal_syscall(SYSCALL(lstat)6, (uptr)path, (uptr)buf); | |||
345 | # endif | |||
346 | #else | |||
347 | struct stat64 buf64; | |||
348 | int res = internal_syscall(SYSCALL(lstat64)__NR_lstat64, path, &buf64); | |||
349 | stat64_to_stat(&buf64, (struct stat *)buf); | |||
350 | return res; | |||
351 | #endif | |||
352 | } | |||
353 | ||||
354 | uptr internal_fstat(fd_t fd, void *buf) { | |||
355 | #if SANITIZER_FREEBSD0 || SANITIZER_LINUX_USES_64BIT_SYSCALLS1 | |||
356 | #if SANITIZER_MIPS640 | |||
357 | // For mips64, fstat syscall fills buffer in the format of kernel_stat | |||
358 | struct kernel_stat kbuf; | |||
359 | int res = internal_syscall(SYSCALL(fstat)5, fd, &kbuf); | |||
360 | kernel_stat_to_stat(&kbuf, (struct stat *)buf); | |||
361 | return res; | |||
362 | # else | |||
363 | return internal_syscall(SYSCALL(fstat)5, fd, (uptr)buf); | |||
364 | # endif | |||
365 | #else | |||
366 | struct stat64 buf64; | |||
367 | int res = internal_syscall(SYSCALL(fstat64)__NR_fstat64, fd, &buf64); | |||
368 | stat64_to_stat(&buf64, (struct stat *)buf); | |||
369 | return res; | |||
370 | #endif | |||
371 | } | |||
372 | ||||
373 | uptr internal_filesize(fd_t fd) { | |||
374 | struct stat st; | |||
375 | if (internal_fstat(fd, &st)) | |||
| ||||
376 | return -1; | |||
377 | return (uptr)st.st_size; | |||
| ||||
378 | } | |||
379 | ||||
380 | uptr internal_dup(int oldfd) { | |||
381 | return internal_syscall(SYSCALL(dup)32, oldfd); | |||
382 | } | |||
383 | ||||
384 | uptr internal_dup2(int oldfd, int newfd) { | |||
385 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
386 | return internal_syscall(SYSCALL(dup3)292, oldfd, newfd, 0); | |||
387 | #else | |||
388 | return internal_syscall(SYSCALL(dup2)33, oldfd, newfd); | |||
389 | #endif | |||
390 | } | |||
391 | ||||
392 | uptr internal_readlink(const char *path, char *buf, uptr bufsize) { | |||
393 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
394 | return internal_syscall(SYSCALL(readlinkat)267, AT_FDCWD-100, (uptr)path, (uptr)buf, | |||
395 | bufsize); | |||
396 | #else | |||
397 | return internal_syscall(SYSCALL(readlink)89, (uptr)path, (uptr)buf, bufsize); | |||
398 | #endif | |||
399 | } | |||
400 | ||||
401 | uptr internal_unlink(const char *path) { | |||
402 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
403 | return internal_syscall(SYSCALL(unlinkat)263, AT_FDCWD-100, (uptr)path, 0); | |||
404 | #else | |||
405 | return internal_syscall(SYSCALL(unlink)87, (uptr)path); | |||
406 | #endif | |||
407 | } | |||
408 | ||||
409 | uptr internal_rename(const char *oldpath, const char *newpath) { | |||
410 | #if defined(__riscv) | |||
411 | return internal_syscall(SYSCALL(renameat2)316, AT_FDCWD-100, (uptr)oldpath, AT_FDCWD-100, | |||
412 | (uptr)newpath, 0); | |||
413 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
414 | return internal_syscall(SYSCALL(renameat)264, AT_FDCWD-100, (uptr)oldpath, AT_FDCWD-100, | |||
415 | (uptr)newpath); | |||
416 | #else | |||
417 | return internal_syscall(SYSCALL(rename)82, (uptr)oldpath, (uptr)newpath); | |||
418 | #endif | |||
419 | } | |||
420 | ||||
421 | uptr internal_sched_yield() { | |||
422 | return internal_syscall(SYSCALL(sched_yield)24); | |||
423 | } | |||
424 | ||||
425 | unsigned int internal_sleep(unsigned int seconds) { | |||
426 | struct timespec ts; | |||
427 | ts.tv_sec = seconds; | |||
428 | ts.tv_nsec = 0; | |||
429 | int res = internal_syscall(SYSCALL(nanosleep)35, &ts, &ts); | |||
430 | if (res) return ts.tv_sec; | |||
431 | return 0; | |||
432 | } | |||
433 | ||||
434 | uptr internal_execve(const char *filename, char *const argv[], | |||
435 | char *const envp[]) { | |||
436 | return internal_syscall(SYSCALL(execve)59, (uptr)filename, (uptr)argv, | |||
437 | (uptr)envp); | |||
438 | } | |||
439 | #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |||
440 | ||||
441 | #if !SANITIZER_NETBSD0 | |||
442 | void internal__exit(int exitcode) { | |||
443 | #if SANITIZER_FREEBSD0 || SANITIZER_SOLARIS0 | |||
444 | internal_syscall(SYSCALL(exit)60, exitcode); | |||
445 | #else | |||
446 | internal_syscall(SYSCALL(exit_group)231, exitcode); | |||
447 | #endif | |||
448 | Die(); // Unreachable. | |||
449 | } | |||
450 | #endif // !SANITIZER_NETBSD | |||
451 | ||||
452 | // ----------------- sanitizer_common.h | |||
453 | bool FileExists(const char *filename) { | |||
454 | if (ShouldMockFailureToOpen(filename)) | |||
455 | return false; | |||
456 | struct stat st; | |||
457 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
458 | if (internal_syscall(SYSCALL(newfstatat)262, AT_FDCWD-100, filename, &st, 0)) | |||
459 | #else | |||
460 | if (internal_stat(filename, &st)) | |||
461 | #endif | |||
462 | return false; | |||
463 | // Sanity check: filename is a regular file. | |||
464 | return S_ISREG(st.st_mode)((((st.st_mode)) & 0170000) == (0100000)); | |||
465 | } | |||
466 | ||||
467 | #if !SANITIZER_NETBSD0 | |||
468 | tid_t GetTid() { | |||
469 | #if SANITIZER_FREEBSD0 | |||
470 | long Tid; | |||
471 | thr_self(&Tid); | |||
472 | return Tid; | |||
473 | #elif SANITIZER_SOLARIS0 | |||
474 | return thr_self(); | |||
475 | #else | |||
476 | return internal_syscall(SYSCALL(gettid)186); | |||
477 | #endif | |||
478 | } | |||
479 | ||||
480 | int TgKill(pid_t pid, tid_t tid, int sig) { | |||
481 | #if SANITIZER_LINUX1 | |||
482 | return internal_syscall(SYSCALL(tgkill)234, pid, tid, sig); | |||
483 | #elif SANITIZER_FREEBSD0 | |||
484 | return internal_syscall(SYSCALL(thr_kill2)__NR_thr_kill2, pid, tid, sig); | |||
485 | #elif SANITIZER_SOLARIS0 | |||
486 | (void)pid; | |||
487 | return thr_kill(tid, sig); | |||
488 | #endif | |||
489 | } | |||
490 | #endif | |||
491 | ||||
492 | #if !SANITIZER_SOLARIS0 && !SANITIZER_NETBSD0 | |||
493 | u64 NanoTime() { | |||
494 | #if SANITIZER_FREEBSD0 | |||
495 | timeval tv; | |||
496 | #else | |||
497 | kernel_timeval tv; | |||
498 | #endif | |||
499 | internal_memset(&tv, 0, sizeof(tv)); | |||
500 | internal_syscall(SYSCALL(gettimeofday)96, &tv, 0); | |||
501 | return (u64)tv.tv_sec * 1000*1000*1000 + tv.tv_usec * 1000; | |||
502 | } | |||
503 | ||||
504 | uptr internal_clock_gettime(__sanitizer_clockid_t clk_id, void *tp) { | |||
505 | return internal_syscall(SYSCALL(clock_gettime)228, clk_id, tp); | |||
506 | } | |||
507 | #endif // !SANITIZER_SOLARIS && !SANITIZER_NETBSD | |||
508 | ||||
509 | // Like getenv, but reads env directly from /proc (on Linux) or parses the | |||
510 | // 'environ' array (on some others) and does not use libc. This function | |||
511 | // should be called first inside __asan_init. | |||
512 | const char *GetEnv(const char *name) { | |||
513 | #if SANITIZER_FREEBSD0 || SANITIZER_NETBSD0 || SANITIZER_SOLARIS0 | |||
514 | if (::environ != 0) { | |||
515 | uptr NameLen = internal_strlen(name); | |||
516 | for (char **Env = ::environ; *Env != 0; Env++) { | |||
517 | if (internal_strncmp(*Env, name, NameLen) == 0 && (*Env)[NameLen] == '=') | |||
518 | return (*Env) + NameLen + 1; | |||
519 | } | |||
520 | } | |||
521 | return 0; // Not found. | |||
522 | #elif SANITIZER_LINUX1 | |||
523 | static char *environ; | |||
524 | static uptr len; | |||
525 | static bool inited; | |||
526 | if (!inited) { | |||
527 | inited = true; | |||
528 | uptr environ_size; | |||
529 | if (!ReadFileToBuffer("/proc/self/environ", &environ, &environ_size, &len)) | |||
530 | environ = nullptr; | |||
531 | } | |||
532 | if (!environ || len == 0) return nullptr; | |||
533 | uptr namelen = internal_strlen(name); | |||
534 | const char *p = environ; | |||
535 | while (*p != '\0') { // will happen at the \0\0 that terminates the buffer | |||
536 | // proc file has the format NAME=value\0NAME=value\0NAME=value\0... | |||
537 | const char* endp = | |||
538 | (char*)internal_memchr(p, '\0', len - (p - environ)); | |||
539 | if (!endp) // this entry isn't NUL terminated | |||
540 | return nullptr; | |||
541 | else if (!internal_memcmp(p, name, namelen) && p[namelen] == '=') // Match. | |||
542 | return p + namelen + 1; // point after = | |||
543 | p = endp + 1; | |||
544 | } | |||
545 | return nullptr; // Not found. | |||
546 | #else | |||
547 | #error "Unsupported platform" | |||
548 | #endif | |||
549 | } | |||
550 | ||||
551 | #if !SANITIZER_FREEBSD0 && !SANITIZER_NETBSD0 && !SANITIZER_GO0 | |||
552 | extern "C" { | |||
553 | SANITIZER_WEAK_ATTRIBUTE__attribute__((weak)) extern void *__libc_stack_end; | |||
554 | } | |||
555 | #endif | |||
556 | ||||
557 | #if !SANITIZER_FREEBSD0 && !SANITIZER_NETBSD0 | |||
558 | static void ReadNullSepFileToArray(const char *path, char ***arr, | |||
559 | int arr_size) { | |||
560 | char *buff; | |||
561 | uptr buff_size; | |||
562 | uptr buff_len; | |||
563 | *arr = (char **)MmapOrDie(arr_size * sizeof(char *), "NullSepFileArray"); | |||
564 | if (!ReadFileToBuffer(path, &buff, &buff_size, &buff_len, 1024 * 1024)) { | |||
565 | (*arr)[0] = nullptr; | |||
566 | return; | |||
567 | } | |||
568 | (*arr)[0] = buff; | |||
569 | int count, i; | |||
570 | for (count = 1, i = 1; ; i++) { | |||
571 | if (buff[i] == 0) { | |||
572 | if (buff[i+1] == 0) break; | |||
573 | (*arr)[count] = &buff[i+1]; | |||
574 | CHECK_LE(count, arr_size - 1)do { __sanitizer::u64 v1 = (__sanitizer::u64)((count)); __sanitizer ::u64 v2 = (__sanitizer::u64)((arr_size - 1)); if (__builtin_expect (!!(!(v1 <= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 574, "(" "(count)" ") " "<=" " (" "(arr_size - 1)" ")", v1 , v2); } while (false); // FIXME: make this more flexible. | |||
575 | count++; | |||
576 | } | |||
577 | } | |||
578 | (*arr)[count] = nullptr; | |||
579 | } | |||
580 | #endif | |||
581 | ||||
582 | static void GetArgsAndEnv(char ***argv, char ***envp) { | |||
583 | #if SANITIZER_FREEBSD0 | |||
584 | // On FreeBSD, retrieving the argument and environment arrays is done via the | |||
585 | // kern.ps_strings sysctl, which returns a pointer to a structure containing | |||
586 | // this information. See also <sys/exec.h>. | |||
587 | ps_strings *pss; | |||
588 | uptr sz = sizeof(pss); | |||
589 | if (internal_sysctlbyname("kern.ps_strings", &pss, &sz, NULL__null, 0) == -1) { | |||
590 | Printf("sysctl kern.ps_strings failed\n"); | |||
591 | Die(); | |||
592 | } | |||
593 | *argv = pss->ps_argvstr; | |||
594 | *envp = pss->ps_envstr; | |||
595 | #elif SANITIZER_NETBSD0 | |||
596 | *argv = __ps_strings->ps_argvstr; | |||
597 | *envp = __ps_strings->ps_envstr; | |||
598 | #else // SANITIZER_FREEBSD | |||
599 | #if !SANITIZER_GO0 | |||
600 | if (&__libc_stack_end) { | |||
601 | uptr* stack_end = (uptr*)__libc_stack_end; | |||
602 | // Normally argc can be obtained from *stack_end, however, on ARM glibc's | |||
603 | // _start clobbers it: | |||
604 | // https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/arm/start.S;hb=refs/heads/release/2.31/master#l75 | |||
605 | // Do not special-case ARM and infer argc from argv everywhere. | |||
606 | int argc = 0; | |||
607 | while (stack_end[argc + 1]) argc++; | |||
608 | *argv = (char**)(stack_end + 1); | |||
609 | *envp = (char**)(stack_end + argc + 2); | |||
610 | } else { | |||
611 | #endif // !SANITIZER_GO | |||
612 | static const int kMaxArgv = 2000, kMaxEnvp = 2000; | |||
613 | ReadNullSepFileToArray("/proc/self/cmdline", argv, kMaxArgv); | |||
614 | ReadNullSepFileToArray("/proc/self/environ", envp, kMaxEnvp); | |||
615 | #if !SANITIZER_GO0 | |||
616 | } | |||
617 | #endif // !SANITIZER_GO | |||
618 | #endif // SANITIZER_FREEBSD | |||
619 | } | |||
620 | ||||
621 | char **GetArgv() { | |||
622 | char **argv, **envp; | |||
623 | GetArgsAndEnv(&argv, &envp); | |||
624 | return argv; | |||
625 | } | |||
626 | ||||
627 | char **GetEnviron() { | |||
628 | char **argv, **envp; | |||
629 | GetArgsAndEnv(&argv, &envp); | |||
630 | return envp; | |||
631 | } | |||
632 | ||||
633 | #if !SANITIZER_SOLARIS0 | |||
634 | enum MutexState { | |||
635 | MtxUnlocked = 0, | |||
636 | MtxLocked = 1, | |||
637 | MtxSleeping = 2 | |||
638 | }; | |||
639 | ||||
640 | BlockingMutex::BlockingMutex() { | |||
641 | internal_memset(this, 0, sizeof(*this)); | |||
642 | } | |||
643 | ||||
644 | void BlockingMutex::Lock() { | |||
645 | CHECK_EQ(owner_, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((owner_)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 == v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 645, "(" "(owner_)" ") " "==" " (" "(0)" ")", v1, v2); } while (false); | |||
646 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |||
647 | if (atomic_exchange(m, MtxLocked, memory_order_acquire) == MtxUnlocked) | |||
648 | return; | |||
649 | while (atomic_exchange(m, MtxSleeping, memory_order_acquire) != MtxUnlocked) { | |||
650 | #if SANITIZER_FREEBSD0 | |||
651 | _umtx_op(m, UMTX_OP_WAIT_UINT, MtxSleeping, 0, 0); | |||
652 | #elif SANITIZER_NETBSD0 | |||
653 | sched_yield(); /* No userspace futex-like synchronization */ | |||
654 | #else | |||
655 | internal_syscall(SYSCALL(futex)202, (uptr)m, FUTEX_WAIT_PRIVATE, MtxSleeping, | |||
656 | 0, 0, 0); | |||
657 | #endif | |||
658 | } | |||
659 | } | |||
660 | ||||
661 | void BlockingMutex::Unlock() { | |||
662 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |||
663 | u32 v = atomic_exchange(m, MtxUnlocked, memory_order_release); | |||
664 | CHECK_NE(v, MtxUnlocked)do { __sanitizer::u64 v1 = (__sanitizer::u64)((v)); __sanitizer ::u64 v2 = (__sanitizer::u64)((MtxUnlocked)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 664, "(" "(v)" ") " "!=" " (" "(MtxUnlocked)" ")", v1, v2); } while (false); | |||
665 | if (v == MtxSleeping) { | |||
666 | #if SANITIZER_FREEBSD0 | |||
667 | _umtx_op(m, UMTX_OP_WAKE, 1, 0, 0); | |||
668 | #elif SANITIZER_NETBSD0 | |||
669 | /* No userspace futex-like synchronization */ | |||
670 | #else | |||
671 | internal_syscall(SYSCALL(futex)202, (uptr)m, FUTEX_WAKE_PRIVATE, 1, 0, 0, 0); | |||
672 | #endif | |||
673 | } | |||
674 | } | |||
675 | ||||
676 | void BlockingMutex::CheckLocked() { | |||
677 | atomic_uint32_t *m = reinterpret_cast<atomic_uint32_t *>(&opaque_storage_); | |||
678 | CHECK_NE(MtxUnlocked, atomic_load(m, memory_order_relaxed))do { __sanitizer::u64 v1 = (__sanitizer::u64)((MtxUnlocked)); __sanitizer::u64 v2 = (__sanitizer::u64)((atomic_load(m, memory_order_relaxed ))); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 678, "(" "(MtxUnlocked)" ") " "!=" " (" "(atomic_load(m, memory_order_relaxed))" ")", v1, v2); } while (false); | |||
679 | } | |||
680 | #endif // !SANITIZER_SOLARIS | |||
681 | ||||
682 | // ----------------- sanitizer_linux.h | |||
683 | // The actual size of this structure is specified by d_reclen. | |||
684 | // Note that getdents64 uses a different structure format. We only provide the | |||
685 | // 32-bit syscall here. | |||
686 | #if SANITIZER_NETBSD0 | |||
687 | // Not used | |||
688 | #else | |||
689 | struct linux_dirent { | |||
690 | #if SANITIZER_X320 || defined(__aarch64__) || SANITIZER_RISCV640 | |||
691 | u64 d_ino; | |||
692 | u64 d_off; | |||
693 | #else | |||
694 | unsigned long d_ino; | |||
695 | unsigned long d_off; | |||
696 | #endif | |||
697 | unsigned short d_reclen; | |||
698 | #if defined(__aarch64__) || SANITIZER_RISCV640 | |||
699 | unsigned char d_type; | |||
700 | #endif | |||
701 | char d_name[256]; | |||
702 | }; | |||
703 | #endif | |||
704 | ||||
705 | #if !SANITIZER_SOLARIS0 && !SANITIZER_NETBSD0 | |||
706 | // Syscall wrappers. | |||
707 | uptr internal_ptrace(int request, int pid, void *addr, void *data) { | |||
708 | return internal_syscall(SYSCALL(ptrace)101, request, pid, (uptr)addr, | |||
709 | (uptr)data); | |||
710 | } | |||
711 | ||||
712 | uptr internal_waitpid(int pid, int *status, int options) { | |||
713 | return internal_syscall(SYSCALL(wait4)61, pid, (uptr)status, options, | |||
714 | 0 /* rusage */); | |||
715 | } | |||
716 | ||||
717 | uptr internal_getpid() { | |||
718 | return internal_syscall(SYSCALL(getpid)39); | |||
719 | } | |||
720 | ||||
721 | uptr internal_getppid() { | |||
722 | return internal_syscall(SYSCALL(getppid)110); | |||
723 | } | |||
724 | ||||
725 | int internal_dlinfo(void *handle, int request, void *p) { | |||
726 | #if SANITIZER_FREEBSD0 | |||
727 | return dlinfo(handle, request, p); | |||
728 | #else | |||
729 | UNIMPLEMENTED()do { do { __sanitizer::u64 v1 = (__sanitizer::u64)((0 && "unimplemented")); __sanitizer::u64 v2 = (__sanitizer::u64)( 0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 729, "(" "(0 && \"unimplemented\")" ") " "!=" " (" "0" ")", v1, v2); } while (false); Die(); } while (0); | |||
730 | #endif | |||
731 | } | |||
732 | ||||
733 | uptr internal_getdents(fd_t fd, struct linux_dirent *dirp, unsigned int count) { | |||
734 | #if SANITIZER_FREEBSD0 | |||
735 | return internal_syscall(SYSCALL(getdirentries)__NR_getdirentries, fd, (uptr)dirp, count, NULL__null); | |||
736 | #elif SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
737 | return internal_syscall(SYSCALL(getdents64)217, fd, (uptr)dirp, count); | |||
738 | #else | |||
739 | return internal_syscall(SYSCALL(getdents)78, fd, (uptr)dirp, count); | |||
740 | #endif | |||
741 | } | |||
742 | ||||
743 | uptr internal_lseek(fd_t fd, OFF_T offset, int whence) { | |||
744 | return internal_syscall(SYSCALL(lseek)8, fd, offset, whence); | |||
745 | } | |||
746 | ||||
747 | #if SANITIZER_LINUX1 | |||
748 | uptr internal_prctl(int option, uptr arg2, uptr arg3, uptr arg4, uptr arg5) { | |||
749 | return internal_syscall(SYSCALL(prctl)157, option, arg2, arg3, arg4, arg5); | |||
750 | } | |||
751 | #endif | |||
752 | ||||
753 | uptr internal_sigaltstack(const void *ss, void *oss) { | |||
754 | return internal_syscall(SYSCALL(sigaltstack)131, (uptr)ss, (uptr)oss); | |||
755 | } | |||
756 | ||||
757 | int internal_fork() { | |||
758 | #if SANITIZER_USES_CANONICAL_LINUX_SYSCALLS0 | |||
759 | return internal_syscall(SYSCALL(clone)56, SIGCHLD17, 0); | |||
760 | #else | |||
761 | return internal_syscall(SYSCALL(fork)57); | |||
762 | #endif | |||
763 | } | |||
764 | ||||
765 | #if SANITIZER_FREEBSD0 | |||
766 | int internal_sysctl(const int *name, unsigned int namelen, void *oldp, | |||
767 | uptr *oldlenp, const void *newp, uptr newlen) { | |||
768 | return internal_syscall(SYSCALL(__sysctl)__NR___sysctl, name, namelen, oldp, | |||
769 | (size_t *)oldlenp, newp, (size_t)newlen); | |||
770 | } | |||
771 | ||||
772 | int internal_sysctlbyname(const char *sname, void *oldp, uptr *oldlenp, | |||
773 | const void *newp, uptr newlen) { | |||
774 | // Note: this function can be called during startup, so we need to avoid | |||
775 | // calling any interceptable functions. On FreeBSD >= 1300045 sysctlbyname() | |||
776 | // is a real syscall, but for older versions it calls sysctlnametomib() | |||
777 | // followed by sysctl(). To avoid calling the intercepted version and | |||
778 | // asserting if this happens during startup, call the real sysctlnametomib() | |||
779 | // followed by internal_sysctl() if the syscall is not available. | |||
780 | #ifdef SYS___sysctlbyname | |||
781 | return internal_syscall(SYSCALL(__sysctlbyname)__NR___sysctlbyname, sname, | |||
782 | internal_strlen(sname), oldp, (size_t *)oldlenp, newp, | |||
783 | (size_t)newlen); | |||
784 | #else | |||
785 | static decltype(sysctlnametomib) *real_sysctlnametomib = nullptr; | |||
786 | if (!real_sysctlnametomib) | |||
787 | real_sysctlnametomib = | |||
788 | (decltype(sysctlnametomib) *)dlsym(RTLD_NEXT((void *) -1l), "sysctlnametomib"); | |||
789 | CHECK(real_sysctlnametomib)do { __sanitizer::u64 v1 = (__sanitizer::u64)((real_sysctlnametomib )); __sanitizer::u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 789, "(" "(real_sysctlnametomib)" ") " "!=" " (" "0" ")", v1 , v2); } while (false); | |||
790 | ||||
791 | int oid[CTL_MAXNAME]; | |||
792 | size_t len = CTL_MAXNAME; | |||
793 | if (real_sysctlnametomib(sname, oid, &len) == -1) | |||
794 | return (-1); | |||
795 | return internal_sysctl(oid, len, oldp, oldlenp, newp, newlen); | |||
796 | #endif | |||
797 | } | |||
798 | #endif | |||
799 | ||||
800 | #if SANITIZER_LINUX1 | |||
801 | #define SA_RESTORER0x04000000 0x04000000 | |||
802 | // Doesn't set sa_restorer if the caller did not set it, so use with caution | |||
803 | //(see below). | |||
804 | int internal_sigaction_norestorer(int signum, const void *act, void *oldact) { | |||
805 | __sanitizer_kernel_sigaction_t k_act, k_oldact; | |||
806 | internal_memset(&k_act, 0, sizeof(__sanitizer_kernel_sigaction_t)); | |||
807 | internal_memset(&k_oldact, 0, sizeof(__sanitizer_kernel_sigaction_t)); | |||
808 | const __sanitizer_sigaction *u_act = (const __sanitizer_sigaction *)act; | |||
809 | __sanitizer_sigaction *u_oldact = (__sanitizer_sigaction *)oldact; | |||
810 | if (u_act) { | |||
811 | k_act.handler = u_act->handler; | |||
812 | k_act.sigaction = u_act->sigaction; | |||
813 | internal_memcpy(&k_act.sa_mask, &u_act->sa_mask, | |||
814 | sizeof(__sanitizer_kernel_sigset_t)); | |||
815 | // Without SA_RESTORER kernel ignores the calls (probably returns EINVAL). | |||
816 | k_act.sa_flags = u_act->sa_flags | SA_RESTORER0x04000000; | |||
817 | // FIXME: most often sa_restorer is unset, however the kernel requires it | |||
818 | // to point to a valid signal restorer that calls the rt_sigreturn syscall. | |||
819 | // If sa_restorer passed to the kernel is NULL, the program may crash upon | |||
820 | // signal delivery or fail to unwind the stack in the signal handler. | |||
821 | // libc implementation of sigaction() passes its own restorer to | |||
822 | // rt_sigaction, so we need to do the same (we'll need to reimplement the | |||
823 | // restorers; for x86_64 the restorer address can be obtained from | |||
824 | // oldact->sa_restorer upon a call to sigaction(xxx, NULL, oldact). | |||
825 | #if !SANITIZER_ANDROID0 || !SANITIZER_MIPS320 | |||
826 | k_act.sa_restorer = u_act->sa_restorer; | |||
827 | #endif | |||
828 | } | |||
829 | ||||
830 | uptr result = internal_syscall(SYSCALL(rt_sigaction)13, (uptr)signum, | |||
831 | (uptr)(u_act ? &k_act : nullptr), | |||
832 | (uptr)(u_oldact ? &k_oldact : nullptr), | |||
833 | (uptr)sizeof(__sanitizer_kernel_sigset_t)); | |||
834 | ||||
835 | if ((result == 0) && u_oldact) { | |||
836 | u_oldact->handler = k_oldact.handler; | |||
837 | u_oldact->sigaction = k_oldact.sigaction; | |||
838 | internal_memcpy(&u_oldact->sa_mask, &k_oldact.sa_mask, | |||
839 | sizeof(__sanitizer_kernel_sigset_t)); | |||
840 | u_oldact->sa_flags = k_oldact.sa_flags; | |||
841 | #if !SANITIZER_ANDROID0 || !SANITIZER_MIPS320 | |||
842 | u_oldact->sa_restorer = k_oldact.sa_restorer; | |||
843 | #endif | |||
844 | } | |||
845 | return result; | |||
846 | } | |||
847 | #endif // SANITIZER_LINUX | |||
848 | ||||
849 | uptr internal_sigprocmask(int how, __sanitizer_sigset_t *set, | |||
850 | __sanitizer_sigset_t *oldset) { | |||
851 | #if SANITIZER_FREEBSD0 | |||
852 | return internal_syscall(SYSCALL(sigprocmask)__NR_sigprocmask, how, set, oldset); | |||
853 | #else | |||
854 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; | |||
855 | __sanitizer_kernel_sigset_t *k_oldset = (__sanitizer_kernel_sigset_t *)oldset; | |||
856 | return internal_syscall(SYSCALL(rt_sigprocmask)14, (uptr)how, (uptr)k_set, | |||
857 | (uptr)k_oldset, sizeof(__sanitizer_kernel_sigset_t)); | |||
858 | #endif | |||
859 | } | |||
860 | ||||
861 | void internal_sigfillset(__sanitizer_sigset_t *set) { | |||
862 | internal_memset(set, 0xff, sizeof(*set)); | |||
863 | } | |||
864 | ||||
865 | void internal_sigemptyset(__sanitizer_sigset_t *set) { | |||
866 | internal_memset(set, 0, sizeof(*set)); | |||
867 | } | |||
868 | ||||
869 | #if SANITIZER_LINUX1 | |||
870 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { | |||
871 | signum -= 1; | |||
872 | CHECK_GE(signum, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 >= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 872, "(" "(signum)" ") " ">=" " (" "(0)" ")", v1, v2); } while (false); | |||
873 | CHECK_LT(signum, sizeof(*set) * 8)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((sizeof(*set) * 8)); if (__builtin_expect (!!(!(v1 < v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 873, "(" "(signum)" ") " "<" " (" "(sizeof(*set) * 8)" ")" , v1, v2); } while (false); | |||
874 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; | |||
875 | const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); | |||
876 | const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); | |||
877 | k_set->sig[idx] &= ~(1 << bit); | |||
878 | } | |||
879 | ||||
880 | bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { | |||
881 | signum -= 1; | |||
882 | CHECK_GE(signum, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 >= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 882, "(" "(signum)" ") " ">=" " (" "(0)" ")", v1, v2); } while (false); | |||
883 | CHECK_LT(signum, sizeof(*set) * 8)do { __sanitizer::u64 v1 = (__sanitizer::u64)((signum)); __sanitizer ::u64 v2 = (__sanitizer::u64)((sizeof(*set) * 8)); if (__builtin_expect (!!(!(v1 < v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 883, "(" "(signum)" ") " "<" " (" "(sizeof(*set) * 8)" ")" , v1, v2); } while (false); | |||
884 | __sanitizer_kernel_sigset_t *k_set = (__sanitizer_kernel_sigset_t *)set; | |||
885 | const uptr idx = signum / (sizeof(k_set->sig[0]) * 8); | |||
886 | const uptr bit = signum % (sizeof(k_set->sig[0]) * 8); | |||
887 | return k_set->sig[idx] & (1 << bit); | |||
888 | } | |||
889 | #elif SANITIZER_FREEBSD0 | |||
890 | void internal_sigdelset(__sanitizer_sigset_t *set, int signum) { | |||
891 | sigset_t *rset = reinterpret_cast<sigset_t *>(set); | |||
892 | sigdelset(rset, signum); | |||
893 | } | |||
894 | ||||
895 | bool internal_sigismember(__sanitizer_sigset_t *set, int signum) { | |||
896 | sigset_t *rset = reinterpret_cast<sigset_t *>(set); | |||
897 | return sigismember(rset, signum); | |||
898 | } | |||
899 | #endif | |||
900 | #endif // !SANITIZER_SOLARIS | |||
901 | ||||
902 | #if !SANITIZER_NETBSD0 | |||
903 | // ThreadLister implementation. | |||
904 | ThreadLister::ThreadLister(pid_t pid) : pid_(pid), buffer_(4096) { | |||
905 | char task_directory_path[80]; | |||
906 | internal_snprintf(task_directory_path, sizeof(task_directory_path), | |||
907 | "/proc/%d/task/", pid); | |||
908 | descriptor_ = internal_open(task_directory_path, O_RDONLY00 | O_DIRECTORY0200000); | |||
909 | if (internal_iserror(descriptor_)) { | |||
910 | Report("Can't open /proc/%d/task for reading.\n", pid); | |||
911 | } | |||
912 | } | |||
913 | ||||
914 | ThreadLister::Result ThreadLister::ListThreads( | |||
915 | InternalMmapVector<tid_t> *threads) { | |||
916 | if (internal_iserror(descriptor_)) | |||
917 | return Error; | |||
918 | internal_lseek(descriptor_, 0, SEEK_SET0); | |||
919 | threads->clear(); | |||
920 | ||||
921 | Result result = Ok; | |||
922 | for (bool first_read = true;; first_read = false) { | |||
923 | // Resize to max capacity if it was downsized by IsAlive. | |||
924 | buffer_.resize(buffer_.capacity()); | |||
925 | CHECK_GE(buffer_.size(), 4096)do { __sanitizer::u64 v1 = (__sanitizer::u64)((buffer_.size() )); __sanitizer::u64 v2 = (__sanitizer::u64)((4096)); if (__builtin_expect (!!(!(v1 >= v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 925, "(" "(buffer_.size())" ") " ">=" " (" "(4096)" ")", v1, v2); } while (false); | |||
926 | uptr read = internal_getdents( | |||
927 | descriptor_, (struct linux_dirent *)buffer_.data(), buffer_.size()); | |||
928 | if (!read) | |||
929 | return result; | |||
930 | if (internal_iserror(read)) { | |||
931 | Report("Can't read directory entries from /proc/%d/task.\n", pid_); | |||
932 | return Error; | |||
933 | } | |||
934 | ||||
935 | for (uptr begin = (uptr)buffer_.data(), end = begin + read; begin < end;) { | |||
936 | struct linux_dirent *entry = (struct linux_dirent *)begin; | |||
937 | begin += entry->d_reclen; | |||
938 | if (entry->d_ino == 1) { | |||
939 | // Inode 1 is for bad blocks and also can be a reason for early return. | |||
940 | // Should be emitted if kernel tried to output terminating thread. | |||
941 | // See proc_task_readdir implementation in Linux. | |||
942 | result = Incomplete; | |||
943 | } | |||
944 | if (entry->d_ino && *entry->d_name >= '0' && *entry->d_name <= '9') | |||
945 | threads->push_back(internal_atoll(entry->d_name)); | |||
946 | } | |||
947 | ||||
948 | // Now we are going to detect short-read or early EOF. In such cases Linux | |||
949 | // can return inconsistent list with missing alive threads. | |||
950 | // Code will just remember that the list can be incomplete but it will | |||
951 | // continue reads to return as much as possible. | |||
952 | if (!first_read) { | |||
953 | // The first one was a short-read by definition. | |||
954 | result = Incomplete; | |||
955 | } else if (read > buffer_.size() - 1024) { | |||
956 | // Read was close to the buffer size. So double the size and assume the | |||
957 | // worst. | |||
958 | buffer_.resize(buffer_.size() * 2); | |||
959 | result = Incomplete; | |||
960 | } else if (!threads->empty() && !IsAlive(threads->back())) { | |||
961 | // Maybe Linux early returned from read on terminated thread (!pid_alive) | |||
962 | // and failed to restore read position. | |||
963 | // See next_tid and proc_task_instantiate in Linux. | |||
964 | result = Incomplete; | |||
965 | } | |||
966 | } | |||
967 | } | |||
968 | ||||
969 | bool ThreadLister::IsAlive(int tid) { | |||
970 | // /proc/%d/task/%d/status uses same call to detect alive threads as | |||
971 | // proc_task_readdir. See task_state implementation in Linux. | |||
972 | char path[80]; | |||
973 | internal_snprintf(path, sizeof(path), "/proc/%d/task/%d/status", pid_, tid); | |||
974 | if (!ReadFileToVector(path, &buffer_) || buffer_.empty()) | |||
975 | return false; | |||
976 | buffer_.push_back(0); | |||
977 | static const char kPrefix[] = "\nPPid:"; | |||
978 | const char *field = internal_strstr(buffer_.data(), kPrefix); | |||
979 | if (!field) | |||
980 | return false; | |||
981 | field += internal_strlen(kPrefix); | |||
982 | return (int)internal_atoll(field) != 0; | |||
983 | } | |||
984 | ||||
985 | ThreadLister::~ThreadLister() { | |||
986 | if (!internal_iserror(descriptor_)) | |||
987 | internal_close(descriptor_); | |||
988 | } | |||
989 | #endif | |||
990 | ||||
991 | #if SANITIZER_WORDSIZE64 == 32 | |||
992 | // Take care of unusable kernel area in top gigabyte. | |||
993 | static uptr GetKernelAreaSize() { | |||
994 | #if SANITIZER_LINUX1 && !SANITIZER_X320 | |||
995 | const uptr gbyte = 1UL << 30; | |||
996 | ||||
997 | // Firstly check if there are writable segments | |||
998 | // mapped to top gigabyte (e.g. stack). | |||
999 | MemoryMappingLayout proc_maps(/*cache_enabled*/true); | |||
1000 | if (proc_maps.Error()) | |||
1001 | return 0; | |||
1002 | MemoryMappedSegment segment; | |||
1003 | while (proc_maps.Next(&segment)) { | |||
1004 | if ((segment.end >= 3 * gbyte) && segment.IsWritable()) return 0; | |||
1005 | } | |||
1006 | ||||
1007 | #if !SANITIZER_ANDROID0 | |||
1008 | // Even if nothing is mapped, top Gb may still be accessible | |||
1009 | // if we are running on 64-bit kernel. | |||
1010 | // Uname may report misleading results if personality type | |||
1011 | // is modified (e.g. under schroot) so check this as well. | |||
1012 | struct utsname uname_info; | |||
1013 | int pers = personality(0xffffffffUL); | |||
1014 | if (!(pers & PER_MASK) && internal_uname(&uname_info) == 0 && | |||
1015 | internal_strstr(uname_info.machine, "64")) | |||
1016 | return 0; | |||
1017 | #endif // SANITIZER_ANDROID | |||
1018 | ||||
1019 | // Top gigabyte is reserved for kernel. | |||
1020 | return gbyte; | |||
1021 | #else | |||
1022 | return 0; | |||
1023 | #endif // SANITIZER_LINUX && !SANITIZER_X32 | |||
1024 | } | |||
1025 | #endif // SANITIZER_WORDSIZE == 32 | |||
1026 | ||||
1027 | uptr GetMaxVirtualAddress() { | |||
1028 | #if SANITIZER_NETBSD0 && defined(__x86_64__1) | |||
1029 | return 0x7f7ffffff000ULL; // (0x00007f8000000000 - PAGE_SIZE) | |||
1030 | #elif SANITIZER_WORDSIZE64 == 64 | |||
1031 | # if defined(__powerpc64__) || defined(__aarch64__) | |||
1032 | // On PowerPC64 we have two different address space layouts: 44- and 46-bit. | |||
1033 | // We somehow need to figure out which one we are using now and choose | |||
1034 | // one of 0x00000fffffffffffUL and 0x00003fffffffffffUL. | |||
1035 | // Note that with 'ulimit -s unlimited' the stack is moved away from the top | |||
1036 | // of the address space, so simply checking the stack address is not enough. | |||
1037 | // This should (does) work for both PowerPC64 Endian modes. | |||
1038 | // Similarly, aarch64 has multiple address space layouts: 39, 42 and 47-bit. | |||
1039 | return (1ULL << (MostSignificantSetBitIndex(GET_CURRENT_FRAME()(__sanitizer::uptr) __builtin_frame_address(0)) + 1)) - 1; | |||
1040 | #elif SANITIZER_RISCV640 | |||
1041 | return (1ULL << 38) - 1; | |||
1042 | # elif defined(__mips64) | |||
1043 | return (1ULL << 40) - 1; // 0x000000ffffffffffUL; | |||
1044 | # elif defined(__s390x__) | |||
1045 | return (1ULL << 53) - 1; // 0x001fffffffffffffUL; | |||
1046 | #elif defined(__sparc__) | |||
1047 | return ~(uptr)0; | |||
1048 | # else | |||
1049 | return (1ULL << 47) - 1; // 0x00007fffffffffffUL; | |||
1050 | # endif | |||
1051 | #else // SANITIZER_WORDSIZE == 32 | |||
1052 | # if defined(__s390__) | |||
1053 | return (1ULL << 31) - 1; // 0x7fffffff; | |||
1054 | # else | |||
1055 | return (1ULL << 32) - 1; // 0xffffffff; | |||
1056 | # endif | |||
1057 | #endif // SANITIZER_WORDSIZE | |||
1058 | } | |||
1059 | ||||
1060 | uptr GetMaxUserVirtualAddress() { | |||
1061 | uptr addr = GetMaxVirtualAddress(); | |||
1062 | #if SANITIZER_WORDSIZE64 == 32 && !defined(__s390__) | |||
1063 | if (!common_flags()->full_address_space) | |||
1064 | addr -= GetKernelAreaSize(); | |||
1065 | CHECK_LT(reinterpret_cast<uptr>(&addr), addr)do { __sanitizer::u64 v1 = (__sanitizer::u64)((reinterpret_cast <uptr>(&addr))); __sanitizer::u64 v2 = (__sanitizer ::u64)((addr)); if (__builtin_expect(!!(!(v1 < v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1065, "(" "(reinterpret_cast<uptr>(&addr))" ") " "<" " (" "(addr)" ")", v1, v2); } while (false); | |||
1066 | #endif | |||
1067 | return addr; | |||
1068 | } | |||
1069 | ||||
1070 | #if !SANITIZER_ANDROID0 | |||
1071 | uptr GetPageSize() { | |||
1072 | #if SANITIZER_LINUX1 && (defined(__x86_64__1) || defined(__i386__)) && \ | |||
1073 | defined(EXEC_PAGESIZE4096) | |||
1074 | return EXEC_PAGESIZE4096; | |||
1075 | #elif SANITIZER_FREEBSD0 || SANITIZER_NETBSD0 | |||
1076 | // Use sysctl as sysconf can trigger interceptors internally. | |||
1077 | int pz = 0; | |||
1078 | uptr pzl = sizeof(pz); | |||
1079 | int mib[2] = {CTL_HW, HW_PAGESIZE}; | |||
1080 | int rv = internal_sysctl(mib, 2, &pz, &pzl, nullptr, 0); | |||
1081 | CHECK_EQ(rv, 0)do { __sanitizer::u64 v1 = (__sanitizer::u64)((rv)); __sanitizer ::u64 v2 = (__sanitizer::u64)((0)); if (__builtin_expect(!!(! (v1 == v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1081, "(" "(rv)" ") " "==" " (" "(0)" ")", v1, v2); } while (false); | |||
1082 | return (uptr)pz; | |||
1083 | #elif SANITIZER_USE_GETAUXVAL1 | |||
1084 | return getauxval(AT_PAGESZ6); | |||
1085 | #else | |||
1086 | return sysconf(_SC_PAGESIZE_SC_PAGESIZE); // EXEC_PAGESIZE may not be trustworthy. | |||
1087 | #endif | |||
1088 | } | |||
1089 | #endif // !SANITIZER_ANDROID | |||
1090 | ||||
1091 | uptr ReadBinaryName(/*out*/char *buf, uptr buf_len) { | |||
1092 | #if SANITIZER_SOLARIS0 | |||
1093 | const char *default_module_name = getexecname(); | |||
1094 | CHECK_NE(default_module_name, NULL)do { __sanitizer::u64 v1 = (__sanitizer::u64)((default_module_name )); __sanitizer::u64 v2 = (__sanitizer::u64)((__null)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1094, "(" "(default_module_name)" ") " "!=" " (" "(__null)" ")", v1, v2); } while (false); | |||
1095 | return internal_snprintf(buf, buf_len, "%s", default_module_name); | |||
1096 | #else | |||
1097 | #if SANITIZER_FREEBSD0 || SANITIZER_NETBSD0 | |||
1098 | #if SANITIZER_FREEBSD0 | |||
1099 | const int Mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; | |||
1100 | #else | |||
1101 | const int Mib[4] = {CTL_KERN, KERN_PROC_ARGS, -1, KERN_PROC_PATHNAME}; | |||
1102 | #endif | |||
1103 | const char *default_module_name = "kern.proc.pathname"; | |||
1104 | uptr Size = buf_len; | |||
1105 | bool IsErr = | |||
1106 | (internal_sysctl(Mib, ARRAY_SIZE(Mib)(sizeof(Mib)/sizeof((Mib)[0])), buf, &Size, NULL__null, 0) != 0); | |||
1107 | int readlink_error = IsErr ? errno(*__errno_location ()) : 0; | |||
1108 | uptr module_name_len = Size; | |||
1109 | #else | |||
1110 | const char *default_module_name = "/proc/self/exe"; | |||
1111 | uptr module_name_len = internal_readlink( | |||
1112 | default_module_name, buf, buf_len); | |||
1113 | int readlink_error; | |||
1114 | bool IsErr = internal_iserror(module_name_len, &readlink_error); | |||
1115 | #endif // SANITIZER_SOLARIS | |||
1116 | if (IsErr) { | |||
1117 | // We can't read binary name for some reason, assume it's unknown. | |||
1118 | Report("WARNING: reading executable name failed with errno %d, " | |||
1119 | "some stack frames may not be symbolized\n", readlink_error); | |||
1120 | module_name_len = internal_snprintf(buf, buf_len, "%s", | |||
1121 | default_module_name); | |||
1122 | CHECK_LT(module_name_len, buf_len)do { __sanitizer::u64 v1 = (__sanitizer::u64)((module_name_len )); __sanitizer::u64 v2 = (__sanitizer::u64)((buf_len)); if ( __builtin_expect(!!(!(v1 < v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1122, "(" "(module_name_len)" ") " "<" " (" "(buf_len)" ")" , v1, v2); } while (false); | |||
1123 | } | |||
1124 | return module_name_len; | |||
1125 | #endif | |||
1126 | } | |||
1127 | ||||
1128 | uptr ReadLongProcessName(/*out*/ char *buf, uptr buf_len) { | |||
1129 | #if SANITIZER_LINUX1 | |||
1130 | char *tmpbuf; | |||
1131 | uptr tmpsize; | |||
1132 | uptr tmplen; | |||
1133 | if (ReadFileToBuffer("/proc/self/cmdline", &tmpbuf, &tmpsize, &tmplen, | |||
1134 | 1024 * 1024)) { | |||
1135 | internal_strncpy(buf, tmpbuf, buf_len); | |||
1136 | UnmapOrDie(tmpbuf, tmpsize); | |||
1137 | return internal_strlen(buf); | |||
1138 | } | |||
1139 | #endif | |||
1140 | return ReadBinaryName(buf, buf_len); | |||
1141 | } | |||
1142 | ||||
1143 | // Match full names of the form /path/to/base_name{-,.}* | |||
1144 | bool LibraryNameIs(const char *full_name, const char *base_name) { | |||
1145 | const char *name = full_name; | |||
1146 | // Strip path. | |||
1147 | while (*name != '\0') name++; | |||
1148 | while (name > full_name && *name != '/') name--; | |||
1149 | if (*name == '/') name++; | |||
1150 | uptr base_name_length = internal_strlen(base_name); | |||
1151 | if (internal_strncmp(name, base_name, base_name_length)) return false; | |||
1152 | return (name[base_name_length] == '-' || name[base_name_length] == '.'); | |||
1153 | } | |||
1154 | ||||
1155 | #if !SANITIZER_ANDROID0 | |||
1156 | // Call cb for each region mapped by map. | |||
1157 | void ForEachMappedRegion(link_map *map, void (*cb)(const void *, uptr)) { | |||
1158 | CHECK_NE(map, nullptr)do { __sanitizer::u64 v1 = (__sanitizer::u64)((map)); __sanitizer ::u64 v2 = (__sanitizer::u64)((nullptr)); if (__builtin_expect (!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1158, "(" "(map)" ") " "!=" " (" "(nullptr)" ")", v1, v2); } while (false); | |||
1159 | #if !SANITIZER_FREEBSD0 | |||
1160 | typedef ElfW(Phdr)Elf64_Phdr Elf_Phdr; | |||
1161 | typedef ElfW(Ehdr)Elf64_Ehdr Elf_Ehdr; | |||
1162 | #endif // !SANITIZER_FREEBSD | |||
1163 | char *base = (char *)map->l_addr; | |||
1164 | Elf_Ehdr *ehdr = (Elf_Ehdr *)base; | |||
1165 | char *phdrs = base + ehdr->e_phoff; | |||
1166 | char *phdrs_end = phdrs + ehdr->e_phnum * ehdr->e_phentsize; | |||
1167 | ||||
1168 | // Find the segment with the minimum base so we can "relocate" the p_vaddr | |||
1169 | // fields. Typically ET_DYN objects (DSOs) have base of zero and ET_EXEC | |||
1170 | // objects have a non-zero base. | |||
1171 | uptr preferred_base = (uptr)-1; | |||
1172 | for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { | |||
1173 | Elf_Phdr *phdr = (Elf_Phdr *)iter; | |||
1174 | if (phdr->p_type == PT_LOAD1 && preferred_base > (uptr)phdr->p_vaddr) | |||
1175 | preferred_base = (uptr)phdr->p_vaddr; | |||
1176 | } | |||
1177 | ||||
1178 | // Compute the delta from the real base to get a relocation delta. | |||
1179 | sptr delta = (uptr)base - preferred_base; | |||
1180 | // Now we can figure out what the loader really mapped. | |||
1181 | for (char *iter = phdrs; iter != phdrs_end; iter += ehdr->e_phentsize) { | |||
1182 | Elf_Phdr *phdr = (Elf_Phdr *)iter; | |||
1183 | if (phdr->p_type == PT_LOAD1) { | |||
1184 | uptr seg_start = phdr->p_vaddr + delta; | |||
1185 | uptr seg_end = seg_start + phdr->p_memsz; | |||
1186 | // None of these values are aligned. We consider the ragged edges of the | |||
1187 | // load command as defined, since they are mapped from the file. | |||
1188 | seg_start = RoundDownTo(seg_start, GetPageSizeCached()); | |||
1189 | seg_end = RoundUpTo(seg_end, GetPageSizeCached()); | |||
1190 | cb((void *)seg_start, seg_end - seg_start); | |||
1191 | } | |||
1192 | } | |||
1193 | } | |||
1194 | #endif | |||
1195 | ||||
1196 | #if defined(__x86_64__1) && SANITIZER_LINUX1 | |||
1197 | // We cannot use glibc's clone wrapper, because it messes with the child | |||
1198 | // task's TLS. It writes the PID and TID of the child task to its thread | |||
1199 | // descriptor, but in our case the child task shares the thread descriptor with | |||
1200 | // the parent (because we don't know how to allocate a new thread | |||
1201 | // descriptor to keep glibc happy). So the stock version of clone(), when | |||
1202 | // used with CLONE_VM, would end up corrupting the parent's thread descriptor. | |||
1203 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1204 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1205 | long long res; | |||
1206 | if (!fn || !child_stack) | |||
1207 | return -EINVAL22; | |||
1208 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1208, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||
1209 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||
1210 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||
1211 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||
1212 | register void *r8 __asm__("r8") = newtls; | |||
1213 | register int *r10 __asm__("r10") = child_tidptr; | |||
1214 | __asm__ __volatile__( | |||
1215 | /* %rax = syscall(%rax = SYSCALL(clone), | |||
1216 | * %rdi = flags, | |||
1217 | * %rsi = child_stack, | |||
1218 | * %rdx = parent_tidptr, | |||
1219 | * %r8 = new_tls, | |||
1220 | * %r10 = child_tidptr) | |||
1221 | */ | |||
1222 | "syscall\n" | |||
1223 | ||||
1224 | /* if (%rax != 0) | |||
1225 | * return; | |||
1226 | */ | |||
1227 | "testq %%rax,%%rax\n" | |||
1228 | "jnz 1f\n" | |||
1229 | ||||
1230 | /* In the child. Terminate unwind chain. */ | |||
1231 | // XXX: We should also terminate the CFI unwind chain | |||
1232 | // here. Unfortunately clang 3.2 doesn't support the | |||
1233 | // necessary CFI directives, so we skip that part. | |||
1234 | "xorq %%rbp,%%rbp\n" | |||
1235 | ||||
1236 | /* Call "fn(arg)". */ | |||
1237 | "popq %%rax\n" | |||
1238 | "popq %%rdi\n" | |||
1239 | "call *%%rax\n" | |||
1240 | ||||
1241 | /* Call _exit(%rax). */ | |||
1242 | "movq %%rax,%%rdi\n" | |||
1243 | "movq %2,%%rax\n" | |||
1244 | "syscall\n" | |||
1245 | ||||
1246 | /* Return to parent. */ | |||
1247 | "1:\n" | |||
1248 | : "=a" (res) | |||
1249 | : "a"(SYSCALL(clone)56), "i"(SYSCALL(exit)60), | |||
1250 | "S"(child_stack), | |||
1251 | "D"(flags), | |||
1252 | "d"(parent_tidptr), | |||
1253 | "r"(r8), | |||
1254 | "r"(r10) | |||
1255 | : "memory", "r11", "rcx"); | |||
1256 | return res; | |||
1257 | } | |||
1258 | #elif defined(__mips__) | |||
1259 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1260 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1261 | long long res; | |||
1262 | if (!fn || !child_stack) | |||
1263 | return -EINVAL22; | |||
1264 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1264, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||
1265 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||
1266 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||
1267 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||
1268 | register void *a3 __asm__("$7") = newtls; | |||
1269 | register int *a4 __asm__("$8") = child_tidptr; | |||
1270 | // We don't have proper CFI directives here because it requires alot of code | |||
1271 | // for very marginal benefits. | |||
1272 | __asm__ __volatile__( | |||
1273 | /* $v0 = syscall($v0 = __NR_clone, | |||
1274 | * $a0 = flags, | |||
1275 | * $a1 = child_stack, | |||
1276 | * $a2 = parent_tidptr, | |||
1277 | * $a3 = new_tls, | |||
1278 | * $a4 = child_tidptr) | |||
1279 | */ | |||
1280 | ".cprestore 16;\n" | |||
1281 | "move $4,%1;\n" | |||
1282 | "move $5,%2;\n" | |||
1283 | "move $6,%3;\n" | |||
1284 | "move $7,%4;\n" | |||
1285 | /* Store the fifth argument on stack | |||
1286 | * if we are using 32-bit abi. | |||
1287 | */ | |||
1288 | #if SANITIZER_WORDSIZE64 == 32 | |||
1289 | "lw %5,16($29);\n" | |||
1290 | #else | |||
1291 | "move $8,%5;\n" | |||
1292 | #endif | |||
1293 | "li $2,%6;\n" | |||
1294 | "syscall;\n" | |||
1295 | ||||
1296 | /* if ($v0 != 0) | |||
1297 | * return; | |||
1298 | */ | |||
1299 | "bnez $2,1f;\n" | |||
1300 | ||||
1301 | /* Call "fn(arg)". */ | |||
1302 | #if SANITIZER_WORDSIZE64 == 32 | |||
1303 | #ifdef __BIG_ENDIAN__ | |||
1304 | "lw $25,4($29);\n" | |||
1305 | "lw $4,12($29);\n" | |||
1306 | #else | |||
1307 | "lw $25,0($29);\n" | |||
1308 | "lw $4,8($29);\n" | |||
1309 | #endif | |||
1310 | #else | |||
1311 | "ld $25,0($29);\n" | |||
1312 | "ld $4,8($29);\n" | |||
1313 | #endif | |||
1314 | "jal $25;\n" | |||
1315 | ||||
1316 | /* Call _exit($v0). */ | |||
1317 | "move $4,$2;\n" | |||
1318 | "li $2,%7;\n" | |||
1319 | "syscall;\n" | |||
1320 | ||||
1321 | /* Return to parent. */ | |||
1322 | "1:\n" | |||
1323 | : "=r" (res) | |||
1324 | : "r"(flags), | |||
1325 | "r"(child_stack), | |||
1326 | "r"(parent_tidptr), | |||
1327 | "r"(a3), | |||
1328 | "r"(a4), | |||
1329 | "i"(__NR_clone56), | |||
1330 | "i"(__NR_exit60) | |||
1331 | : "memory", "$29" ); | |||
1332 | return res; | |||
1333 | } | |||
1334 | #elif SANITIZER_RISCV640 | |||
1335 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1336 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1337 | long long res; | |||
1338 | if (!fn || !child_stack) | |||
1339 | return -EINVAL22; | |||
1340 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1340, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||
1341 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||
1342 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||
1343 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||
1344 | ||||
1345 | register int (*__fn)(void *) __asm__("a0") = fn; | |||
1346 | register void *__stack __asm__("a1") = child_stack; | |||
1347 | register int __flags __asm__("a2") = flags; | |||
1348 | register void *__arg __asm__("a3") = arg; | |||
1349 | register int *__ptid __asm__("a4") = parent_tidptr; | |||
1350 | register void *__tls __asm__("a5") = newtls; | |||
1351 | register int *__ctid __asm__("a6") = child_tidptr; | |||
1352 | ||||
1353 | __asm__ __volatile__( | |||
1354 | "mv a0,a2\n" /* flags */ | |||
1355 | "mv a2,a4\n" /* ptid */ | |||
1356 | "mv a3,a5\n" /* tls */ | |||
1357 | "mv a4,a6\n" /* ctid */ | |||
1358 | "addi a7, zero, %9\n" /* clone */ | |||
1359 | ||||
1360 | "ecall\n" | |||
1361 | ||||
1362 | /* if (%r0 != 0) | |||
1363 | * return %r0; | |||
1364 | */ | |||
1365 | "bnez a0, 1f\n" | |||
1366 | ||||
1367 | /* In the child, now. Call "fn(arg)". */ | |||
1368 | "ld a0, 8(sp)\n" | |||
1369 | "ld a1, 16(sp)\n" | |||
1370 | "jalr a1\n" | |||
1371 | ||||
1372 | /* Call _exit(%r0). */ | |||
1373 | "addi a7, zero, %10\n" | |||
1374 | "ecall\n" | |||
1375 | "1:\n" | |||
1376 | ||||
1377 | : "=r"(res) | |||
1378 | : "i"(-EINVAL22), "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg), | |||
1379 | "r"(__ptid), "r"(__tls), "r"(__ctid), "i"(__NR_clone56), "i"(__NR_exit60) | |||
1380 | : "ra", "memory"); | |||
1381 | return res; | |||
1382 | } | |||
1383 | #elif defined(__aarch64__) | |||
1384 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1385 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1386 | long long res; | |||
1387 | if (!fn || !child_stack) | |||
1388 | return -EINVAL22; | |||
1389 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1389, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||
1390 | child_stack = (char *)child_stack - 2 * sizeof(unsigned long long); | |||
1391 | ((unsigned long long *)child_stack)[0] = (uptr)fn; | |||
1392 | ((unsigned long long *)child_stack)[1] = (uptr)arg; | |||
1393 | ||||
1394 | register int (*__fn)(void *) __asm__("x0") = fn; | |||
1395 | register void *__stack __asm__("x1") = child_stack; | |||
1396 | register int __flags __asm__("x2") = flags; | |||
1397 | register void *__arg __asm__("x3") = arg; | |||
1398 | register int *__ptid __asm__("x4") = parent_tidptr; | |||
1399 | register void *__tls __asm__("x5") = newtls; | |||
1400 | register int *__ctid __asm__("x6") = child_tidptr; | |||
1401 | ||||
1402 | __asm__ __volatile__( | |||
1403 | "mov x0,x2\n" /* flags */ | |||
1404 | "mov x2,x4\n" /* ptid */ | |||
1405 | "mov x3,x5\n" /* tls */ | |||
1406 | "mov x4,x6\n" /* ctid */ | |||
1407 | "mov x8,%9\n" /* clone */ | |||
1408 | ||||
1409 | "svc 0x0\n" | |||
1410 | ||||
1411 | /* if (%r0 != 0) | |||
1412 | * return %r0; | |||
1413 | */ | |||
1414 | "cmp x0, #0\n" | |||
1415 | "bne 1f\n" | |||
1416 | ||||
1417 | /* In the child, now. Call "fn(arg)". */ | |||
1418 | "ldp x1, x0, [sp], #16\n" | |||
1419 | "blr x1\n" | |||
1420 | ||||
1421 | /* Call _exit(%r0). */ | |||
1422 | "mov x8, %10\n" | |||
1423 | "svc 0x0\n" | |||
1424 | "1:\n" | |||
1425 | ||||
1426 | : "=r" (res) | |||
1427 | : "i"(-EINVAL22), | |||
1428 | "r"(__fn), "r"(__stack), "r"(__flags), "r"(__arg), | |||
1429 | "r"(__ptid), "r"(__tls), "r"(__ctid), | |||
1430 | "i"(__NR_clone56), "i"(__NR_exit60) | |||
1431 | : "x30", "memory"); | |||
1432 | return res; | |||
1433 | } | |||
1434 | #elif defined(__powerpc64__) | |||
1435 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1436 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1437 | long long res; | |||
1438 | // Stack frame structure. | |||
1439 | #if SANITIZER_PPC64V10 | |||
1440 | // Back chain == 0 (SP + 112) | |||
1441 | // Frame (112 bytes): | |||
1442 | // Parameter save area (SP + 48), 8 doublewords | |||
1443 | // TOC save area (SP + 40) | |||
1444 | // Link editor doubleword (SP + 32) | |||
1445 | // Compiler doubleword (SP + 24) | |||
1446 | // LR save area (SP + 16) | |||
1447 | // CR save area (SP + 8) | |||
1448 | // Back chain (SP + 0) | |||
1449 | # define FRAME_SIZE 112 | |||
1450 | # define FRAME_TOC_SAVE_OFFSET 40 | |||
1451 | #elif SANITIZER_PPC64V20 | |||
1452 | // Back chain == 0 (SP + 32) | |||
1453 | // Frame (32 bytes): | |||
1454 | // TOC save area (SP + 24) | |||
1455 | // LR save area (SP + 16) | |||
1456 | // CR save area (SP + 8) | |||
1457 | // Back chain (SP + 0) | |||
1458 | # define FRAME_SIZE 32 | |||
1459 | # define FRAME_TOC_SAVE_OFFSET 24 | |||
1460 | #else | |||
1461 | # error "Unsupported PPC64 ABI" | |||
1462 | #endif | |||
1463 | if (!fn || !child_stack) | |||
1464 | return -EINVAL22; | |||
1465 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1465, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||
1466 | ||||
1467 | register int (*__fn)(void *) __asm__("r3") = fn; | |||
1468 | register void *__cstack __asm__("r4") = child_stack; | |||
1469 | register int __flags __asm__("r5") = flags; | |||
1470 | register void *__arg __asm__("r6") = arg; | |||
1471 | register int *__ptidptr __asm__("r7") = parent_tidptr; | |||
1472 | register void *__newtls __asm__("r8") = newtls; | |||
1473 | register int *__ctidptr __asm__("r9") = child_tidptr; | |||
1474 | ||||
1475 | __asm__ __volatile__( | |||
1476 | /* fn and arg are saved across the syscall */ | |||
1477 | "mr 28, %5\n\t" | |||
1478 | "mr 27, %8\n\t" | |||
1479 | ||||
1480 | /* syscall | |||
1481 | r0 == __NR_clone | |||
1482 | r3 == flags | |||
1483 | r4 == child_stack | |||
1484 | r5 == parent_tidptr | |||
1485 | r6 == newtls | |||
1486 | r7 == child_tidptr */ | |||
1487 | "mr 3, %7\n\t" | |||
1488 | "mr 5, %9\n\t" | |||
1489 | "mr 6, %10\n\t" | |||
1490 | "mr 7, %11\n\t" | |||
1491 | "li 0, %3\n\t" | |||
1492 | "sc\n\t" | |||
1493 | ||||
1494 | /* Test if syscall was successful */ | |||
1495 | "cmpdi cr1, 3, 0\n\t" | |||
1496 | "crandc cr1*4+eq, cr1*4+eq, cr0*4+so\n\t" | |||
1497 | "bne- cr1, 1f\n\t" | |||
1498 | ||||
1499 | /* Set up stack frame */ | |||
1500 | "li 29, 0\n\t" | |||
1501 | "stdu 29, -8(1)\n\t" | |||
1502 | "stdu 1, -%12(1)\n\t" | |||
1503 | /* Do the function call */ | |||
1504 | "std 2, %13(1)\n\t" | |||
1505 | #if SANITIZER_PPC64V10 | |||
1506 | "ld 0, 0(28)\n\t" | |||
1507 | "ld 2, 8(28)\n\t" | |||
1508 | "mtctr 0\n\t" | |||
1509 | #elif SANITIZER_PPC64V20 | |||
1510 | "mr 12, 28\n\t" | |||
1511 | "mtctr 12\n\t" | |||
1512 | #else | |||
1513 | # error "Unsupported PPC64 ABI" | |||
1514 | #endif | |||
1515 | "mr 3, 27\n\t" | |||
1516 | "bctrl\n\t" | |||
1517 | "ld 2, %13(1)\n\t" | |||
1518 | ||||
1519 | /* Call _exit(r3) */ | |||
1520 | "li 0, %4\n\t" | |||
1521 | "sc\n\t" | |||
1522 | ||||
1523 | /* Return to parent */ | |||
1524 | "1:\n\t" | |||
1525 | "mr %0, 3\n\t" | |||
1526 | : "=r" (res) | |||
1527 | : "0" (-1), | |||
1528 | "i" (EINVAL22), | |||
1529 | "i" (__NR_clone56), | |||
1530 | "i" (__NR_exit60), | |||
1531 | "r" (__fn), | |||
1532 | "r" (__cstack), | |||
1533 | "r" (__flags), | |||
1534 | "r" (__arg), | |||
1535 | "r" (__ptidptr), | |||
1536 | "r" (__newtls), | |||
1537 | "r" (__ctidptr), | |||
1538 | "i" (FRAME_SIZE), | |||
1539 | "i" (FRAME_TOC_SAVE_OFFSET) | |||
1540 | : "cr0", "cr1", "memory", "ctr", "r0", "r27", "r28", "r29"); | |||
1541 | return res; | |||
1542 | } | |||
1543 | #elif defined(__i386__) && SANITIZER_LINUX1 | |||
1544 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1545 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1546 | int res; | |||
1547 | if (!fn || !child_stack) | |||
1548 | return -EINVAL22; | |||
1549 | CHECK_EQ(0, (uptr)child_stack % 16)do { __sanitizer::u64 v1 = (__sanitizer::u64)((0)); __sanitizer ::u64 v2 = (__sanitizer::u64)(((uptr)child_stack % 16)); if ( __builtin_expect(!!(!(v1 == v2)), 0)) __sanitizer::CheckFailed ("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 1549, "(" "(0)" ") " "==" " (" "((uptr)child_stack % 16)" ")" , v1, v2); } while (false); | |||
1550 | child_stack = (char *)child_stack - 7 * sizeof(unsigned int); | |||
1551 | ((unsigned int *)child_stack)[0] = (uptr)flags; | |||
1552 | ((unsigned int *)child_stack)[1] = (uptr)0; | |||
1553 | ((unsigned int *)child_stack)[2] = (uptr)fn; | |||
1554 | ((unsigned int *)child_stack)[3] = (uptr)arg; | |||
1555 | __asm__ __volatile__( | |||
1556 | /* %eax = syscall(%eax = SYSCALL(clone), | |||
1557 | * %ebx = flags, | |||
1558 | * %ecx = child_stack, | |||
1559 | * %edx = parent_tidptr, | |||
1560 | * %esi = new_tls, | |||
1561 | * %edi = child_tidptr) | |||
1562 | */ | |||
1563 | ||||
1564 | /* Obtain flags */ | |||
1565 | "movl (%%ecx), %%ebx\n" | |||
1566 | /* Do the system call */ | |||
1567 | "pushl %%ebx\n" | |||
1568 | "pushl %%esi\n" | |||
1569 | "pushl %%edi\n" | |||
1570 | /* Remember the flag value. */ | |||
1571 | "movl %%ebx, (%%ecx)\n" | |||
1572 | "int $0x80\n" | |||
1573 | "popl %%edi\n" | |||
1574 | "popl %%esi\n" | |||
1575 | "popl %%ebx\n" | |||
1576 | ||||
1577 | /* if (%eax != 0) | |||
1578 | * return; | |||
1579 | */ | |||
1580 | ||||
1581 | "test %%eax,%%eax\n" | |||
1582 | "jnz 1f\n" | |||
1583 | ||||
1584 | /* terminate the stack frame */ | |||
1585 | "xorl %%ebp,%%ebp\n" | |||
1586 | /* Call FN. */ | |||
1587 | "call *%%ebx\n" | |||
1588 | #ifdef PIC | |||
1589 | "call here\n" | |||
1590 | "here:\n" | |||
1591 | "popl %%ebx\n" | |||
1592 | "addl $_GLOBAL_OFFSET_TABLE_+[.-here], %%ebx\n" | |||
1593 | #endif | |||
1594 | /* Call exit */ | |||
1595 | "movl %%eax, %%ebx\n" | |||
1596 | "movl %2, %%eax\n" | |||
1597 | "int $0x80\n" | |||
1598 | "1:\n" | |||
1599 | : "=a" (res) | |||
1600 | : "a"(SYSCALL(clone)56), "i"(SYSCALL(exit)60), | |||
1601 | "c"(child_stack), | |||
1602 | "d"(parent_tidptr), | |||
1603 | "S"(newtls), | |||
1604 | "D"(child_tidptr) | |||
1605 | : "memory"); | |||
1606 | return res; | |||
1607 | } | |||
1608 | #elif defined(__arm__) && SANITIZER_LINUX1 | |||
1609 | uptr internal_clone(int (*fn)(void *), void *child_stack, int flags, void *arg, | |||
1610 | int *parent_tidptr, void *newtls, int *child_tidptr) { | |||
1611 | unsigned int res; | |||
1612 | if (!fn || !child_stack) | |||
1613 | return -EINVAL22; | |||
1614 | child_stack = (char *)child_stack - 2 * sizeof(unsigned int); | |||
1615 | ((unsigned int *)child_stack)[0] = (uptr)fn; | |||
1616 | ((unsigned int *)child_stack)[1] = (uptr)arg; | |||
1617 | register int r0 __asm__("r0") = flags; | |||
1618 | register void *r1 __asm__("r1") = child_stack; | |||
1619 | register int *r2 __asm__("r2") = parent_tidptr; | |||
1620 | register void *r3 __asm__("r3") = newtls; | |||
1621 | register int *r4 __asm__("r4") = child_tidptr; | |||
1622 | register int r7 __asm__("r7") = __NR_clone56; | |||
1623 | ||||
1624 | #if __ARM_ARCH > 4 || defined (__ARM_ARCH_4T__) | |||
1625 | # define ARCH_HAS_BX | |||
1626 | #endif | |||
1627 | #if __ARM_ARCH > 4 | |||
1628 | # define ARCH_HAS_BLX | |||
1629 | #endif | |||
1630 | ||||
1631 | #ifdef ARCH_HAS_BX | |||
1632 | # ifdef ARCH_HAS_BLX | |||
1633 | # define BLX(R) "blx " #R "\n" | |||
1634 | # else | |||
1635 | # define BLX(R) "mov lr, pc; bx " #R "\n" | |||
1636 | # endif | |||
1637 | #else | |||
1638 | # define BLX(R) "mov lr, pc; mov pc," #R "\n" | |||
1639 | #endif | |||
1640 | ||||
1641 | __asm__ __volatile__( | |||
1642 | /* %r0 = syscall(%r7 = SYSCALL(clone), | |||
1643 | * %r0 = flags, | |||
1644 | * %r1 = child_stack, | |||
1645 | * %r2 = parent_tidptr, | |||
1646 | * %r3 = new_tls, | |||
1647 | * %r4 = child_tidptr) | |||
1648 | */ | |||
1649 | ||||
1650 | /* Do the system call */ | |||
1651 | "swi 0x0\n" | |||
1652 | ||||
1653 | /* if (%r0 != 0) | |||
1654 | * return %r0; | |||
1655 | */ | |||
1656 | "cmp r0, #0\n" | |||
1657 | "bne 1f\n" | |||
1658 | ||||
1659 | /* In the child, now. Call "fn(arg)". */ | |||
1660 | "ldr r0, [sp, #4]\n" | |||
1661 | "ldr ip, [sp], #8\n" | |||
1662 | BLX(ip) | |||
1663 | /* Call _exit(%r0). */ | |||
1664 | "mov r7, %7\n" | |||
1665 | "swi 0x0\n" | |||
1666 | "1:\n" | |||
1667 | "mov %0, r0\n" | |||
1668 | : "=r"(res) | |||
1669 | : "r"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r7), | |||
1670 | "i"(__NR_exit60) | |||
1671 | : "memory"); | |||
1672 | return res; | |||
1673 | } | |||
1674 | #endif // defined(__x86_64__) && SANITIZER_LINUX | |||
1675 | ||||
1676 | #if SANITIZER_LINUX1 | |||
1677 | int internal_uname(struct utsname *buf) { | |||
1678 | return internal_syscall(SYSCALL(uname)63, buf); | |||
1679 | } | |||
1680 | #endif | |||
1681 | ||||
1682 | #if SANITIZER_ANDROID0 | |||
1683 | #if __ANDROID_API__ < 21 | |||
1684 | extern "C" __attribute__((weak)) int dl_iterate_phdr( | |||
1685 | int (*)(struct dl_phdr_info *, size_t, void *), void *); | |||
1686 | #endif | |||
1687 | ||||
1688 | static int dl_iterate_phdr_test_cb(struct dl_phdr_info *info, size_t size, | |||
1689 | void *data) { | |||
1690 | // Any name starting with "lib" indicates a bug in L where library base names | |||
1691 | // are returned instead of paths. | |||
1692 | if (info->dlpi_name && info->dlpi_name[0] == 'l' && | |||
1693 | info->dlpi_name[1] == 'i' && info->dlpi_name[2] == 'b') { | |||
1694 | *(bool *)data = true; | |||
1695 | return 1; | |||
1696 | } | |||
1697 | return 0; | |||
1698 | } | |||
1699 | ||||
1700 | static atomic_uint32_t android_api_level; | |||
1701 | ||||
1702 | static AndroidApiLevel AndroidDetectApiLevelStatic() { | |||
1703 | #if __ANDROID_API__ <= 19 | |||
1704 | return ANDROID_KITKAT; | |||
1705 | #elif __ANDROID_API__ <= 22 | |||
1706 | return ANDROID_LOLLIPOP_MR1; | |||
1707 | #else | |||
1708 | return ANDROID_POST_LOLLIPOP; | |||
1709 | #endif | |||
1710 | } | |||
1711 | ||||
1712 | static AndroidApiLevel AndroidDetectApiLevel() { | |||
1713 | if (!&dl_iterate_phdr) | |||
1714 | return ANDROID_KITKAT; // K or lower | |||
1715 | bool base_name_seen = false; | |||
1716 | dl_iterate_phdr(dl_iterate_phdr_test_cb, &base_name_seen); | |||
1717 | if (base_name_seen) | |||
1718 | return ANDROID_LOLLIPOP_MR1; // L MR1 | |||
1719 | return ANDROID_POST_LOLLIPOP; // post-L | |||
1720 | // Plain L (API level 21) is completely broken wrt ASan and not very | |||
1721 | // interesting to detect. | |||
1722 | } | |||
1723 | ||||
1724 | extern "C" __attribute__((weak)) void* _DYNAMIC; | |||
1725 | ||||
1726 | AndroidApiLevel AndroidGetApiLevel() { | |||
1727 | AndroidApiLevel level = | |||
1728 | (AndroidApiLevel)atomic_load(&android_api_level, memory_order_relaxed); | |||
1729 | if (level) return level; | |||
1730 | level = &_DYNAMIC == nullptr ? AndroidDetectApiLevelStatic() | |||
1731 | : AndroidDetectApiLevel(); | |||
1732 | atomic_store(&android_api_level, level, memory_order_relaxed); | |||
1733 | return level; | |||
1734 | } | |||
1735 | ||||
1736 | #endif | |||
1737 | ||||
1738 | static HandleSignalMode GetHandleSignalModeImpl(int signum) { | |||
1739 | switch (signum) { | |||
1740 | case SIGABRT6: | |||
1741 | return common_flags()->handle_abort; | |||
1742 | case SIGILL4: | |||
1743 | return common_flags()->handle_sigill; | |||
1744 | case SIGTRAP5: | |||
1745 | return common_flags()->handle_sigtrap; | |||
1746 | case SIGFPE8: | |||
1747 | return common_flags()->handle_sigfpe; | |||
1748 | case SIGSEGV11: | |||
1749 | return common_flags()->handle_segv; | |||
1750 | case SIGBUS7: | |||
1751 | return common_flags()->handle_sigbus; | |||
1752 | } | |||
1753 | return kHandleSignalNo; | |||
1754 | } | |||
1755 | ||||
1756 | HandleSignalMode GetHandleSignalMode(int signum) { | |||
1757 | HandleSignalMode result = GetHandleSignalModeImpl(signum); | |||
1758 | if (result == kHandleSignalYes && !common_flags()->allow_user_segv_handler) | |||
1759 | return kHandleSignalExclusive; | |||
1760 | return result; | |||
1761 | } | |||
1762 | ||||
1763 | #if !SANITIZER_GO0 | |||
1764 | void *internal_start_thread(void *(*func)(void *arg), void *arg) { | |||
1765 | // Start the thread with signals blocked, otherwise it can steal user signals. | |||
1766 | __sanitizer_sigset_t set, old; | |||
1767 | internal_sigfillset(&set); | |||
1768 | #if SANITIZER_LINUX1 && !SANITIZER_ANDROID0 | |||
1769 | // Glibc uses SIGSETXID signal during setuid call. If this signal is blocked | |||
1770 | // on any thread, setuid call hangs (see test/tsan/setuid.c). | |||
1771 | internal_sigdelset(&set, 33); | |||
1772 | #endif | |||
1773 | internal_sigprocmask(SIG_SETMASK2, &set, &old); | |||
1774 | void *th; | |||
1775 | real_pthread_create(&th, nullptr, func, arg); | |||
1776 | internal_sigprocmask(SIG_SETMASK2, &old, nullptr); | |||
1777 | return th; | |||
1778 | } | |||
1779 | ||||
1780 | void internal_join_thread(void *th) { | |||
1781 | real_pthread_join(th, nullptr); | |||
1782 | } | |||
1783 | #else | |||
1784 | void *internal_start_thread(void *(*func)(void *), void *arg) { return 0; } | |||
1785 | ||||
1786 | void internal_join_thread(void *th) {} | |||
1787 | #endif | |||
1788 | ||||
1789 | #if defined(__aarch64__) | |||
1790 | // Android headers in the older NDK releases miss this definition. | |||
1791 | struct __sanitizer_esr_context { | |||
1792 | struct _aarch64_ctx head; | |||
1793 | uint64_t esr; | |||
1794 | }; | |||
1795 | ||||
1796 | static bool Aarch64GetESR(ucontext_t *ucontext, u64 *esr) { | |||
1797 | static const u32 kEsrMagic = 0x45535201; | |||
1798 | u8 *aux = ucontext->uc_mcontext.__reserved; | |||
1799 | while (true) { | |||
1800 | _aarch64_ctx *ctx = (_aarch64_ctx *)aux; | |||
1801 | if (ctx->size == 0) break; | |||
1802 | if (ctx->magic == kEsrMagic) { | |||
1803 | *esr = ((__sanitizer_esr_context *)ctx)->esr; | |||
1804 | return true; | |||
1805 | } | |||
1806 | aux += ctx->size; | |||
1807 | } | |||
1808 | return false; | |||
1809 | } | |||
1810 | #endif | |||
1811 | ||||
1812 | using Context = ucontext_t; | |||
1813 | ||||
1814 | SignalContext::WriteFlag SignalContext::GetWriteFlag() const { | |||
1815 | Context *ucontext = (Context *)context; | |||
1816 | #if defined(__x86_64__1) || defined(__i386__) | |||
1817 | static const uptr PF_WRITE = 1U << 1; | |||
1818 | #if SANITIZER_FREEBSD0 | |||
1819 | uptr err = ucontext->uc_mcontext.mc_err; | |||
1820 | #elif SANITIZER_NETBSD0 | |||
1821 | uptr err = ucontext->uc_mcontext.__gregs[_REG_ERR]; | |||
1822 | #elif SANITIZER_SOLARIS0 && defined(__i386__) | |||
1823 | const int Err = 13; | |||
1824 | uptr err = ucontext->uc_mcontext.gregs[Err]; | |||
1825 | #else | |||
1826 | uptr err = ucontext->uc_mcontext.gregs[REG_ERRREG_ERR]; | |||
1827 | #endif // SANITIZER_FREEBSD | |||
1828 | return err & PF_WRITE ? WRITE : READ; | |||
1829 | #elif defined(__mips__) | |||
1830 | uint32_t *exception_source; | |||
1831 | uint32_t faulty_instruction; | |||
1832 | uint32_t op_code; | |||
1833 | ||||
1834 | exception_source = (uint32_t *)ucontext->uc_mcontext.pc; | |||
1835 | faulty_instruction = (uint32_t)(*exception_source); | |||
1836 | ||||
1837 | op_code = (faulty_instruction >> 26) & 0x3f; | |||
1838 | ||||
1839 | // FIXME: Add support for FPU, microMIPS, DSP, MSA memory instructions. | |||
1840 | switch (op_code) { | |||
1841 | case 0x28: // sb | |||
1842 | case 0x29: // sh | |||
1843 | case 0x2b: // sw | |||
1844 | case 0x3f: // sd | |||
1845 | #if __mips_isa_rev < 6 | |||
1846 | case 0x2c: // sdl | |||
1847 | case 0x2d: // sdr | |||
1848 | case 0x2a: // swl | |||
1849 | case 0x2e: // swr | |||
1850 | #endif | |||
1851 | return SignalContext::WRITE; | |||
1852 | ||||
1853 | case 0x20: // lb | |||
1854 | case 0x24: // lbu | |||
1855 | case 0x21: // lh | |||
1856 | case 0x25: // lhu | |||
1857 | case 0x23: // lw | |||
1858 | case 0x27: // lwu | |||
1859 | case 0x37: // ld | |||
1860 | #if __mips_isa_rev < 6 | |||
1861 | case 0x1a: // ldl | |||
1862 | case 0x1b: // ldr | |||
1863 | case 0x22: // lwl | |||
1864 | case 0x26: // lwr | |||
1865 | #endif | |||
1866 | return SignalContext::READ; | |||
1867 | #if __mips_isa_rev == 6 | |||
1868 | case 0x3b: // pcrel | |||
1869 | op_code = (faulty_instruction >> 19) & 0x3; | |||
1870 | switch (op_code) { | |||
1871 | case 0x1: // lwpc | |||
1872 | case 0x2: // lwupc | |||
1873 | return SignalContext::READ; | |||
1874 | } | |||
1875 | #endif | |||
1876 | } | |||
1877 | return SignalContext::UNKNOWN; | |||
1878 | #elif defined(__arm__) | |||
1879 | static const uptr FSR_WRITE = 1U << 11; | |||
1880 | uptr fsr = ucontext->uc_mcontext.error_code; | |||
1881 | return fsr & FSR_WRITE ? WRITE : READ; | |||
1882 | #elif defined(__aarch64__) | |||
1883 | static const u64 ESR_ELx_WNR = 1U << 6; | |||
1884 | u64 esr; | |||
1885 | if (!Aarch64GetESR(ucontext, &esr)) return UNKNOWN; | |||
1886 | return esr & ESR_ELx_WNR ? WRITE : READ; | |||
1887 | #elif defined(__sparc__) | |||
1888 | // Decode the instruction to determine the access type. | |||
1889 | // From OpenSolaris $SRC/uts/sun4/os/trap.c (get_accesstype). | |||
1890 | #if SANITIZER_SOLARIS0 | |||
1891 | uptr pc = ucontext->uc_mcontext.gregs[REG_PC]; | |||
1892 | #else | |||
1893 | // Historical BSDism here. | |||
1894 | struct sigcontext *scontext = (struct sigcontext *)context; | |||
1895 | #if defined(__arch64__) | |||
1896 | uptr pc = scontext->sigc_regs.tpc; | |||
1897 | #else | |||
1898 | uptr pc = scontext->si_regs.pc; | |||
1899 | #endif | |||
1900 | #endif | |||
1901 | u32 instr = *(u32 *)pc; | |||
1902 | return (instr >> 21) & 1 ? WRITE: READ; | |||
1903 | #elif defined(__riscv) | |||
1904 | unsigned long pc = ucontext->uc_mcontext.__gregs[REG_PC]; | |||
1905 | unsigned faulty_instruction = *(uint16_t *)pc; | |||
1906 | ||||
1907 | #if defined(__riscv_compressed) | |||
1908 | if ((faulty_instruction & 0x3) != 0x3) { // it's a compressed instruction | |||
1909 | // set op_bits to the instruction bits [1, 0, 15, 14, 13] | |||
1910 | unsigned op_bits = | |||
1911 | ((faulty_instruction & 0x3) << 3) | (faulty_instruction >> 13); | |||
1912 | unsigned rd = faulty_instruction & 0xF80; // bits 7-11, inclusive | |||
1913 | switch (op_bits) { | |||
1914 | case 0b10'010: // c.lwsp (rd != x0) | |||
1915 | #if __riscv_xlen == 64 | |||
1916 | case 0b10'011: // c.ldsp (rd != x0) | |||
1917 | #endif | |||
1918 | return rd ? SignalContext::READ : SignalContext::UNKNOWN; | |||
1919 | case 0b00'010: // c.lw | |||
1920 | #if __riscv_flen >= 32 && __riscv_xlen == 32 | |||
1921 | case 0b10'011: // c.flwsp | |||
1922 | #endif | |||
1923 | #if __riscv_flen >= 32 || __riscv_xlen == 64 | |||
1924 | case 0b00'011: // c.flw / c.ld | |||
1925 | #endif | |||
1926 | #if __riscv_flen == 64 | |||
1927 | case 0b00'001: // c.fld | |||
1928 | case 0b10'001: // c.fldsp | |||
1929 | #endif | |||
1930 | return SignalContext::READ; | |||
1931 | case 0b00'110: // c.sw | |||
1932 | case 0b10'110: // c.swsp | |||
1933 | #if __riscv_flen >= 32 || __riscv_xlen == 64 | |||
1934 | case 0b00'111: // c.fsw / c.sd | |||
1935 | case 0b10'111: // c.fswsp / c.sdsp | |||
1936 | #endif | |||
1937 | #if __riscv_flen == 64 | |||
1938 | case 0b00'101: // c.fsd | |||
1939 | case 0b10'101: // c.fsdsp | |||
1940 | #endif | |||
1941 | return SignalContext::WRITE; | |||
1942 | default: | |||
1943 | return SignalContext::UNKNOWN; | |||
1944 | } | |||
1945 | } | |||
1946 | #endif | |||
1947 | ||||
1948 | unsigned opcode = faulty_instruction & 0x7f; // lower 7 bits | |||
1949 | unsigned funct3 = (faulty_instruction >> 12) & 0x7; // bits 12-14, inclusive | |||
1950 | switch (opcode) { | |||
1951 | case 0b0000011: // loads | |||
1952 | switch (funct3) { | |||
1953 | case 0b000: // lb | |||
1954 | case 0b001: // lh | |||
1955 | case 0b010: // lw | |||
1956 | #if __riscv_xlen == 64 | |||
1957 | case 0b011: // ld | |||
1958 | #endif | |||
1959 | case 0b100: // lbu | |||
1960 | case 0b101: // lhu | |||
1961 | return SignalContext::READ; | |||
1962 | default: | |||
1963 | return SignalContext::UNKNOWN; | |||
1964 | } | |||
1965 | case 0b0100011: // stores | |||
1966 | switch (funct3) { | |||
1967 | case 0b000: // sb | |||
1968 | case 0b001: // sh | |||
1969 | case 0b010: // sw | |||
1970 | #if __riscv_xlen == 64 | |||
1971 | case 0b011: // sd | |||
1972 | #endif | |||
1973 | return SignalContext::WRITE; | |||
1974 | default: | |||
1975 | return SignalContext::UNKNOWN; | |||
1976 | } | |||
1977 | #if __riscv_flen >= 32 | |||
1978 | case 0b0000111: // floating-point loads | |||
1979 | switch (funct3) { | |||
1980 | case 0b010: // flw | |||
1981 | #if __riscv_flen == 64 | |||
1982 | case 0b011: // fld | |||
1983 | #endif | |||
1984 | return SignalContext::READ; | |||
1985 | default: | |||
1986 | return SignalContext::UNKNOWN; | |||
1987 | } | |||
1988 | case 0b0100111: // floating-point stores | |||
1989 | switch (funct3) { | |||
1990 | case 0b010: // fsw | |||
1991 | #if __riscv_flen == 64 | |||
1992 | case 0b011: // fsd | |||
1993 | #endif | |||
1994 | return SignalContext::WRITE; | |||
1995 | default: | |||
1996 | return SignalContext::UNKNOWN; | |||
1997 | } | |||
1998 | #endif | |||
1999 | default: | |||
2000 | return SignalContext::UNKNOWN; | |||
2001 | } | |||
2002 | #else | |||
2003 | (void)ucontext; | |||
2004 | return UNKNOWN; // FIXME: Implement. | |||
2005 | #endif | |||
2006 | } | |||
2007 | ||||
2008 | bool SignalContext::IsTrueFaultingAddress() const { | |||
2009 | auto si = static_cast<const siginfo_t *>(siginfo); | |||
2010 | // SIGSEGV signals without a true fault address have si_code set to 128. | |||
2011 | return si->si_signo == SIGSEGV11 && si->si_code != 128; | |||
2012 | } | |||
2013 | ||||
2014 | void SignalContext::DumpAllRegisters(void *context) { | |||
2015 | // FIXME: Implement this. | |||
2016 | } | |||
2017 | ||||
2018 | static void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { | |||
2019 | #if SANITIZER_NETBSD0 | |||
2020 | // This covers all NetBSD architectures | |||
2021 | ucontext_t *ucontext = (ucontext_t *)context; | |||
2022 | *pc = _UC_MACHINE_PC(ucontext); | |||
2023 | *bp = _UC_MACHINE_FP(ucontext); | |||
2024 | *sp = _UC_MACHINE_SP(ucontext); | |||
2025 | #elif defined(__arm__) | |||
2026 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2027 | *pc = ucontext->uc_mcontext.arm_pc; | |||
2028 | *bp = ucontext->uc_mcontext.arm_fp; | |||
2029 | *sp = ucontext->uc_mcontext.arm_sp; | |||
2030 | #elif defined(__aarch64__) | |||
2031 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2032 | *pc = ucontext->uc_mcontext.pc; | |||
2033 | *bp = ucontext->uc_mcontext.regs[29]; | |||
2034 | *sp = ucontext->uc_mcontext.sp; | |||
2035 | #elif defined(__hppa__) | |||
2036 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2037 | *pc = ucontext->uc_mcontext.sc_iaoq[0]; | |||
2038 | /* GCC uses %r3 whenever a frame pointer is needed. */ | |||
2039 | *bp = ucontext->uc_mcontext.sc_gr[3]; | |||
2040 | *sp = ucontext->uc_mcontext.sc_gr[30]; | |||
2041 | #elif defined(__x86_64__1) | |||
2042 | # if SANITIZER_FREEBSD0 | |||
2043 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2044 | *pc = ucontext->uc_mcontext.mc_rip; | |||
2045 | *bp = ucontext->uc_mcontext.mc_rbp; | |||
2046 | *sp = ucontext->uc_mcontext.mc_rsp; | |||
2047 | # else | |||
2048 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2049 | *pc = ucontext->uc_mcontext.gregs[REG_RIPREG_RIP]; | |||
2050 | *bp = ucontext->uc_mcontext.gregs[REG_RBPREG_RBP]; | |||
2051 | *sp = ucontext->uc_mcontext.gregs[REG_RSPREG_RSP]; | |||
2052 | # endif | |||
2053 | #elif defined(__i386__) | |||
2054 | # if SANITIZER_FREEBSD0 | |||
2055 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2056 | *pc = ucontext->uc_mcontext.mc_eip; | |||
2057 | *bp = ucontext->uc_mcontext.mc_ebp; | |||
2058 | *sp = ucontext->uc_mcontext.mc_esp; | |||
2059 | # else | |||
2060 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2061 | # if SANITIZER_SOLARIS0 | |||
2062 | /* Use the numeric values: the symbolic ones are undefined by llvm | |||
2063 | include/llvm/Support/Solaris.h. */ | |||
2064 | # ifndef REG_EIP | |||
2065 | # define REG_EIP 14 // REG_PC | |||
2066 | # endif | |||
2067 | # ifndef REG_EBP | |||
2068 | # define REG_EBP 6 // REG_FP | |||
2069 | # endif | |||
2070 | # ifndef REG_UESP | |||
2071 | # define REG_UESP 17 // REG_SP | |||
2072 | # endif | |||
2073 | # endif | |||
2074 | *pc = ucontext->uc_mcontext.gregs[REG_EIP]; | |||
2075 | *bp = ucontext->uc_mcontext.gregs[REG_EBP]; | |||
2076 | *sp = ucontext->uc_mcontext.gregs[REG_UESP]; | |||
2077 | # endif | |||
2078 | #elif defined(__powerpc__) || defined(__powerpc64__) | |||
2079 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2080 | *pc = ucontext->uc_mcontext.regs->nip; | |||
2081 | *sp = ucontext->uc_mcontext.regs->gpr[PT_R1]; | |||
2082 | // The powerpc{,64}-linux ABIs do not specify r31 as the frame | |||
2083 | // pointer, but GCC always uses r31 when we need a frame pointer. | |||
2084 | *bp = ucontext->uc_mcontext.regs->gpr[PT_R31]; | |||
2085 | #elif defined(__sparc__) | |||
2086 | #if defined(__arch64__) || defined(__sparcv9) | |||
2087 | #define STACK_BIAS 2047 | |||
2088 | #else | |||
2089 | #define STACK_BIAS 0 | |||
2090 | # endif | |||
2091 | # if SANITIZER_SOLARIS0 | |||
2092 | ucontext_t *ucontext = (ucontext_t *)context; | |||
2093 | *pc = ucontext->uc_mcontext.gregs[REG_PC]; | |||
2094 | *sp = ucontext->uc_mcontext.gregs[REG_O6] + STACK_BIAS; | |||
2095 | #else | |||
2096 | // Historical BSDism here. | |||
2097 | struct sigcontext *scontext = (struct sigcontext *)context; | |||
2098 | #if defined(__arch64__) | |||
2099 | *pc = scontext->sigc_regs.tpc; | |||
2100 | *sp = scontext->sigc_regs.u_regs[14] + STACK_BIAS; | |||
2101 | #else | |||
2102 | *pc = scontext->si_regs.pc; | |||
2103 | *sp = scontext->si_regs.u_regs[14]; | |||
2104 | #endif | |||
2105 | # endif | |||
2106 | *bp = (uptr)((uhwptr *)*sp)[14] + STACK_BIAS; | |||
2107 | #elif defined(__mips__) | |||
2108 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2109 | *pc = ucontext->uc_mcontext.pc; | |||
2110 | *bp = ucontext->uc_mcontext.gregs[30]; | |||
2111 | *sp = ucontext->uc_mcontext.gregs[29]; | |||
2112 | #elif defined(__s390__) | |||
2113 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2114 | # if defined(__s390x__) | |||
2115 | *pc = ucontext->uc_mcontext.psw.addr; | |||
2116 | # else | |||
2117 | *pc = ucontext->uc_mcontext.psw.addr & 0x7fffffff; | |||
2118 | # endif | |||
2119 | *bp = ucontext->uc_mcontext.gregs[11]; | |||
2120 | *sp = ucontext->uc_mcontext.gregs[15]; | |||
2121 | #elif defined(__riscv) | |||
2122 | ucontext_t *ucontext = (ucontext_t*)context; | |||
2123 | *pc = ucontext->uc_mcontext.__gregs[REG_PC]; | |||
2124 | *bp = ucontext->uc_mcontext.__gregs[REG_S0]; | |||
2125 | *sp = ucontext->uc_mcontext.__gregs[REG_SP]; | |||
2126 | #else | |||
2127 | # error "Unsupported arch" | |||
2128 | #endif | |||
2129 | } | |||
2130 | ||||
2131 | void SignalContext::InitPcSpBp() { GetPcSpBp(context, &pc, &sp, &bp); } | |||
2132 | ||||
2133 | void InitializePlatformEarly() { | |||
2134 | // Do nothing. | |||
2135 | } | |||
2136 | ||||
2137 | void MaybeReexec() { | |||
2138 | // No need to re-exec on Linux. | |||
2139 | } | |||
2140 | ||||
2141 | void CheckASLR() { | |||
2142 | #if SANITIZER_NETBSD0 | |||
2143 | int mib[3]; | |||
2144 | int paxflags; | |||
2145 | uptr len = sizeof(paxflags); | |||
2146 | ||||
2147 | mib[0] = CTL_PROC; | |||
2148 | mib[1] = internal_getpid(); | |||
2149 | mib[2] = PROC_PID_PAXFLAGS; | |||
2150 | ||||
2151 | if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)__builtin_expect(!!(internal_sysctl(mib, 3, &paxflags, & len, __null, 0) == -1), 0)) { | |||
2152 | Printf("sysctl failed\n"); | |||
2153 | Die(); | |||
2154 | } | |||
2155 | ||||
2156 | if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_ASLR)__builtin_expect(!!(paxflags & CTL_PROC_PAXFLAGS_ASLR), 0 )) { | |||
2157 | Printf("This sanitizer is not compatible with enabled ASLR.\n" | |||
2158 | "To disable ASLR, please run \"paxctl +a %s\" and try again.\n", | |||
2159 | GetArgv()[0]); | |||
2160 | Die(); | |||
2161 | } | |||
2162 | #elif SANITIZER_PPC64V20 | |||
2163 | // Disable ASLR for Linux PPC64LE. | |||
2164 | int old_personality = personality(0xffffffff); | |||
2165 | if (old_personality != -1 && (old_personality & ADDR_NO_RANDOMIZE) == 0) { | |||
2166 | VReport(1, "WARNING: Program is being run with address space layout "do { if ((uptr)Verbosity() >= (1)) Report("WARNING: Program is being run with address space layout " "randomization (ASLR) enabled which prevents the thread and " "memory sanitizers from working on powerpc64le.\n" "ASLR will be disabled and the program re-executed.\n" ); } while (0) | |||
2167 | "randomization (ASLR) enabled which prevents the thread and "do { if ((uptr)Verbosity() >= (1)) Report("WARNING: Program is being run with address space layout " "randomization (ASLR) enabled which prevents the thread and " "memory sanitizers from working on powerpc64le.\n" "ASLR will be disabled and the program re-executed.\n" ); } while (0) | |||
2168 | "memory sanitizers from working on powerpc64le.\n"do { if ((uptr)Verbosity() >= (1)) Report("WARNING: Program is being run with address space layout " "randomization (ASLR) enabled which prevents the thread and " "memory sanitizers from working on powerpc64le.\n" "ASLR will be disabled and the program re-executed.\n" ); } while (0) | |||
2169 | "ASLR will be disabled and the program re-executed.\n")do { if ((uptr)Verbosity() >= (1)) Report("WARNING: Program is being run with address space layout " "randomization (ASLR) enabled which prevents the thread and " "memory sanitizers from working on powerpc64le.\n" "ASLR will be disabled and the program re-executed.\n" ); } while (0); | |||
2170 | CHECK_NE(personality(old_personality | ADDR_NO_RANDOMIZE), -1)do { __sanitizer::u64 v1 = (__sanitizer::u64)((personality(old_personality | ADDR_NO_RANDOMIZE))); __sanitizer::u64 v2 = (__sanitizer:: u64)((-1)); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer ::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 2170, "(" "(personality(old_personality | ADDR_NO_RANDOMIZE))" ") " "!=" " (" "(-1)" ")", v1, v2); } while (false); | |||
2171 | ReExec(); | |||
2172 | } | |||
2173 | #elif SANITIZER_FREEBSD0 | |||
2174 | int aslr_pie; | |||
2175 | uptr len = sizeof(aslr_pie); | |||
2176 | #if SANITIZER_WORDSIZE64 == 64 | |||
2177 | if (UNLIKELY(internal_sysctlbyname("kern.elf64.aslr.pie_enable",__builtin_expect(!!(internal_sysctlbyname("kern.elf64.aslr.pie_enable" , &aslr_pie, &len, __null, 0) == -1), 0) | |||
2178 | &aslr_pie, &len, NULL, 0) == -1)__builtin_expect(!!(internal_sysctlbyname("kern.elf64.aslr.pie_enable" , &aslr_pie, &len, __null, 0) == -1), 0)) { | |||
2179 | // We're making things less 'dramatic' here since | |||
2180 | // the OID is not necessarily guaranteed to be here | |||
2181 | // just yet regarding FreeBSD release | |||
2182 | return; | |||
2183 | } | |||
2184 | ||||
2185 | if (aslr_pie > 0) { | |||
2186 | Printf("This sanitizer is not compatible with enabled ASLR " | |||
2187 | "and binaries compiled with PIE\n"); | |||
2188 | Die(); | |||
2189 | } | |||
2190 | #endif | |||
2191 | // there might be 32 bits compat for 64 bits | |||
2192 | if (UNLIKELY(internal_sysctlbyname("kern.elf32.aslr.pie_enable",__builtin_expect(!!(internal_sysctlbyname("kern.elf32.aslr.pie_enable" , &aslr_pie, &len, __null, 0) == -1), 0) | |||
2193 | &aslr_pie, &len, NULL, 0) == -1)__builtin_expect(!!(internal_sysctlbyname("kern.elf32.aslr.pie_enable" , &aslr_pie, &len, __null, 0) == -1), 0)) { | |||
2194 | return; | |||
2195 | } | |||
2196 | ||||
2197 | if (aslr_pie > 0) { | |||
2198 | Printf("This sanitizer is not compatible with enabled ASLR " | |||
2199 | "and binaries compiled with PIE\n"); | |||
2200 | Die(); | |||
2201 | } | |||
2202 | #else | |||
2203 | // Do nothing | |||
2204 | #endif | |||
2205 | } | |||
2206 | ||||
2207 | void CheckMPROTECT() { | |||
2208 | #if SANITIZER_NETBSD0 | |||
2209 | int mib[3]; | |||
2210 | int paxflags; | |||
2211 | uptr len = sizeof(paxflags); | |||
2212 | ||||
2213 | mib[0] = CTL_PROC; | |||
2214 | mib[1] = internal_getpid(); | |||
2215 | mib[2] = PROC_PID_PAXFLAGS; | |||
2216 | ||||
2217 | if (UNLIKELY(internal_sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)__builtin_expect(!!(internal_sysctl(mib, 3, &paxflags, & len, __null, 0) == -1), 0)) { | |||
2218 | Printf("sysctl failed\n"); | |||
2219 | Die(); | |||
2220 | } | |||
2221 | ||||
2222 | if (UNLIKELY(paxflags & CTL_PROC_PAXFLAGS_MPROTECT)__builtin_expect(!!(paxflags & CTL_PROC_PAXFLAGS_MPROTECT ), 0)) { | |||
2223 | Printf("This sanitizer is not compatible with enabled MPROTECT\n"); | |||
2224 | Die(); | |||
2225 | } | |||
2226 | #else | |||
2227 | // Do nothing | |||
2228 | #endif | |||
2229 | } | |||
2230 | ||||
2231 | void CheckNoDeepBind(const char *filename, int flag) { | |||
2232 | #ifdef RTLD_DEEPBIND0x00008 | |||
2233 | if (flag & RTLD_DEEPBIND0x00008) { | |||
2234 | Report( | |||
2235 | "You are trying to dlopen a %s shared library with RTLD_DEEPBIND flag" | |||
2236 | " which is incompatible with sanitizer runtime " | |||
2237 | "(see https://github.com/google/sanitizers/issues/611 for details" | |||
2238 | "). If you want to run %s library under sanitizers please remove " | |||
2239 | "RTLD_DEEPBIND from dlopen flags.\n", | |||
2240 | filename, filename); | |||
2241 | Die(); | |||
2242 | } | |||
2243 | #endif | |||
2244 | } | |||
2245 | ||||
2246 | uptr FindAvailableMemoryRange(uptr size, uptr alignment, uptr left_padding, | |||
2247 | uptr *largest_gap_found, | |||
2248 | uptr *max_occupied_addr) { | |||
2249 | UNREACHABLE("FindAvailableMemoryRange is not available")do { do { __sanitizer::u64 v1 = (__sanitizer::u64)((0 && "FindAvailableMemoryRange is not available")); __sanitizer:: u64 v2 = (__sanitizer::u64)(0); if (__builtin_expect(!!(!(v1 != v2)), 0)) __sanitizer::CheckFailed("/build/llvm-toolchain-snapshot-12~++20210124100612+2afaf072f5c1/compiler-rt/lib/sanitizer_common/sanitizer_linux.cpp" , 2249, "(" "(0 && \"FindAvailableMemoryRange is not available\")" ") " "!=" " (" "0" ")", v1, v2); } while (false); Die(); } while (0); | |||
2250 | return 0; | |||
2251 | } | |||
2252 | ||||
2253 | bool GetRandom(void *buffer, uptr length, bool blocking) { | |||
2254 | if (!buffer || !length || length > 256) | |||
2255 | return false; | |||
2256 | #if SANITIZER_USE_GETENTROPY0 | |||
2257 | uptr rnd = getentropy(buffer, length); | |||
2258 | int rverrno = 0; | |||
2259 | if (internal_iserror(rnd, &rverrno) && rverrno == EFAULT14) | |||
2260 | return false; | |||
2261 | else if (rnd == 0) | |||
2262 | return true; | |||
2263 | #endif // SANITIZER_USE_GETENTROPY | |||
2264 | ||||
2265 | #if SANITIZER_USE_GETRANDOM1 | |||
2266 | static atomic_uint8_t skip_getrandom_syscall; | |||
2267 | if (!atomic_load_relaxed(&skip_getrandom_syscall)) { | |||
2268 | // Up to 256 bytes, getrandom will not be interrupted. | |||
2269 | uptr res = internal_syscall(SYSCALL(getrandom)318, buffer, length, | |||
2270 | blocking ? 0 : GRND_NONBLOCK1); | |||
2271 | int rverrno = 0; | |||
2272 | if (internal_iserror(res, &rverrno) && rverrno == ENOSYS38) | |||
2273 | atomic_store_relaxed(&skip_getrandom_syscall, 1); | |||
2274 | else if (res == length) | |||
2275 | return true; | |||
2276 | } | |||
2277 | #endif // SANITIZER_USE_GETRANDOM | |||
2278 | // Up to 256 bytes, a read off /dev/urandom will not be interrupted. | |||
2279 | // blocking is moot here, O_NONBLOCK has no effect when opening /dev/urandom. | |||
2280 | uptr fd = internal_open("/dev/urandom", O_RDONLY00); | |||
2281 | if (internal_iserror(fd)) | |||
2282 | return false; | |||
2283 | uptr res = internal_read(fd, buffer, length); | |||
2284 | if (internal_iserror(res)) | |||
2285 | return false; | |||
2286 | internal_close(fd); | |||
2287 | return true; | |||
2288 | } | |||
2289 | ||||
2290 | } // namespace __sanitizer | |||
2291 | ||||
2292 | #endif |
1 | //===-- sanitizer_syscall_linux_x86_64.inc ----------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Implementations of internal_syscall and internal_iserror for Linux/x86_64. |
10 | // |
11 | //===----------------------------------------------------------------------===// |
12 | |
13 | #define SYSCALL(name)__NR_name __NR_ ## name |
14 | |
15 | static uptr internal_syscall(u64 nr) { |
16 | u64 retval; |
17 | asm volatile("syscall" : "=a"(retval) : "a"(nr) : "rcx", "r11", |
18 | "memory", "cc"); |
19 | return retval; |
20 | } |
21 | |
22 | template <typename T1> |
23 | static uptr internal_syscall(u64 nr, T1 arg1) { |
24 | u64 retval; |
25 | asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1) : |
26 | "rcx", "r11", "memory", "cc"); |
27 | return retval; |
28 | } |
29 | |
30 | template <typename T1, typename T2> |
31 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2) { |
32 | u64 retval; |
33 | asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
34 | "S"((u64)arg2) : "rcx", "r11", "memory", "cc"); |
35 | return retval; |
36 | } |
37 | |
38 | template <typename T1, typename T2, typename T3> |
39 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3) { |
40 | u64 retval; |
41 | asm volatile("syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
42 | "S"((u64)arg2), "d"((u64)arg3) : "rcx", "r11", "memory", "cc"); |
43 | return retval; |
44 | } |
45 | |
46 | template <typename T1, typename T2, typename T3, typename T4> |
47 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4) { |
48 | u64 retval; |
49 | asm volatile("mov %5, %%r10;" |
50 | "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
51 | "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4) : |
52 | "rcx", "r11", "r10", "memory", "cc"); |
53 | return retval; |
54 | } |
55 | |
56 | template <typename T1, typename T2, typename T3, typename T4, typename T5> |
57 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, |
58 | T5 arg5) { |
59 | u64 retval; |
60 | asm volatile("mov %5, %%r10;" |
61 | "mov %6, %%r8;" |
62 | "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
63 | "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5) : |
64 | "rcx", "r11", "r10", "r8", "memory", "cc"); |
65 | return retval; |
66 | } |
67 | |
68 | template <typename T1, typename T2, typename T3, typename T4, typename T5, |
69 | typename T6> |
70 | static uptr internal_syscall(u64 nr, T1 arg1, T2 arg2, T3 arg3, T4 arg4, |
71 | T5 arg5, T6 arg6) { |
72 | u64 retval; |
73 | asm volatile("mov %5, %%r10;" |
74 | "mov %6, %%r8;" |
75 | "mov %7, %%r9;" |
76 | "syscall" : "=a"(retval) : "a"(nr), "D"((u64)arg1), |
77 | "S"((u64)arg2), "d"((u64)arg3), "r"((u64)arg4), "r"((u64)arg5), |
78 | "r"((u64)arg6) : "rcx", "r11", "r10", "r8", "r9", |
79 | "memory", "cc"); |
80 | return retval; |
81 | } |
82 | |
83 | bool internal_iserror(uptr retval, int *rverrno) { |
84 | if (retval >= (uptr)-4095) { |
85 | if (rverrno) |
86 | *rverrno = -retval; |
87 | return true; |
88 | } |
89 | return false; |
90 | } |