void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) { timer_t timerid; if (arch_setTimer(&timerid) == false) { LOGMSG(l_FATAL, "Couldn't set timer"); } int perfFd[3]; if (hfuzz->pid == 0) { int status; pid_t pid = wait4(fuzzer->pid, &status, __WNOTHREAD | __WALL | WUNTRACED, NULL); if (pid != pid) { LOGMSG(l_FATAL, "wait4() =! pid (%d)", fuzzer->pid); } if (!WIFSTOPPED(status)) { LOGMSG(l_FATAL, "PID '%d' is not in a stopped state", fuzzer->pid); } if (arch_ptraceAttach(fuzzer->pid) == false) { LOGMSG(l_FATAL, "Couldn't attach to pid %d", fuzzer->pid); } if (arch_perfEnable(fuzzer->pid, hfuzz, perfFd) == false) { LOGMSG(l_FATAL, "Couldn't enable perf counters for pid %d", fuzzer->pid); } arch_ptraceAnalyze(hfuzz, status, fuzzer->pid, fuzzer); } for (;;) { int status; pid_t pid = wait3(&status, __WNOTHREAD | __WALL | WUNTRACED, NULL); LOGMSG(l_DEBUG, "PID '%d' returned with status '%d'", pid, status); if (pid == -1 && errno == EINTR) { arch_checkTimeLimit(hfuzz, fuzzer); continue; } if (pid == -1 && errno == ECHILD) { if (hfuzz->pid == 0) { arch_perfAnalyze(hfuzz, fuzzer, perfFd); } LOGMSG(l_DEBUG, "No more processes to track"); arch_removeTimer(&timerid); return; } if (pid == -1) { LOGMSG_P(l_FATAL, "wait3() failed"); } if (hfuzz->pid == 0) { uint64_t tmp = arch_ptraceGetCustomPerf(hfuzz, pid); if (tmp != 0ULL) { fuzzer->branchCnt[3] = tmp; } arch_ptraceAnalyze(hfuzz, status, pid, fuzzer); } } }
void arch_reapChild(honggfuzz_t * hfuzz, fuzzer_t * fuzzer) { pid_t ptracePid = (hfuzz->pid > 0) ? hfuzz->pid : fuzzer->pid; pid_t childPid = fuzzer->pid; timer_t timerid; if (arch_setTimer(&timerid) == false) { LOG_F("Couldn't set timer"); } if (arch_ptraceWaitForPidStop(childPid) == false) { LOG_F("PID %d not in a stopped state", childPid); } LOG_D("PID: %d is in a stopped state now", childPid); static bool ptraceAttached = false; if (ptraceAttached == false) { if (arch_ptraceAttach(ptracePid) == false) { LOG_F("arch_ptraceAttach(pid=%d) failed", ptracePid); } /* In case we fuzz a long-lived process (-p pid) we attach to it once only */ if (ptracePid != childPid) { ptraceAttached = true; } } /* A long-lived processed could have already exited, and we wouldn't know */ if (kill(ptracePid, 0) == -1) { PLOG_F("Liveness of %d questioned", ptracePid); } perfFd_t perfFds; if (arch_perfEnable(ptracePid, hfuzz, &perfFds) == false) { LOG_F("Couldn't enable perf counters for pid %d", ptracePid); } if (kill(childPid, SIGCONT) == -1) { PLOG_F("Restarting PID: %d failed", childPid); } for (;;) { int status; pid_t pid = wait4(-1, &status, __WALL | __WNOTHREAD, NULL); if (pid == -1 && errno == EINTR) { if (hfuzz->tmOut) { arch_checkTimeLimit(hfuzz, fuzzer); } continue; } if (pid == -1 && errno == ECHILD) { LOG_D("No more processes to track"); break; } if (pid == -1) { PLOG_F("wait4() failed"); } LOG_D("PID '%d' returned with status '%d'", pid, status); arch_ptraceGetCustomPerf(hfuzz, ptracePid, &fuzzer->hwCnts.customCnt); if (ptracePid == childPid) { arch_ptraceAnalyze(hfuzz, status, pid, fuzzer); continue; } if (pid == childPid && (WIFEXITED(status) || WIFSIGNALED(status))) { break; } if (pid == childPid) { continue; } arch_ptraceAnalyze(hfuzz, status, pid, fuzzer); } arch_removeTimer(&timerid); arch_perfAnalyze(hfuzz, fuzzer, &perfFds); return; }