1 /* 2 * 3 * honggfuzz - architecture dependent code (LINUX/PTRACE) 4 * ----------------------------------------- 5 * 6 * Author: Robert Swiecki <swiecki (at) google.com> 7 * 8 * Copyright 2010-2018 by Google Inc. All Rights Reserved. 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); you may 11 * not use this file except in compliance with the License. You may obtain 12 * a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 19 * implied. See the License for the specific language governing 20 * permissions and limitations under the License. 21 * 22 */ 23 24 #include "linux/trace.h" 25 26 #include <ctype.h> 27 #include <dirent.h> 28 #include <elf.h> 29 #include <endian.h> 30 #include <errno.h> 31 #include <fcntl.h> 32 #include <inttypes.h> 33 #include <signal.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <sys/cdefs.h> 38 #include <sys/personality.h> 39 #include <sys/ptrace.h> 40 #include <sys/resource.h> 41 #include <sys/stat.h> 42 #include <sys/syscall.h> 43 #include <sys/time.h> 44 #include <sys/types.h> 45 #include <sys/uio.h> 46 #include <sys/user.h> 47 #include <sys/wait.h> 48 #include <time.h> 49 #include <unistd.h> 50 51 #include "libhfcommon/common.h" 52 #include "libhfcommon/files.h" 53 #include "libhfcommon/log.h" 54 #include "libhfcommon/util.h" 55 #include "linux/bfd.h" 56 #include "linux/unwind.h" 57 #include "sanitizers.h" 58 #include "socketfuzzer.h" 59 #include "subproc.h" 60 61 #if defined(__ANDROID__) 62 #include "capstone.h" 63 #endif 64 65 #if defined(__i386__) || defined(__arm__) || defined(__powerpc__) 66 #define REG_TYPE uint32_t 67 #define REG_PM PRIx32 68 #define REG_PD "0x%08" 69 #elif defined(__x86_64__) || defined(__aarch64__) || defined(__powerpc64__) || \ 70 defined(__mips__) || defined(__mips64__) 71 #define REG_TYPE uint64_t 72 #define REG_PM PRIx64 73 #define REG_PD "0x%016" 74 #endif 75 76 /* 77 * Size in characters required to store a string representation of a 78 * register value (0xdeadbeef style)) 79 */ 80 #define REGSIZEINCHAR (2 * sizeof(REG_TYPE) + 3) 81 82 #if defined(__i386__) || defined(__x86_64__) 83 #define MAX_INSTR_SZ 16 84 #elif defined(__arm__) || defined(__powerpc__) || defined(__powerpc64__) 85 #define MAX_INSTR_SZ 4 86 #elif defined(__aarch64__) 87 #define MAX_INSTR_SZ 8 88 #elif defined(__mips__) || defined(__mips64__) 89 #define MAX_INSTR_SZ 8 90 #endif 91 92 #if defined(__i386__) || defined(__x86_64__) 93 struct user_regs_struct_32 { 94 uint32_t ebx; 95 uint32_t ecx; 96 uint32_t edx; 97 uint32_t esi; 98 uint32_t edi; 99 uint32_t ebp; 100 uint32_t eax; 101 uint16_t ds, __ds; 102 uint16_t es, __es; 103 uint16_t fs, __fs; 104 uint16_t gs, __gs; 105 uint32_t orig_eax; 106 uint32_t eip; 107 uint16_t cs, __cs; 108 uint32_t eflags; 109 uint32_t esp; 110 uint16_t ss, __ss; 111 }; 112 113 struct user_regs_struct_64 { 114 uint64_t r15; 115 uint64_t r14; 116 uint64_t r13; 117 uint64_t r12; 118 uint64_t bp; 119 uint64_t bx; 120 uint64_t r11; 121 uint64_t r10; 122 uint64_t r9; 123 uint64_t r8; 124 uint64_t ax; 125 uint64_t cx; 126 uint64_t dx; 127 uint64_t si; 128 uint64_t di; 129 uint64_t orig_ax; 130 uint64_t ip; 131 uint64_t cs; 132 uint64_t flags; 133 uint64_t sp; 134 uint64_t ss; 135 uint64_t fs_base; 136 uint64_t gs_base; 137 uint64_t ds; 138 uint64_t es; 139 uint64_t fs; 140 uint64_t gs; 141 }; 142 #define HEADERS_STRUCT struct user_regs_struct_64 143 #endif /* defined(__i386__) || defined(__x86_64__) */ 144 145 #if defined(__arm__) || defined(__aarch64__) 146 #ifndef ARM_pc 147 #ifdef __ANDROID__ /* Building with NDK headers */ 148 #define ARM_pc uregs[15] 149 #else /* Building with glibc headers */ 150 #define ARM_pc 15 151 #endif 152 #endif /* ARM_pc */ 153 #ifndef ARM_cpsr 154 #ifdef __ANDROID__ /* Building with NDK headers */ 155 #define ARM_cpsr uregs[16] 156 #else /* Building with glibc headers */ 157 #define ARM_cpsr 16 158 #endif 159 #endif /* ARM_cpsr */ 160 struct user_regs_struct_32 { 161 uint32_t uregs[18]; 162 }; 163 164 struct user_regs_struct_64 { 165 uint64_t regs[31]; 166 uint64_t sp; 167 uint64_t pc; 168 uint64_t pstate; 169 }; 170 #define HEADERS_STRUCT struct user_regs_struct_64 171 #endif /* defined(__arm__) || defined(__aarch64__) */ 172 173 #if defined(__powerpc64__) || defined(__powerpc__) 174 #define HEADERS_STRUCT struct pt_regs 175 struct user_regs_struct_32 { 176 uint32_t gpr[32]; 177 uint32_t nip; 178 uint32_t msr; 179 uint32_t orig_gpr3; 180 uint32_t ctr; 181 uint32_t link; 182 uint32_t xer; 183 uint32_t ccr; 184 uint32_t mq; 185 uint32_t trap; 186 uint32_t dar; 187 uint32_t dsisr; 188 uint32_t result; 189 /* 190 * elf.h's ELF_NGREG says it's 48 registers, so kernel fills it in 191 * with some zeros 192 */ 193 uint32_t zero0; 194 uint32_t zero1; 195 uint32_t zero2; 196 uint32_t zero3; 197 }; 198 struct user_regs_struct_64 { 199 uint64_t gpr[32]; 200 uint64_t nip; 201 uint64_t msr; 202 uint64_t orig_gpr3; 203 uint64_t ctr; 204 uint64_t link; 205 uint64_t xer; 206 uint64_t ccr; 207 uint64_t softe; 208 uint64_t trap; 209 uint64_t dar; 210 uint64_t dsisr; 211 uint64_t result; 212 /* 213 * elf.h's ELF_NGREG says it's 48 registers, so kernel fills it in 214 * with some zeros 215 */ 216 uint64_t zero0; 217 uint64_t zero1; 218 uint64_t zero2; 219 uint64_t zero3; 220 }; 221 #endif /* defined(__powerpc64__) || defined(__powerpc__) */ 222 223 #if defined(__mips__) || defined(__mips64__) 224 struct user_regs_struct { 225 uint64_t regs[32]; 226 227 uint64_t lo; 228 uint64_t hi; 229 uint64_t cp0_epc; 230 uint64_t cp0_badvaddr; 231 uint64_t cp0_status; 232 uint64_t cp0_cause; 233 }; 234 #define HEADERS_STRUCT struct user_regs_struct 235 #endif /* defined(__mips__) || defined(__mips64__) */ 236 237 #if defined(__ANDROID__) 238 /* 239 * Some Android ABIs don't implement PTRACE_GETREGS (e.g. aarch64) 240 */ 241 #if defined(PTRACE_GETREGS) 242 #define PTRACE_GETREGS_AVAILABLE 1 243 #else 244 #define PTRACE_GETREGS_AVAILABLE 0 245 #endif /* defined(PTRACE_GETREGS) */ 246 #endif /* defined(__ANDROID__) */ 247 248 static struct { 249 const char* descr; 250 bool important; 251 } arch_sigs[_NSIG + 1] = { 252 [0 ...(_NSIG)].important = false, 253 [0 ...(_NSIG)].descr = "UNKNOWN", 254 255 [SIGTRAP].important = false, 256 [SIGTRAP].descr = "SIGTRAP", 257 258 [SIGILL].important = true, 259 [SIGILL].descr = "SIGILL", 260 261 [SIGFPE].important = true, 262 [SIGFPE].descr = "SIGFPE", 263 264 [SIGSEGV].important = true, 265 [SIGSEGV].descr = "SIGSEGV", 266 267 [SIGBUS].important = true, 268 [SIGBUS].descr = "SIGBUS", 269 270 /* Is affected from monitorSIGABRT flag */ 271 [SIGABRT].important = false, 272 [SIGABRT].descr = "SIGABRT", 273 274 /* Is affected from tmoutVTALRM flag */ 275 [SIGVTALRM].important = false, 276 [SIGVTALRM].descr = "SIGVTALRM-TMOUT", 277 278 /* seccomp-bpf kill */ 279 [SIGSYS].important = true, 280 [SIGSYS].descr = "SIGSYS", 281 }; 282 283 #ifndef SI_FROMUSER 284 #define SI_FROMUSER(siptr) ((siptr)->si_code <= 0) 285 #endif /* SI_FROMUSER */ 286 287 extern const char* sys_sigabbrev[]; 288 289 static __thread char arch_signame[32]; 290 static const char* arch_sigName(int signo) { 291 if (signo < 0 || signo > _NSIG) { 292 snprintf(arch_signame, sizeof(arch_signame), "UNKNOWN-%d", signo); 293 return arch_signame; 294 } 295 if (signo > __SIGRTMIN) { 296 snprintf(arch_signame, sizeof(arch_signame), "SIG%d-RTMIN+%d", signo, signo - __SIGRTMIN); 297 return arch_signame; 298 } 299 #ifdef __ANDROID__ 300 return arch_sigs[signo].descr; 301 #else 302 if (sys_sigabbrev[signo] == NULL) { 303 snprintf(arch_signame, sizeof(arch_signame), "SIG%d", signo); 304 } else { 305 snprintf(arch_signame, sizeof(arch_signame), "SIG%s", sys_sigabbrev[signo]); 306 } 307 return arch_signame; 308 #endif /* __ANDROID__ */ 309 } 310 311 static size_t arch_getProcMem(pid_t pid, uint8_t* buf, size_t len, REG_TYPE pc) { 312 /* 313 * Let's try process_vm_readv first 314 */ 315 const struct iovec local_iov = { 316 .iov_base = buf, 317 .iov_len = len, 318 }; 319 const struct iovec remote_iov = { 320 .iov_base = (void*)(uintptr_t)pc, 321 .iov_len = len, 322 }; 323 if (process_vm_readv(pid, &local_iov, 1, &remote_iov, 1, 0) == (ssize_t)len) { 324 return len; 325 } 326 // Debug if failed since it shouldn't happen very often 327 PLOG_D("process_vm_readv() failed"); 328 329 /* 330 * Ok, let's do it via ptrace() then. 331 * len must be aligned to the sizeof(long) 332 */ 333 int cnt = len / sizeof(long); 334 size_t memsz = 0; 335 336 for (int x = 0; x < cnt; x++) { 337 uint8_t* addr = (uint8_t*)(uintptr_t)pc + (int)(x * sizeof(long)); 338 long ret = ptrace(PTRACE_PEEKDATA, pid, addr, NULL); 339 340 if (errno != 0) { 341 PLOG_W("Couldn't PT_READ_D on pid %d, addr: %p", pid, addr); 342 break; 343 } 344 345 memsz += sizeof(long); 346 memcpy(&buf[x * sizeof(long)], &ret, sizeof(long)); 347 } 348 return memsz; 349 } 350 351 static size_t arch_getPC(pid_t pid, REG_TYPE* pc, REG_TYPE* status_reg HF_ATTR_UNUSED) { 352 /* 353 * Some old ARM android kernels are failing with PTRACE_GETREGS to extract 354 * the correct register values if struct size is bigger than expected. As such the 355 * 32/64-bit multiplexing trick is not working for them in case PTRACE_GETREGSET 356 * fails or is not implemented. To cover such cases we explicitly define 357 * the struct size to 32bit version for arm CPU. 358 */ 359 #if defined(__arm__) 360 struct user_regs_struct_32 regs; 361 #else 362 HEADERS_STRUCT regs; 363 #endif 364 const struct iovec pt_iov = { 365 .iov_base = ®s, 366 .iov_len = sizeof(regs), 367 }; 368 369 if (ptrace(PTRACE_GETREGSET, pid, NT_PRSTATUS, &pt_iov) == -1L) { 370 PLOG_D("ptrace(PTRACE_GETREGSET) failed"); 371 372 // If PTRACE_GETREGSET fails, try PTRACE_GETREGS if available 373 #if PTRACE_GETREGS_AVAILABLE 374 if (ptrace(PTRACE_GETREGS, pid, 0, ®s)) { 375 PLOG_D("ptrace(PTRACE_GETREGS) failed"); 376 LOG_W("ptrace PTRACE_GETREGSET & PTRACE_GETREGS failed to extract target registers"); 377 return 0; 378 } 379 #else 380 return 0; 381 #endif 382 } 383 #if defined(__i386__) || defined(__x86_64__) 384 /* 385 * 32-bit 386 */ 387 if (pt_iov.iov_len == sizeof(struct user_regs_struct_32)) { 388 struct user_regs_struct_32* r32 = (struct user_regs_struct_32*)®s; 389 *pc = r32->eip; 390 *status_reg = r32->eflags; 391 return pt_iov.iov_len; 392 } 393 394 /* 395 * 64-bit 396 */ 397 if (pt_iov.iov_len == sizeof(struct user_regs_struct_64)) { 398 struct user_regs_struct_64* r64 = (struct user_regs_struct_64*)®s; 399 *pc = r64->ip; 400 *status_reg = r64->flags; 401 return pt_iov.iov_len; 402 } 403 LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len); 404 return 0; 405 #endif /* defined(__i386__) || defined(__x86_64__) */ 406 407 #if defined(__arm__) || defined(__aarch64__) 408 /* 409 * 32-bit 410 */ 411 if (pt_iov.iov_len == sizeof(struct user_regs_struct_32)) { 412 struct user_regs_struct_32* r32 = (struct user_regs_struct_32*)®s; 413 #ifdef __ANDROID__ 414 *pc = r32->ARM_pc; 415 *status_reg = r32->ARM_cpsr; 416 #else 417 *pc = r32->uregs[ARM_pc]; 418 *status_reg = r32->uregs[ARM_cpsr]; 419 #endif 420 return pt_iov.iov_len; 421 } 422 423 /* 424 * 64-bit 425 */ 426 if (pt_iov.iov_len == sizeof(struct user_regs_struct_64)) { 427 struct user_regs_struct_64* r64 = (struct user_regs_struct_64*)®s; 428 *pc = r64->pc; 429 *status_reg = r64->pstate; 430 return pt_iov.iov_len; 431 } 432 LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len); 433 return 0; 434 #endif /* defined(__arm__) || defined(__aarch64__) */ 435 436 #if defined(__powerpc64__) || defined(__powerpc__) 437 /* 438 * 32-bit 439 */ 440 if (pt_iov.iov_len == sizeof(struct user_regs_struct_32)) { 441 struct user_regs_struct_32* r32 = (struct user_regs_struct_32*)®s; 442 *pc = r32->nip; 443 return pt_iov.iov_len; 444 } 445 446 /* 447 * 64-bit 448 */ 449 if (pt_iov.iov_len == sizeof(struct user_regs_struct_64)) { 450 struct user_regs_struct_64* r64 = (struct user_regs_struct_64*)®s; 451 *pc = r64->nip; 452 return pt_iov.iov_len; 453 } 454 455 LOG_W("Unknown registers structure size: '%zd'", pt_iov.iov_len); 456 return 0; 457 #endif /* defined(__powerpc64__) || defined(__powerpc__) */ 458 459 #if defined(__mips__) || defined(__mips64__) 460 *pc = regs.cp0_epc; 461 return pt_iov.iov_len; 462 #endif /* defined(__mips__) || defined(__mips64__) */ 463 464 LOG_D("Unknown/unsupported CPU architecture"); 465 return 0; 466 } 467 468 static void arch_getInstrStr(pid_t pid, REG_TYPE* pc, char* instr) { 469 /* 470 * We need a value aligned to 8 471 * which is sizeof(long) on 64bit CPU archs (on most of them, I hope;) 472 */ 473 uint8_t buf[MAX_INSTR_SZ]; 474 size_t memsz; 475 REG_TYPE status_reg = 0; 476 477 snprintf(instr, _HF_INSTR_SZ, "%s", "[UNKNOWN]"); 478 479 size_t pcRegSz = arch_getPC(pid, pc, &status_reg); 480 if (!pcRegSz) { 481 LOG_W("Current architecture not supported for disassembly"); 482 return; 483 } 484 485 if ((memsz = arch_getProcMem(pid, buf, sizeof(buf), *pc)) == 0) { 486 snprintf(instr, _HF_INSTR_SZ, "%s", "[NOT_MMAPED]"); 487 return; 488 } 489 #if !defined(__ANDROID__) 490 arch_bfdDisasm(pid, buf, memsz, instr); 491 #else 492 cs_arch arch; 493 cs_mode mode; 494 #if defined(__arm__) || defined(__aarch64__) 495 arch = (pcRegSz == sizeof(struct user_regs_struct_64)) ? CS_ARCH_ARM64 : CS_ARCH_ARM; 496 if (arch == CS_ARCH_ARM) { 497 mode = (status_reg & 0x20) ? CS_MODE_THUMB : CS_MODE_ARM; 498 } else { 499 mode = CS_MODE_ARM; 500 } 501 #elif defined(__i386__) || defined(__x86_64__) 502 arch = CS_ARCH_X86; 503 mode = (pcRegSz == sizeof(struct user_regs_struct_64)) ? CS_MODE_64 : CS_MODE_32; 504 #else 505 LOG_E("Unknown/Unsupported Android CPU architecture"); 506 #endif 507 508 csh handle; 509 cs_err err = cs_open(arch, mode, &handle); 510 if (err != CS_ERR_OK) { 511 LOG_W("Capstone initialization failed: '%s'", cs_strerror(err)); 512 return; 513 } 514 515 cs_insn* insn; 516 size_t count = cs_disasm(handle, buf, sizeof(buf), *pc, 0, &insn); 517 518 if (count < 1) { 519 LOG_W("Couldn't disassemble the assembler instructions' stream: '%s'", 520 cs_strerror(cs_errno(handle))); 521 cs_close(&handle); 522 return; 523 } 524 525 snprintf(instr, _HF_INSTR_SZ, "%s %s", insn[0].mnemonic, insn[0].op_str); 526 cs_free(insn, count); 527 cs_close(&handle); 528 #endif /* defined(__ANDROID__) */ 529 530 for (int x = 0; instr[x] && x < _HF_INSTR_SZ; x++) { 531 if (instr[x] == '/' || instr[x] == '\\' || isspace(instr[x]) || !isprint(instr[x])) { 532 instr[x] = '_'; 533 } 534 } 535 536 return; 537 } 538 539 static void arch_hashCallstack(run_t* run, funcs_t* funcs, size_t funcCnt, bool enableMasking) { 540 uint64_t hash = 0; 541 for (size_t i = 0; i < funcCnt && i < run->global->linux.numMajorFrames; i++) { 542 /* 543 * Convert PC to char array to be compatible with hash function 544 */ 545 char pcStr[REGSIZEINCHAR] = {0}; 546 snprintf(pcStr, REGSIZEINCHAR, REG_PD REG_PM, (REG_TYPE)(long)funcs[i].pc); 547 548 /* 549 * Hash the last three nibbles 550 */ 551 hash ^= util_hash(&pcStr[strlen(pcStr) - 3], 3); 552 } 553 554 /* 555 * If only one frame, hash is not safe to be used for uniqueness. We mask it 556 * here with a constant prefix, so analyzers can pick it up and create filenames 557 * accordingly. 'enableMasking' is controlling masking for cases where it should 558 * not be enabled (e.g. fuzzer worker is from verifier). 559 */ 560 if (enableMasking && funcCnt == 1) { 561 hash |= _HF_SINGLE_FRAME_MASK; 562 } 563 run->backtrace = hash; 564 } 565 566 static void arch_traceGenerateReport( 567 pid_t pid, run_t* run, funcs_t* funcs, size_t funcCnt, siginfo_t* si, const char* instr) { 568 run->report[0] = '\0'; 569 util_ssnprintf(run->report, sizeof(run->report), "ORIG_FNAME: %s\n", run->origFileName); 570 util_ssnprintf(run->report, sizeof(run->report), "FUZZ_FNAME: %s\n", run->crashFileName); 571 util_ssnprintf(run->report, sizeof(run->report), "PID: %d\n", pid); 572 util_ssnprintf(run->report, sizeof(run->report), "SIGNAL: %s (%d)\n", 573 arch_sigName(si->si_signo), si->si_signo); 574 util_ssnprintf(run->report, sizeof(run->report), "FAULT ADDRESS: %p\n", 575 SI_FROMUSER(si) ? NULL : si->si_addr); 576 util_ssnprintf(run->report, sizeof(run->report), "INSTRUCTION: %s\n", instr); 577 util_ssnprintf( 578 run->report, sizeof(run->report), "STACK HASH: %016" PRIx64 "\n", run->backtrace); 579 util_ssnprintf(run->report, sizeof(run->report), "STACK:\n"); 580 for (size_t i = 0; i < funcCnt; i++) { 581 #ifdef __HF_USE_CAPSTONE__ 582 util_ssnprintf( 583 run->report, sizeof(run->report), " <" REG_PD REG_PM "> ", (REG_TYPE)(long)funcs[i].pc); 584 if (funcs[i].func[0] != '\0') 585 util_ssnprintf(run->report, sizeof(run->report), "[%s() + 0x%x at %s]\n", funcs[i].func, 586 funcs[i].line, funcs[i].mapName); 587 else 588 util_ssnprintf(run->report, sizeof(run->report), "[]\n"); 589 #else 590 util_ssnprintf(run->report, sizeof(run->report), " <" REG_PD REG_PM "> [%s():%zu at %s]\n", 591 (REG_TYPE)(long)funcs[i].pc, funcs[i].func, funcs[i].line, funcs[i].mapName); 592 #endif 593 } 594 595 // libunwind is not working for 32bit targets in 64bit systems 596 #if defined(__aarch64__) 597 if (funcCnt == 0) { 598 util_ssnprintf(run->report, sizeof(run->report), 599 " !ERROR: If 32bit fuzz target" 600 " in aarch64 system, try ARM 32bit build\n"); 601 } 602 #endif 603 604 return; 605 } 606 607 static void arch_traceAnalyzeData(run_t* run, pid_t pid) { 608 REG_TYPE pc = 0, status_reg = 0; 609 size_t pcRegSz = arch_getPC(pid, &pc, &status_reg); 610 if (!pcRegSz) { 611 LOG_W("ptrace arch_getPC failed"); 612 return; 613 } 614 615 /* 616 * Unwind and resolve symbols 617 */ 618 funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t)); 619 defer { 620 free(funcs); 621 }; 622 memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t)); 623 624 #if !defined(__ANDROID__) 625 size_t funcCnt = arch_unwindStack(pid, funcs); 626 arch_bfdResolveSyms(pid, funcs, funcCnt); 627 #else 628 size_t funcCnt = arch_unwindStack(pid, funcs); 629 #endif 630 631 /* 632 * If unwinder failed (zero frames), use PC from ptrace GETREGS if not zero. 633 * If PC reg zero return and callers should handle zero hash case. 634 */ 635 if (funcCnt == 0) { 636 if (pc) { 637 /* Manually update major frame PC & frames counter */ 638 funcs[0].pc = (void*)(uintptr_t)pc; 639 funcCnt = 1; 640 } else { 641 return; 642 } 643 } 644 645 /* 646 * Calculate backtrace callstack hash signature 647 */ 648 arch_hashCallstack(run, funcs, funcCnt, false); 649 } 650 651 static void arch_traceSaveData(run_t* run, pid_t pid) { 652 REG_TYPE pc = 0; 653 654 /* Local copy since flag is overridden for some crashes */ 655 bool saveUnique = run->global->io.saveUnique; 656 657 char instr[_HF_INSTR_SZ] = "\x00"; 658 siginfo_t si; 659 bzero(&si, sizeof(si)); 660 661 if (ptrace(PTRACE_GETSIGINFO, pid, 0, &si) == -1) { 662 PLOG_W("Couldn't get siginfo for pid %d", pid); 663 } 664 665 arch_getInstrStr(pid, &pc, instr); 666 667 LOG_D("Pid: %d, signo: %d, errno: %d, code: %d, addr: %p, pc: %" REG_PM ", instr: '%s'", pid, 668 si.si_signo, si.si_errno, si.si_code, si.si_addr, pc, instr); 669 670 if (!SI_FROMUSER(&si) && pc && si.si_addr < run->global->linux.ignoreAddr) { 671 LOG_I("Input is interesting (%s), but the si.si_addr is %p (below %p), skipping", 672 arch_sigName(si.si_signo), si.si_addr, run->global->linux.ignoreAddr); 673 return; 674 } 675 676 /* 677 * Unwind and resolve symbols 678 */ 679 funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t)); 680 defer { 681 free(funcs); 682 }; 683 memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t)); 684 685 #if !defined(__ANDROID__) 686 size_t funcCnt = arch_unwindStack(pid, funcs); 687 arch_bfdResolveSyms(pid, funcs, funcCnt); 688 #else 689 size_t funcCnt = arch_unwindStack(pid, funcs); 690 #endif 691 692 /* 693 * If unwinder failed (zero frames), use PC from ptrace GETREGS if not zero. 694 * If PC reg zero, temporarily disable uniqueness flag since callstack 695 * hash will be also zero, thus not safe for unique decisions. 696 */ 697 if (funcCnt == 0) { 698 if (pc) { 699 /* Manually update major frame PC & frames counter */ 700 funcs[0].pc = (void*)(uintptr_t)pc; 701 funcCnt = 1; 702 } else { 703 saveUnique = false; 704 } 705 } 706 707 /* 708 * Temp local copy of previous backtrace value in case worker hit crashes into multiple 709 * tids for same target master thread. Will be 0 for first crash against target. 710 */ 711 uint64_t oldBacktrace = run->backtrace; 712 713 /* 714 * Calculate backtrace callstack hash signature 715 */ 716 arch_hashCallstack(run, funcs, funcCnt, saveUnique); 717 718 /* 719 * If unique flag is set and single frame crash, disable uniqueness for this crash 720 * to always save (timestamp will be added to the filename) 721 */ 722 if (saveUnique && (funcCnt == 1)) { 723 saveUnique = false; 724 } 725 726 /* 727 * If worker crashFileName member is set, it means that a tid has already crashed 728 * from target master thread. 729 */ 730 if (run->crashFileName[0] != '\0') { 731 LOG_D("Multiple crashes detected from worker against attached tids group"); 732 733 /* 734 * If stackhashes match, don't re-analyze. This will avoid duplicates 735 * and prevent verifier from running multiple passes. Depth of check is 736 * always 1 (last backtrace saved only per target iteration). 737 */ 738 if (oldBacktrace == run->backtrace) { 739 return; 740 } 741 } 742 743 /* Increase global crashes counter */ 744 ATOMIC_POST_INC(run->global->cnts.crashesCnt); 745 746 /* 747 * Check if backtrace contains whitelisted symbol. Whitelist overrides 748 * both stackhash and symbol blacklist. Crash is always kept regardless 749 * of the status of uniqueness flag. 750 */ 751 if (run->global->linux.symsWl) { 752 char* wlSymbol = arch_btContainsSymbol( 753 run->global->linux.symsWlCnt, run->global->linux.symsWl, funcCnt, funcs); 754 if (wlSymbol != NULL) { 755 saveUnique = false; 756 LOG_D("Whitelisted symbol '%s' found, skipping blacklist checks", wlSymbol); 757 } 758 } else { 759 /* 760 * Check if stackhash is blacklisted 761 */ 762 if (run->global->feedback.blacklist && 763 (fastArray64Search(run->global->feedback.blacklist, run->global->feedback.blacklistCnt, 764 run->backtrace) != -1)) { 765 LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", run->backtrace); 766 ATOMIC_POST_INC(run->global->cnts.blCrashesCnt); 767 return; 768 } 769 770 /* 771 * Check if backtrace contains blacklisted symbol 772 */ 773 char* blSymbol = arch_btContainsSymbol( 774 run->global->linux.symsBlCnt, run->global->linux.symsBl, funcCnt, funcs); 775 if (blSymbol != NULL) { 776 LOG_I("Blacklisted symbol '%s' found, skipping", blSymbol); 777 ATOMIC_POST_INC(run->global->cnts.blCrashesCnt); 778 return; 779 } 780 } 781 782 /* If non-blacklisted crash detected, zero set two MSB */ 783 ATOMIC_POST_ADD(run->global->cfg.dynFileIterExpire, _HF_DYNFILE_SUB_MASK); 784 785 void* sig_addr = si.si_addr; 786 if (!run->global->linux.disableRandomization) { 787 pc = 0UL; 788 sig_addr = NULL; 789 } 790 791 /* User-induced signals don't set si.si_addr */ 792 if (SI_FROMUSER(&si)) { 793 sig_addr = NULL; 794 } 795 796 /* If dry run mode, copy file with same name into workspace */ 797 if (run->global->mutate.mutationsPerRun == 0U && run->global->cfg.useVerifier) { 798 snprintf(run->crashFileName, sizeof(run->crashFileName), "%s/%s", run->global->io.crashDir, 799 run->origFileName); 800 } else if (saveUnique) { 801 snprintf(run->crashFileName, sizeof(run->crashFileName), 802 "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%d.ADDR.%p.INSTR.%s.%s", 803 run->global->io.crashDir, arch_sigName(si.si_signo), pc, run->backtrace, si.si_code, 804 sig_addr, instr, run->global->io.fileExtn); 805 } else { 806 char localtmstr[PATH_MAX]; 807 util_getLocalTime("%F.%H:%M:%S", localtmstr, sizeof(localtmstr), time(NULL)); 808 snprintf(run->crashFileName, sizeof(run->crashFileName), 809 "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%d.ADDR.%p.INSTR.%s.%s.%d.%s", 810 run->global->io.crashDir, arch_sigName(si.si_signo), pc, run->backtrace, si.si_code, 811 sig_addr, instr, localtmstr, pid, run->global->io.fileExtn); 812 } 813 814 /* Target crashed (no duplicate detection yet) */ 815 if (run->global->socketFuzzer.enabled) { 816 LOG_D("SocketFuzzer: trace: Crash Identified"); 817 } 818 819 if (files_exists(run->crashFileName)) { 820 LOG_I("Crash (dup): '%s' already exists, skipping", run->crashFileName); 821 // Clear filename so that verifier can understand we hit a duplicate 822 memset(run->crashFileName, 0, sizeof(run->crashFileName)); 823 return; 824 } 825 826 if (!files_writeBufToFile(run->crashFileName, run->dynamicFile, run->dynamicFileSz, 827 O_CREAT | O_EXCL | O_WRONLY | O_CLOEXEC)) { 828 LOG_E("Couldn't write to '%s'", run->crashFileName); 829 return; 830 } 831 832 /* Unique new crash, notify fuzzer */ 833 if (run->global->socketFuzzer.enabled) { 834 LOG_D("SocketFuzzer: trace: New Uniqu Crash"); 835 fuzz_notifySocketFuzzerCrash(run); 836 } 837 LOG_I("Crash: saved as '%s'", run->crashFileName); 838 839 ATOMIC_POST_INC(run->global->cnts.uniqueCrashesCnt); 840 /* If unique crash found, reset dynFile counter */ 841 ATOMIC_CLEAR(run->global->cfg.dynFileIterExpire); 842 843 arch_traceGenerateReport(pid, run, funcs, funcCnt, &si, instr); 844 } 845 846 /* TODO: Add report parsing support for other sanitizers too */ 847 static int arch_parseAsanReport( 848 run_t* run, pid_t pid, funcs_t* funcs, void** crashAddr, char** op) { 849 char crashReport[PATH_MAX] = {0}; 850 const char* const crashReportCpy = crashReport; 851 snprintf( 852 crashReport, sizeof(crashReport), "%s/%s.%d", run->global->io.workDir, kLOGPREFIX, pid); 853 854 FILE* fReport = fopen(crashReport, "rb"); 855 if (fReport == NULL) { 856 PLOG_D("Couldn't open '%s' - R/O mode", crashReport); 857 return -1; 858 } 859 defer { 860 fclose(fReport); 861 }; 862 defer { 863 unlink(crashReportCpy); 864 }; 865 866 char header[35] = {0}; 867 snprintf(header, sizeof(header), "==%d==ERROR: AddressSanitizer:", pid); 868 size_t headerSz = strlen(header); 869 bool headerFound = false; 870 871 uint8_t frameIdx = 0; 872 char framePrefix[5] = {0}; 873 snprintf(framePrefix, sizeof(framePrefix), "#%" PRIu8, frameIdx); 874 875 char *lineptr = NULL, *cAddr = NULL; 876 size_t n = 0; 877 defer { 878 free(lineptr); 879 }; 880 for (;;) { 881 if (getline(&lineptr, &n, fReport) == -1) { 882 break; 883 } 884 885 /* First step is to identify header */ 886 if (!headerFound) { 887 if ((strlen(lineptr) > headerSz) && (strncmp(header, lineptr, headerSz) == 0)) { 888 headerFound = true; 889 890 /* Parse crash address */ 891 cAddr = strstr(lineptr, "address 0x"); 892 if (cAddr) { 893 cAddr = cAddr + strlen("address "); 894 char* endOff = strchr(cAddr, ' '); 895 cAddr[endOff - cAddr] = '\0'; 896 *crashAddr = (void*)((size_t)strtoull(cAddr, NULL, 16)); 897 } else { 898 *crashAddr = 0x0; 899 } 900 } 901 continue; 902 } else { 903 char* pLineLC = lineptr; 904 /* Trim leading spaces */ 905 while (*pLineLC != '\0' && isspace(*pLineLC)) { 906 ++pLineLC; 907 } 908 909 /* End separator for crash thread stack trace is an empty line */ 910 if ((*pLineLC == '\0') && (frameIdx != 0)) { 911 break; 912 } 913 914 /* Basic length checks */ 915 if (strlen(pLineLC) < 10) { 916 continue; 917 } 918 919 /* If available parse the type of error (READ/WRITE) */ 920 if (cAddr && strstr(pLineLC, cAddr)) { 921 if (strncmp(pLineLC, "READ", 4) == 0) { 922 *op = "READ"; 923 } else if (strncmp(pLineLC, "WRITE", 5) == 0) { 924 *op = "WRITE"; 925 } 926 cAddr = NULL; 927 } 928 929 /* Check for crash thread frames */ 930 if (strncmp(pLineLC, framePrefix, strlen(framePrefix)) == 0) { 931 /* Abort if max depth */ 932 if (frameIdx >= _HF_MAX_FUNCS) { 933 break; 934 } 935 936 /* 937 * Frames have following format: 938 #0 0xaa860177 (/system/lib/libc.so+0x196177) 939 */ 940 char* savePtr = NULL; 941 strtok_r(pLineLC, " ", &savePtr); 942 funcs[frameIdx].pc = 943 (void*)((size_t)strtoull(strtok_r(NULL, " ", &savePtr), NULL, 16)); 944 945 /* DSO & code offset parsing */ 946 char* targetStr = strtok_r(NULL, " ", &savePtr); 947 char* startOff = strchr(targetStr, '(') + 1; 948 char* plusOff = strchr(targetStr, '+'); 949 char* endOff = strrchr(targetStr, ')'); 950 targetStr[endOff - startOff] = '\0'; 951 if ((startOff == NULL) || (endOff == NULL) || (plusOff == NULL)) { 952 LOG_D("Invalid ASan report entry (%s)", lineptr); 953 } else { 954 size_t dsoSz = 955 MIN(sizeof(funcs[frameIdx].mapName), (size_t)(plusOff - startOff)); 956 memcpy(funcs[frameIdx].mapName, startOff, dsoSz); 957 char* codeOff = targetStr + (plusOff - startOff) + 1; 958 funcs[frameIdx].line = strtoull(codeOff, NULL, 16); 959 } 960 961 frameIdx++; 962 snprintf(framePrefix, sizeof(framePrefix), "#%" PRIu8, frameIdx); 963 } 964 } 965 } 966 967 return frameIdx; 968 } 969 970 /* 971 * Special book keeping for cases where crashes are detected based on exitcode and not 972 * a raised signal. Such case is the ASan fuzzing for Android. Crash file name maintains 973 * the same format for compatibility with post campaign tools. 974 */ 975 static void arch_traceExitSaveData(run_t* run, pid_t pid) { 976 REG_TYPE pc = 0; 977 void* crashAddr = 0; 978 char* op = "UNKNOWN"; 979 980 /* Save only the first hit for each worker */ 981 if (run->crashFileName[0] != '\0') { 982 return; 983 } 984 985 /* Increase global crashes counter */ 986 ATOMIC_POST_INC(run->global->cnts.crashesCnt); 987 ATOMIC_POST_AND(run->global->cfg.dynFileIterExpire, _HF_DYNFILE_SUB_MASK); 988 989 /* If sanitizer produces reports with stack traces (e.g. ASan), they're parsed manually */ 990 int funcCnt = 0; 991 funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t)); 992 defer { 993 free(funcs); 994 }; 995 memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t)); 996 997 /* Sanitizers save reports against parent PID */ 998 if (run->pid != pid) { 999 return; 1000 } 1001 funcCnt = arch_parseAsanReport(run, pid, funcs, &crashAddr, &op); 1002 1003 /* 1004 * -1 error indicates a file not found for report. This is expected to happen often since 1005 * ASan report is generated once for crashing TID. Ptrace arch is not guaranteed to parse 1006 * that TID first. Not setting the 'crashFileName' variable will ensure that this branch 1007 * is executed again for all TIDs until the matching report is found 1008 */ 1009 if (funcCnt == -1) { 1010 return; 1011 } 1012 1013 /* Since crash address is available, apply ignoreAddr filters */ 1014 if (crashAddr < run->global->linux.ignoreAddr) { 1015 LOG_I("Input is interesting, but the crash addr is %p (below %p), skipping", crashAddr, 1016 run->global->linux.ignoreAddr); 1017 return; 1018 } 1019 1020 /* If frames successfully recovered, calculate stack hash & populate crash PC */ 1021 arch_hashCallstack(run, funcs, funcCnt, false); 1022 pc = (uintptr_t)funcs[0].pc; 1023 1024 /* 1025 * Check if stackhash is blacklisted 1026 */ 1027 if (run->global->feedback.blacklist && 1028 (fastArray64Search(run->global->feedback.blacklist, run->global->feedback.blacklistCnt, 1029 run->backtrace) != -1)) { 1030 LOG_I("Blacklisted stack hash '%" PRIx64 "', skipping", run->backtrace); 1031 ATOMIC_POST_INC(run->global->cnts.blCrashesCnt); 1032 return; 1033 } 1034 1035 /* If dry run mode, copy file with same name into workspace */ 1036 if (run->global->mutate.mutationsPerRun == 0U && run->global->cfg.useVerifier) { 1037 snprintf(run->crashFileName, sizeof(run->crashFileName), "%s/%s", run->global->io.crashDir, 1038 run->origFileName); 1039 } else { 1040 /* Keep the crashes file name format identical */ 1041 if (run->backtrace != 0ULL && run->global->io.saveUnique) { 1042 snprintf(run->crashFileName, sizeof(run->crashFileName), 1043 "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%s.ADDR.%p.INSTR.%s.%s", 1044 run->global->io.crashDir, "SAN", pc, run->backtrace, op, crashAddr, "[UNKNOWN]", 1045 run->global->io.fileExtn); 1046 } else { 1047 /* If no stack hash available, all crashes treated as unique */ 1048 char localtmstr[PATH_MAX]; 1049 util_getLocalTime("%F.%H:%M:%S", localtmstr, sizeof(localtmstr), time(NULL)); 1050 snprintf(run->crashFileName, sizeof(run->crashFileName), 1051 "%s/%s.PC.%" REG_PM ".STACK.%" PRIx64 ".CODE.%s.ADDR.%p.INSTR.%s.%s.%s", 1052 run->global->io.crashDir, "SAN", pc, run->backtrace, op, crashAddr, "[UNKNOWN]", 1053 localtmstr, run->global->io.fileExtn); 1054 } 1055 } 1056 1057 int fd = open(run->crashFileName, O_WRONLY | O_EXCL | O_CREAT, 0600); 1058 if (fd == -1 && errno == EEXIST) { 1059 LOG_I("It seems that '%s' already exists, skipping", run->crashFileName); 1060 return; 1061 } else if (fd == -1) { 1062 PLOG_E("Cannot create output file '%s'", run->crashFileName); 1063 return; 1064 } else { 1065 defer { 1066 close(fd); 1067 }; 1068 if (files_writeToFd(fd, run->dynamicFile, run->dynamicFileSz)) { 1069 LOG_I("Ok, that's interesting, saved new crash as '%s'", run->crashFileName); 1070 /* Clear stack hash so that verifier can understand we hit a duplicate */ 1071 run->backtrace = 0ULL; 1072 /* Increase unique crashes counters */ 1073 ATOMIC_POST_INC(run->global->cnts.uniqueCrashesCnt); 1074 ATOMIC_CLEAR(run->global->cfg.dynFileIterExpire); 1075 } else { 1076 LOG_E("Couldn't save crash to '%s'", run->crashFileName); 1077 /* In case of write error, clear crashFileName to so that other monitored TIDs can retry 1078 */ 1079 memset(run->crashFileName, 0, sizeof(run->crashFileName)); 1080 return; 1081 } 1082 } 1083 1084 /* Generate report */ 1085 run->report[0] = '\0'; 1086 util_ssnprintf(run->report, sizeof(run->report), "EXIT_CODE: %d\n", HF_SAN_EXIT_CODE); 1087 util_ssnprintf(run->report, sizeof(run->report), "ORIG_FNAME: %s\n", run->origFileName); 1088 util_ssnprintf(run->report, sizeof(run->report), "FUZZ_FNAME: %s\n", run->crashFileName); 1089 util_ssnprintf(run->report, sizeof(run->report), "PID: %d\n", pid); 1090 util_ssnprintf(run->report, sizeof(run->report), "OPERATION: %s\n", op); 1091 util_ssnprintf(run->report, sizeof(run->report), "FAULT ADDRESS: %p\n", crashAddr); 1092 if (funcCnt > 0) { 1093 util_ssnprintf( 1094 run->report, sizeof(run->report), "STACK HASH: %016" PRIx64 "\n", run->backtrace); 1095 util_ssnprintf(run->report, sizeof(run->report), "STACK:\n"); 1096 for (int i = 0; i < funcCnt; i++) { 1097 util_ssnprintf(run->report, sizeof(run->report), " <" REG_PD REG_PM "> ", 1098 (REG_TYPE)(long)funcs[i].pc); 1099 if (funcs[i].mapName[0] != '\0') { 1100 util_ssnprintf(run->report, sizeof(run->report), "[%s + 0x%zx]\n", funcs[i].mapName, 1101 funcs[i].line); 1102 } else { 1103 util_ssnprintf(run->report, sizeof(run->report), "[]\n"); 1104 } 1105 } 1106 } 1107 } 1108 1109 static void arch_traceExitAnalyzeData(run_t* run, pid_t pid) { 1110 void* crashAddr = 0; 1111 char* op = "UNKNOWN"; 1112 int funcCnt = 0; 1113 funcs_t* funcs = util_Malloc(_HF_MAX_FUNCS * sizeof(funcs_t)); 1114 defer { 1115 free(funcs); 1116 }; 1117 memset(funcs, 0, _HF_MAX_FUNCS * sizeof(funcs_t)); 1118 1119 funcCnt = arch_parseAsanReport(run, pid, funcs, &crashAddr, &op); 1120 1121 /* 1122 * -1 error indicates a file not found for report. This is expected to happen often since 1123 * ASan report is generated once for crashing TID. Ptrace arch is not guaranteed to parse 1124 * that TID first. Not setting the 'crashFileName' variable will ensure that this branch 1125 * is executed again for all TIDs until the matching report is found 1126 */ 1127 if (funcCnt == -1) { 1128 return; 1129 } 1130 1131 /* If frames successfully recovered, calculate stack hash & populate crash PC */ 1132 arch_hashCallstack(run, funcs, funcCnt, false); 1133 } 1134 1135 void arch_traceExitAnalyze(run_t* run, pid_t pid) { 1136 if (run->mainWorker) { 1137 /* Main fuzzing threads */ 1138 arch_traceExitSaveData(run, pid); 1139 } else { 1140 /* Post crash analysis (e.g. crashes verifier) */ 1141 arch_traceExitAnalyzeData(run, pid); 1142 } 1143 } 1144 1145 #define __WEVENT(status) ((status & 0xFF0000) >> 16) 1146 static void arch_traceEvent(run_t* run, int status, pid_t pid) { 1147 LOG_D("PID: %d, Ptrace event: %d", pid, __WEVENT(status)); 1148 switch (__WEVENT(status)) { 1149 case PTRACE_EVENT_EXIT: { 1150 unsigned long event_msg; 1151 if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &event_msg) == -1) { 1152 PLOG_E("ptrace(PTRACE_GETEVENTMSG,%d) failed", pid); 1153 return; 1154 } 1155 1156 if (WIFEXITED(event_msg)) { 1157 LOG_D("PID: %d exited with exit_code: %lu", pid, 1158 (unsigned long)WEXITSTATUS(event_msg)); 1159 if (WEXITSTATUS(event_msg) == (unsigned long)HF_SAN_EXIT_CODE) { 1160 arch_traceExitAnalyze(run, pid); 1161 } 1162 } else if (WIFSIGNALED(event_msg)) { 1163 LOG_D( 1164 "PID: %d terminated with signal: %lu", pid, (unsigned long)WTERMSIG(event_msg)); 1165 } else { 1166 LOG_D("PID: %d exited with unknown status: %lu", pid, event_msg); 1167 } 1168 } break; 1169 default: 1170 break; 1171 } 1172 1173 ptrace(PTRACE_CONT, pid, 0, 0); 1174 } 1175 1176 void arch_traceAnalyze(run_t* run, int status, pid_t pid) { 1177 /* 1178 * It's a ptrace event, deal with it elsewhere 1179 */ 1180 if (WIFSTOPPED(status) && __WEVENT(status)) { 1181 return arch_traceEvent(run, status, pid); 1182 } 1183 1184 if (WIFSTOPPED(status)) { 1185 /* 1186 * If it's an interesting signal, save the testcase 1187 */ 1188 if (arch_sigs[WSTOPSIG(status)].important) { 1189 /* 1190 * If fuzzer worker is from core fuzzing process run full 1191 * analysis. Otherwise just unwind and get stack hash signature. 1192 */ 1193 if (run->mainWorker) { 1194 arch_traceSaveData(run, pid); 1195 } else { 1196 arch_traceAnalyzeData(run, pid); 1197 } 1198 } 1199 /* Do not deliver SIGSTOP, as we don't support PTRACE_LISTEN anyway */ 1200 int sig = (WSTOPSIG(status) != SIGSTOP) ? WSTOPSIG(status) : 0; 1201 ptrace(PTRACE_CONT, pid, 0, sig); 1202 return; 1203 } 1204 1205 /* 1206 * Resumed by delivery of SIGCONT 1207 */ 1208 if (WIFCONTINUED(status)) { 1209 return; 1210 } 1211 1212 /* 1213 * Process exited 1214 */ 1215 if (WIFEXITED(status)) { 1216 /* 1217 * Target exited with sanitizer defined exitcode (used when SIGABRT is not monitored) 1218 */ 1219 if (WEXITSTATUS(status) == (unsigned long)HF_SAN_EXIT_CODE) { 1220 arch_traceExitAnalyze(run, pid); 1221 } 1222 return; 1223 } 1224 1225 if (WIFSIGNALED(status)) { 1226 return; 1227 } 1228 1229 abort(); /* NOTREACHED */ 1230 } 1231 1232 static bool arch_listThreads(int tasks[], size_t thrSz, int pid) { 1233 char path[512]; 1234 snprintf(path, sizeof(path), "/proc/%d/task", pid); 1235 1236 /* An optimization, the number of threads is st.st_nlink - 2 (. and ..) */ 1237 struct stat st; 1238 if (stat(path, &st) != -1) { 1239 if (st.st_nlink == 3) { 1240 tasks[0] = pid; 1241 tasks[1] = 0; 1242 return true; 1243 } 1244 } 1245 1246 size_t count = 0; 1247 DIR* dir = opendir(path); 1248 if (!dir) { 1249 PLOG_E("Couldn't open dir '%s'", path); 1250 return false; 1251 } 1252 defer { 1253 closedir(dir); 1254 }; 1255 1256 for (;;) { 1257 errno = 0; 1258 const struct dirent* res = readdir(dir); 1259 if (res == NULL && errno != 0) { 1260 PLOG_E("Couldn't read contents of '%s'", path); 1261 return false; 1262 } 1263 1264 if (res == NULL) { 1265 break; 1266 } 1267 1268 pid_t pid = (pid_t)strtol(res->d_name, (char**)NULL, 10); 1269 if (pid == 0) { 1270 LOG_D("The following dir entry couldn't be converted to pid_t '%s'", res->d_name); 1271 continue; 1272 } 1273 1274 tasks[count++] = pid; 1275 LOG_D("Added pid '%d' from '%s/%s'", pid, path, res->d_name); 1276 1277 if (count >= thrSz) { 1278 break; 1279 } 1280 } 1281 PLOG_D("Total number of threads in pid '%d': '%zd'", pid, count); 1282 tasks[count + 1] = 0; 1283 if (count < 1) { 1284 return false; 1285 } 1286 return true; 1287 } 1288 1289 bool arch_traceWaitForPidStop(pid_t pid) { 1290 for (;;) { 1291 int status; 1292 pid_t ret = wait4(pid, &status, __WALL | WUNTRACED, NULL); 1293 if (ret == -1 && errno == EINTR) { 1294 continue; 1295 } 1296 if (ret == -1) { 1297 PLOG_W("wait4(pid=%d) failed", pid); 1298 return false; 1299 } 1300 if (!WIFSTOPPED(status)) { 1301 LOG_W("PID %d not in a stopped state - status:%d", pid, status); 1302 return false; 1303 } 1304 return true; 1305 } 1306 } 1307 1308 #define MAX_THREAD_IN_TASK 4096 1309 bool arch_traceAttach(run_t* run) { 1310 /* 1311 * It should be present since, at least, Linux kernel 3.8, but 1312 * not always defined in kernel-headers 1313 */ 1314 #if !defined(PTRACE_O_EXITKILL) 1315 #define PTRACE_O_EXITKILL (1 << 20) 1316 #endif /* !defined(PTRACE_O_EXITKILL) */ 1317 long seize_options = 1318 PTRACE_O_TRACECLONE | PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_EXITKILL; 1319 /* The event is only used with sanitizers */ 1320 if (run->global->sanitizer.enable) { 1321 seize_options |= PTRACE_O_TRACEEXIT; 1322 } 1323 1324 if (!arch_traceWaitForPidStop(run->pid)) { 1325 return false; 1326 } 1327 1328 if (ptrace(PTRACE_SEIZE, run->pid, NULL, seize_options) == -1) { 1329 PLOG_W("Couldn't ptrace(PTRACE_SEIZE) to pid: %d", (int)run->pid); 1330 return false; 1331 } 1332 1333 LOG_D("Attached to PID: %d", (int)run->pid); 1334 1335 int tasks[MAX_THREAD_IN_TASK + 1] = {0}; 1336 if (!arch_listThreads(tasks, MAX_THREAD_IN_TASK, run->pid)) { 1337 LOG_E("Couldn't read thread list for pid '%d'", run->pid); 1338 return false; 1339 } 1340 1341 for (int i = 0; i < MAX_THREAD_IN_TASK && tasks[i]; i++) { 1342 if (tasks[i] == run->pid) { 1343 continue; 1344 } 1345 if (ptrace(PTRACE_SEIZE, tasks[i], NULL, seize_options) == -1) { 1346 PLOG_W("Couldn't ptrace(PTRACE_SEIZE) to pid: %d", tasks[i]); 1347 continue; 1348 } 1349 LOG_D("Attached to PID: %d (thread_group:%d)", tasks[i], run->pid); 1350 } 1351 1352 if (ptrace(PTRACE_CONT, run->pid, NULL, NULL) == -1) { 1353 PLOG_W("ptrace(PTRACE_CONT) to pid: %d", (int)run->pid); 1354 } 1355 1356 return true; 1357 } 1358 1359 void arch_traceDetach(pid_t pid) { 1360 if (syscall(__NR_kill, pid, 0) == -1 && errno == ESRCH) { 1361 LOG_D("PID: %d no longer exists", pid); 1362 return; 1363 } 1364 1365 int tasks[MAX_THREAD_IN_TASK + 1] = {0}; 1366 if (!arch_listThreads(tasks, MAX_THREAD_IN_TASK, pid)) { 1367 LOG_E("Couldn't read thread list for pid '%d'", pid); 1368 return; 1369 } 1370 1371 for (int i = 0; i < MAX_THREAD_IN_TASK && tasks[i]; i++) { 1372 ptrace(PTRACE_INTERRUPT, tasks[i], NULL, NULL); 1373 arch_traceWaitForPidStop(tasks[i]); 1374 ptrace(PTRACE_DETACH, tasks[i], NULL, NULL); 1375 } 1376 } 1377 1378 void arch_traceSignalsInit(honggfuzz_t* hfuzz) { 1379 /* Default is true for all platforms except Android */ 1380 arch_sigs[SIGABRT].important = hfuzz->cfg.monitorSIGABRT; 1381 1382 /* Default is false */ 1383 arch_sigs[SIGVTALRM].important = hfuzz->timing.tmoutVTALRM; 1384 } 1385