static void arch_ptraceEvent(honggfuzz_t * hfuzz, fuzzer_t * fuzzer, int status, pid_t pid) { unsigned long event_msg; if (ptrace(PTRACE_GETEVENTMSG, pid, NULL, &event_msg) == -1) { LOGMSG(l_ERROR, "ptrace(PTRACE_GETEVENTMSG,%d) failed", pid); return; } LOGMSG(l_DEBUG, "PID: %d, Ptrace event: %d, event_msg: %ld", pid, __WEVENT(status), event_msg); switch (__WEVENT(status)) { case PTRACE_EVENT_EXIT: if (WIFEXITED(event_msg)) { LOGMSG(l_DEBUG, "PID: %d exited with exit_code: %d", pid, WEXITSTATUS(event_msg)); if (WEXITSTATUS(event_msg) == HF_MSAN_EXIT_CODE) { arch_ptraceSaveData(hfuzz, pid, fuzzer); } } else if (WIFSIGNALED(event_msg)) { LOGMSG(l_DEBUG, "PID: %d terminated with signal: %d", pid, WTERMSIG(event_msg)); } else { LOGMSG(l_DEBUG, "PID: %d exited with unknown status: %ld", pid, event_msg); } break; default: break; } ptrace(PT_CONTINUE, pid, 0, 0); return; }
void arch_ptraceAnalyze(honggfuzz_t * hfuzz, int status, pid_t pid, fuzzer_t * fuzzer) { /* * It's a ptrace event, deal with it elsewhere */ if (WIFSTOPPED(status) && __WEVENT(status)) { return arch_ptraceEvent(hfuzz, fuzzer, status, pid); } if (WIFSTOPPED(status)) { /* * If it's an interesting signal, save the testcase */ if (arch_sigs[WSTOPSIG(status)].important) { /* * If fuzzer worker is from core fuzzing process run full * analysis. Otherwise just unwind and get stack hash signature. */ if (fuzzer->mainWorker) { arch_ptraceSaveData(hfuzz, pid, fuzzer); } else { arch_ptraceAnalyzeData(hfuzz, pid, fuzzer); } } ptrace(PTRACE_CONT, pid, 0, WSTOPSIG(status)); return; } /* * Resumed by delivery of SIGCONT */ if (WIFCONTINUED(status)) { return; } /* * Process exited */ if (WIFEXITED(status)) { /* * Target exited with sanitizer defined exitcode (used when SIGABRT is not monitored) */ if ((WEXITSTATUS(status) == HF_MSAN_EXIT_CODE) || (WEXITSTATUS(status) == HF_ASAN_EXIT_CODE) || (WEXITSTATUS(status) == HF_UBSAN_EXIT_CODE)) { arch_ptraceExitAnalyze(hfuzz, pid, fuzzer, WEXITSTATUS(status)); } return; } if (WIFSIGNALED(status)) { return; } abort(); /* NOTREACHED */ }
void arch_ptraceAnalyze(honggfuzz_t * hfuzz, int status, pid_t pid, fuzzer_t * fuzzer) { /* * It's a ptrace event, deal with it elsewhere */ if (WIFSTOPPED(status) && __WEVENT(status)) { return arch_ptraceEvent(hfuzz, fuzzer, status, pid); } if (WIFSTOPPED(status)) { int curStatus = WSTOPSIG(status); /* * If it's an interesting signal, save the testcase */ if (arch_sigs[WSTOPSIG(status)].important) { arch_ptraceSaveData(hfuzz, pid, fuzzer); /* * An kind of ugly (although necessary) hack due to custom signal handlers * in Android from debuggerd. If we pass one of the monitored signals, * we'll end-up running the processing routine twice. A cost that we * don't want to pay. */ #if defined(__ANDROID__) curStatus = SIGINT; #endif } ptrace(PT_CONTINUE, pid, 0, curStatus); return; } /* * Resumed by delivery of SIGCONT */ if (WIFCONTINUED(status)) { return; } /* * Process exited */ if (WIFEXITED(status)) { return; } if (WIFSIGNALED(status)) { return; } abort(); /* NOTREACHED */ return; }
void arch_ptraceAnalyze(honggfuzz_t * hfuzz, int status, pid_t pid, fuzzer_t * fuzzer) { /* * It's a ptrace event, deal with it elsewhere */ if (WIFSTOPPED(status) && __WEVENT(status)) { return arch_ptraceEvent(hfuzz, fuzzer, status, pid); } if (WIFSTOPPED(status)) { /* * If it's an interesting signal, save the testcase */ if (arch_sigs[WSTOPSIG(status)].important) { /* * If fuzzer worker is from core fuzzing process run full * analysis. Otherwise just unwind and get stack hash signature. */ if (fuzzer->mainWorker) { arch_ptraceSaveData(hfuzz, pid, fuzzer); } else { arch_ptraceAnalyzeData(pid, fuzzer); } } ptrace(PT_CONTINUE, pid, 0, WSTOPSIG(status)); return; } /* * Resumed by delivery of SIGCONT */ if (WIFCONTINUED(status)) { return; } /* * Process exited */ if (WIFEXITED(status)) { return; } if (WIFSIGNALED(status)) { return; } abort(); /* NOTREACHED */ }