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