1 /*
2 *
3 * honggfuzz - architecture dependent code (LINUX/PTRACE)
4 * -----------------------------------------
5 *
6 * Author: Robert Swiecki <swiecki@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];
arch_sigName(int signo)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
arch_getProcMem(pid_t pid,uint8_t * buf,size_t len,REG_TYPE pc)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
arch_getPC(pid_t pid,REG_TYPE * pc,REG_TYPE * status_reg HF_ATTR_UNUSED)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
arch_getInstrStr(pid_t pid,REG_TYPE * pc,char * instr)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
arch_hashCallstack(run_t * run,funcs_t * funcs,size_t funcCnt,bool enableMasking)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
arch_traceGenerateReport(pid_t pid,run_t * run,funcs_t * funcs,size_t funcCnt,siginfo_t * si,const char * instr)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
arch_traceAnalyzeData(run_t * run,pid_t pid)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
arch_traceSaveData(run_t * run,pid_t pid)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 */
arch_parseAsanReport(run_t * run,pid_t pid,funcs_t * funcs,void ** crashAddr,char ** op)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 */
arch_traceExitSaveData(run_t * run,pid_t pid)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
arch_traceExitAnalyzeData(run_t * run,pid_t pid)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
arch_traceExitAnalyze(run_t * run,pid_t pid)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)
arch_traceEvent(run_t * run,int status,pid_t pid)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
arch_traceAnalyze(run_t * run,int status,pid_t pid)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
arch_listThreads(int tasks[],size_t thrSz,int pid)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
arch_traceWaitForPidStop(pid_t pid)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
arch_traceAttach(run_t * run)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
arch_traceDetach(pid_t pid)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
arch_traceSignalsInit(honggfuzz_t * hfuzz)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