1. afl-fuzz部分
afl-fuzz部分和非qemu模式是相同的,主要是通过管道接收来自forkserver传入的status信息,通过status信息来判断是否存在crash
if (unlikely(/* A normal crash/abort */(WIFSIGNALED(fsrv->child_status)) ||/* special handling for msan and lsan */(fsrv->uses_asan &&(WEXITSTATUS(fsrv->child_status) == MSAN_ERROR ||WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) ||/* the custom crash_exitcode was returned by the target */(fsrv->uses_crash_exitcode &&WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
主要是通过这一段判断,如果是crash,child_status的某些值会显示signal的值
2. qemu部分
在cpu-exec.c的afl_forkserver函数中,
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);/* Collect translation requests until child dies and closes the pipe. */afl_wait_tsl(cpu, t_fd[0]);if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) {printf("waitpid failed with errno: %d (%s)\n", errno, strerror(errno));exit(6);}/* In persistent mode, the child stops itself with SIGSTOP to indicatea successful run. In this case, we want to wake it up without forkingagain. */if (WIFSTOPPED(status))child_stopped = 1;else if (unlikely(first_run && is_persistent)) {fprintf(stderr, "[AFL] ERROR: no persistent iteration executed\n");exit(12); // Persistent is wrong}first_run = 0;if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
afl_wait_tsl函数return后,waitpid这里去获取子进程的状态,通过wait子进程使其退出,将子进程状态存入status变量,并返回pid,最后write写回管道关于status的值。