1 //===-- asan_linux.cc -----------------------------------------------------===// 2 // 3 // This file is distributed under the University of Illinois Open Source 4 // License. See LICENSE.TXT for details. 5 // 6 //===----------------------------------------------------------------------===// 7 // 8 // This file is a part of AddressSanitizer, an address sanity checker. 9 // 10 // Linux-specific details. 11 //===----------------------------------------------------------------------===// 12 13 #include "sanitizer_common/sanitizer_platform.h" 14 #if SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || \ 15 SANITIZER_SOLARIS 16 17 #include "asan_interceptors.h" 18 #include "asan_internal.h" 19 #include "asan_premap_shadow.h" 20 #include "asan_thread.h" 21 #include "sanitizer_common/sanitizer_flags.h" 22 #include "sanitizer_common/sanitizer_freebsd.h" 23 #include "sanitizer_common/sanitizer_libc.h" 24 #include "sanitizer_common/sanitizer_procmaps.h" 25 26 #include <sys/time.h> 27 #include <sys/resource.h> 28 #include <sys/mman.h> 29 #include <sys/syscall.h> 30 #include <sys/types.h> 31 #include <dlfcn.h> 32 #include <fcntl.h> 33 #include <limits.h> 34 #include <pthread.h> 35 #include <stdio.h> 36 #include <unistd.h> 37 #include <unwind.h> 38 39 #if SANITIZER_FREEBSD 40 #include <sys/link_elf.h> 41 #endif 42 #if SANITIZER_NETBSD 43 #include <link_elf.h> 44 extern Elf_Dyn _DYNAMIC; 45 #endif 46 47 #if SANITIZER_SOLARIS 48 #include <link.h> 49 #endif 50 51 #if SANITIZER_ANDROID || SANITIZER_FREEBSD || SANITIZER_SOLARIS 52 #include <ucontext.h> 53 extern "C" void* _DYNAMIC; 54 #elif SANITIZER_NETBSD 55 #include <link_elf.h> 56 #include <ucontext.h> 57 extern Elf_Dyn _DYNAMIC; 58 #else 59 #include <sys/ucontext.h> 60 #include <link.h> 61 #endif 62 63 // x86-64 FreeBSD 9.2 and older define 'ucontext_t' incorrectly in 64 // 32-bit mode. 65 #if SANITIZER_FREEBSD && (SANITIZER_WORDSIZE == 32) && \ 66 __FreeBSD_version <= 902001 // v9.2 67 #define ucontext_t xucontext_t 68 #endif 69 70 typedef enum { 71 ASAN_RT_VERSION_UNDEFINED = 0, 72 ASAN_RT_VERSION_DYNAMIC, 73 ASAN_RT_VERSION_STATIC, 74 } asan_rt_version_t; 75 76 // FIXME: perhaps also store abi version here? 77 extern "C" { 78 SANITIZER_INTERFACE_ATTRIBUTE 79 asan_rt_version_t __asan_rt_version; 80 } 81 82 namespace __asan { 83 84 void InitializePlatformInterceptors() {} 85 void InitializePlatformExceptionHandlers() {} 86 bool IsSystemHeapAddress (uptr addr) { return false; } 87 88 void *AsanDoesNotSupportStaticLinkage() { 89 // This will fail to link with -static. 90 return &_DYNAMIC; // defined in link.h 91 } 92 93 static void UnmapFromTo(uptr from, uptr to) { 94 CHECK(to >= from); 95 if (to == from) return; 96 uptr res = internal_munmap(reinterpret_cast<void *>(from), to - from); 97 if (UNLIKELY(internal_iserror(res))) { 98 Report( 99 "ERROR: AddresSanitizer failed to unmap 0x%zx (%zd) bytes at address " 100 "%p\n", 101 to - from, to - from, from); 102 CHECK("unable to unmap" && 0); 103 } 104 } 105 106 #if ASAN_PREMAP_SHADOW 107 uptr FindPremappedShadowStart() { 108 uptr granularity = GetMmapGranularity(); 109 uptr shadow_start = reinterpret_cast<uptr>(&__asan_shadow); 110 uptr premap_shadow_size = PremapShadowSize(); 111 uptr shadow_size = RoundUpTo(kHighShadowEnd, granularity); 112 // We may have mapped too much. Release extra memory. 113 UnmapFromTo(shadow_start + shadow_size, shadow_start + premap_shadow_size); 114 return shadow_start; 115 } 116 #endif 117 118 uptr FindDynamicShadowStart() { 119 #if ASAN_PREMAP_SHADOW 120 if (!PremapShadowFailed()) 121 return FindPremappedShadowStart(); 122 #endif 123 124 uptr granularity = GetMmapGranularity(); 125 uptr alignment = granularity * 8; 126 uptr left_padding = granularity; 127 uptr shadow_size = RoundUpTo(kHighShadowEnd, granularity); 128 uptr map_size = shadow_size + left_padding + alignment; 129 130 uptr map_start = (uptr)MmapNoAccess(map_size); 131 CHECK_NE(map_start, ~(uptr)0); 132 133 uptr shadow_start = RoundUpTo(map_start + left_padding, alignment); 134 UnmapFromTo(map_start, shadow_start - left_padding); 135 UnmapFromTo(shadow_start + shadow_size, map_start + map_size); 136 137 return shadow_start; 138 } 139 140 void AsanApplyToGlobals(globals_op_fptr op, const void *needle) { 141 UNIMPLEMENTED(); 142 } 143 144 #if SANITIZER_ANDROID 145 // FIXME: should we do anything for Android? 146 void AsanCheckDynamicRTPrereqs() {} 147 void AsanCheckIncompatibleRT() {} 148 #else 149 static int FindFirstDSOCallback(struct dl_phdr_info *info, size_t size, 150 void *data) { 151 VReport(2, "info->dlpi_name = %s\tinfo->dlpi_addr = %p\n", 152 info->dlpi_name, info->dlpi_addr); 153 154 // Continue until the first dynamic library is found 155 if (!info->dlpi_name || info->dlpi_name[0] == 0) 156 return 0; 157 158 // Ignore vDSO 159 if (internal_strncmp(info->dlpi_name, "linux-", sizeof("linux-") - 1) == 0) 160 return 0; 161 162 #if SANITIZER_FREEBSD || SANITIZER_NETBSD 163 // Ignore first entry (the main program) 164 char **p = (char **)data; 165 if (!(*p)) { 166 *p = (char *)-1; 167 return 0; 168 } 169 #endif 170 171 #if SANITIZER_SOLARIS 172 // Ignore executable on Solaris 173 if (info->dlpi_addr == 0) 174 return 0; 175 #endif 176 177 *(const char **)data = info->dlpi_name; 178 return 1; 179 } 180 181 static bool IsDynamicRTName(const char *libname) { 182 return internal_strstr(libname, "libclang_rt.asan") || 183 internal_strstr(libname, "libasan.so"); 184 } 185 186 static void ReportIncompatibleRT() { 187 Report("Your application is linked against incompatible ASan runtimes.\n"); 188 Die(); 189 } 190 191 void AsanCheckDynamicRTPrereqs() { 192 if (!ASAN_DYNAMIC || !flags()->verify_asan_link_order) 193 return; 194 195 // Ensure that dynamic RT is the first DSO in the list 196 const char *first_dso_name = nullptr; 197 dl_iterate_phdr(FindFirstDSOCallback, &first_dso_name); 198 if (first_dso_name && !IsDynamicRTName(first_dso_name)) { 199 Report("ASan runtime does not come first in initial library list; " 200 "you should either link runtime to your application or " 201 "manually preload it with LD_PRELOAD.\n"); 202 Die(); 203 } 204 } 205 206 void AsanCheckIncompatibleRT() { 207 if (ASAN_DYNAMIC) { 208 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) { 209 __asan_rt_version = ASAN_RT_VERSION_DYNAMIC; 210 } else if (__asan_rt_version != ASAN_RT_VERSION_DYNAMIC) { 211 ReportIncompatibleRT(); 212 } 213 } else { 214 if (__asan_rt_version == ASAN_RT_VERSION_UNDEFINED) { 215 // Ensure that dynamic runtime is not present. We should detect it 216 // as early as possible, otherwise ASan interceptors could bind to 217 // the functions in dynamic ASan runtime instead of the functions in 218 // system libraries, causing crashes later in ASan initialization. 219 MemoryMappingLayout proc_maps(/*cache_enabled*/true); 220 char filename[PATH_MAX]; 221 MemoryMappedSegment segment(filename, sizeof(filename)); 222 while (proc_maps.Next(&segment)) { 223 if (IsDynamicRTName(segment.filename)) { 224 Report("Your application is linked against " 225 "incompatible ASan runtimes.\n"); 226 Die(); 227 } 228 } 229 __asan_rt_version = ASAN_RT_VERSION_STATIC; 230 } else if (__asan_rt_version != ASAN_RT_VERSION_STATIC) { 231 ReportIncompatibleRT(); 232 } 233 } 234 } 235 #endif // SANITIZER_ANDROID 236 237 #if 0 // was in old netbsd / gcc 5 sanitizer stuff 238 void GetPcSpBp(void *context, uptr *pc, uptr *sp, uptr *bp) { 239 #ifdef __NetBSD__ 240 # define __UC_MACHINE_FP(ucontext, r) \ 241 (ucontext)->uc_mcontext.__gregs[(r)] 242 /* 243 * Unfortunately we don't have a portable frame pointer (yet) 244 */ 245 # if defined(__alpha__) 246 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_S6) 247 # elif defined(__arm__) 248 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_FP) 249 # elif defined(__x86_64__) 250 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_RBP) 251 # elif defined(__i386__) 252 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_EBP) 253 # elif defined(__m68k__) 254 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_A6) 255 # elif defined(__mips__) 256 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_S8) 257 # elif defined(__powerpc__) || defined(__powerpc64__) 258 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_R1) 259 # elif defined(__riscv__) 260 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_S0) 261 # elif defined(__sparc__) 262 # define _UC_MACHINE_FP(ucontext) sp[15] 263 # elif defined(__sh3__) 264 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_R14) 265 # elif defined(__vax__) 266 # define _UC_MACHINE_FP(ucontext) __UC_MACHINE_FP(ucontext, _REG_FP) 267 # else 268 # define _UC_MACHINE_FP(ucontext) 0 269 # endif 270 ucontext_t *ucontext = (ucontext_t*)context; 271 *pc = _UC_MACHINE_PC(ucontext); 272 *sp = _UC_MACHINE_SP(ucontext); 273 *bp = _UC_MACHINE_FP(ucontext); 274 #elif ASAN_ANDROID 275 *pc = *sp = *bp = 0; 276 #elif defined(__arm__) 277 ucontext_t *ucontext = (ucontext_t*)context; 278 *pc = ucontext->uc_mcontext.arm_pc; 279 *bp = ucontext->uc_mcontext.arm_fp; 280 *sp = ucontext->uc_mcontext.arm_sp; 281 #elif defined(__aarch64__) 282 ucontext_t *ucontext = (ucontext_t*)context; 283 *pc = ucontext->uc_mcontext.pc; 284 *bp = ucontext->uc_mcontext.regs[29]; 285 *sp = ucontext->uc_mcontext.sp; 286 #elif defined(__hppa__) 287 ucontext_t *ucontext = (ucontext_t*)context; 288 *pc = ucontext->uc_mcontext.sc_iaoq[0]; 289 /* GCC uses %r3 whenever a frame pointer is needed. */ 290 *bp = ucontext->uc_mcontext.sc_gr[3]; 291 *sp = ucontext->uc_mcontext.sc_gr[30]; 292 #elif defined(__x86_64__) 293 # if SANITIZER_FREEBSD 294 ucontext_t *ucontext = (ucontext_t*)context; 295 *pc = ucontext->uc_mcontext.mc_rip; 296 *bp = ucontext->uc_mcontext.mc_rbp; 297 *sp = ucontext->uc_mcontext.mc_rsp; 298 # elif SANITIZER_NETBSD 299 *pc = ucontext->uc_mcontext.__gregs[_REG_RIP]; 300 *bp = ucontext->uc_mcontext.__gregs[_REG_RBP]; 301 *sp = ucontext->uc_mcontext.__gregs[_REG_RSP]; 302 # else 303 ucontext_t *ucontext = (ucontext_t*)context; 304 *pc = ucontext->uc_mcontext.gregs[REG_RIP]; 305 *bp = ucontext->uc_mcontext.gregs[REG_RBP]; 306 *sp = ucontext->uc_mcontext.gregs[REG_RSP]; 307 # endif 308 #elif defined(__i386__) 309 # if SANITIZER_FREEBSD 310 ucontext_t *ucontext = (ucontext_t*)context; 311 *pc = ucontext->uc_mcontext.mc_eip; 312 *bp = ucontext->uc_mcontext.mc_ebp; 313 *sp = ucontext->uc_mcontext.mc_esp; 314 # elif SANITIZER_FREEBSD 315 ucontext_t *ucontext = (ucontext_t*)context; 316 *pc = ucontext->uc_mcontext.__gregs[_REG_EIP]; 317 *bp = ucontext->uc_mcontext.__gregs[_REG_EBP]; 318 *sp = ucontext->uc_mcontext.__gregs[_REG_ESP]; 319 # else 320 ucontext_t *ucontext = (ucontext_t*)context; 321 *pc = ucontext->uc_mcontext.gregs[REG_EIP]; 322 *bp = ucontext->uc_mcontext.gregs[REG_EBP]; 323 *sp = ucontext->uc_mcontext.gregs[REG_ESP]; 324 # endif 325 #elif defined(__powerpc__) || defined(__powerpc64__) 326 ucontext_t *ucontext = (ucontext_t*)context; 327 *pc = ucontext->uc_mcontext.regs->nip; 328 *sp = ucontext->uc_mcontext.regs->gpr[PT_R1]; 329 // The powerpc{,64}-linux ABIs do not specify r31 as the frame 330 // pointer, but GCC always uses r31 when we need a frame pointer. 331 *bp = ucontext->uc_mcontext.regs->gpr[PT_R31]; 332 #elif defined(__riscv__) 333 ucontext_t *ucontext = (ucontext_t*)context; 334 *pc = ucontext->uc_mcontext.gregs[REG_PC]; 335 *bp = ucontext->uc_mcontext.gregs[REG_S0]; 336 *sp = ucontext->uc_mcontext.gregs[REG_SP]; 337 #elif defined(__sparc__) 338 ucontext_t *ucontext = (ucontext_t*)context; 339 uptr *stk_ptr; 340 # if defined (__arch64__) 341 *pc = ucontext->uc_mcontext.mc_gregs[MC_PC]; 342 *sp = ucontext->uc_mcontext.mc_gregs[MC_O6]; 343 stk_ptr = (uptr *) (*sp + 2047); 344 *bp = stk_ptr[15]; 345 # else 346 *pc = ucontext->uc_mcontext.gregs[REG_PC]; 347 *sp = ucontext->uc_mcontext.gregs[REG_O6]; 348 stk_ptr = (uptr *) *sp; 349 *bp = stk_ptr[15]; 350 # endif 351 #elif defined(__mips__) 352 ucontext_t *ucontext = (ucontext_t*)context; 353 *pc = ucontext->uc_mcontext.gregs[31]; 354 *bp = ucontext->uc_mcontext.gregs[30]; 355 *sp = ucontext->uc_mcontext.gregs[29]; 356 #else 357 # error "Unsupported arch" 358 #endif 359 } 360 361 bool AsanInterceptsSignal(int signum) { 362 return signum == SIGSEGV && common_flags()->handle_segv; 363 } 364 365 void AsanPlatformThreadInit() { 366 // Nothing here for now. 367 } 368 #endif 369 370 #if !SANITIZER_ANDROID 371 void ReadContextStack(void *context, uptr *stack, uptr *ssize) { 372 ucontext_t *ucp = (ucontext_t*)context; 373 *stack = (uptr)ucp->uc_stack.ss_sp; 374 *ssize = ucp->uc_stack.ss_size; 375 } 376 #else 377 void ReadContextStack(void *context, uptr *stack, uptr *ssize) { 378 UNIMPLEMENTED(); 379 } 380 #endif 381 382 void *AsanDlSymNext(const char *sym) { 383 return dlsym(RTLD_NEXT, sym); 384 } 385 386 } // namespace __asan 387 388 #endif // SANITIZER_FREEBSD || SANITIZER_LINUX || SANITIZER_NETBSD || 389 // SANITIZER_SOLARIS 390