• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 = &regs,
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, &regs)) {
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*)&regs;
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*)&regs;
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*)&regs;
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*)&regs;
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*)&regs;
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*)&regs;
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