static void __afl_start_forkserver(void) {
static u8 tmp[
4
];
s32 child_pid;
u8 child_stopped
=
0
;
/
*
Phone home
and
tell the parent that we
're OK. If parent isn'
t there,
assume we're
not
running
in
forkserver mode
and
just execute program.
*
/
if
(write(FORKSRV_FD
+
1
, tmp,
4
) !
=
4
)
return
;
/
/
向状态管道写入
4
字节告知已启动
while
(
1
) {
u32 was_killed;
int
status;
/
*
Wait
for
parent by reading
from
the pipe. Abort
if
read fails.
*
/
/
*
当子进程超时,父进程会kill掉子进程
*
/
if
(read(FORKSRV_FD, &was_killed,
4
) !
=
4
) _exit(
1
);
/
*
If we stopped the child
in
persistent mode, but there was a race
condition
and
afl
-
fuzz already issued SIGKILL, write off the old
process.
*
/
/
*
如果在persistent mode下,且子进程已经被killed
*
/
if
(child_stopped && was_killed) {
child_stopped
=
0
;
if
(waitpid(child_pid, &status,
0
) <
0
) _exit(
1
);
}
if
(!child_stopped) {
/
/
如果子进程真的彻底结束了
/
*
Once woken up, create a clone of our process.
*
/
/
/
重新fork一次
child_pid
=
fork();
if
(child_pid <
0
) _exit(
1
);
/
*
In child process: close fds, resume execution.
*
/
/
/
如果是fork出的子进程
if
(!child_pid) {
close(FORKSRV_FD);
/
/
关闭对应描述符。然后返回执行真正的程序
close(FORKSRV_FD
+
1
);
return
;
}
}
else
{
/
*
Special handling
for
persistent mode:
if
the child
is
alive but
currently stopped, simply restart it with SIGCONT.
*
/
/
*
如果子进程并非彻底结束而是暂停
*
/
/
*
重新启动这个暂停的子进程
*
/
kill(child_pid, SIGCONT);
child_stopped
=
0
;
}
/
*
In parent process: write PID to pipe, then wait
for
child.
*
/
/
/
在父进程(fork
-
server)中,向afl
-
fuzzer写
4
字节(子进程pid)到管道,告知fuzzer
if
(write(FORKSRV_FD
+
1
, &child_pid,
4
) !
=
4
) _exit(
1
);
/
/
读取子进程退出状态
if
(waitpid(child_pid, &status, is_persistent ? WUNTRACED :
0
) <
0
)
_exit(
1
);
/
*
In persistent mode, the child stops itself with SIGSTOP to indicate
a successful run. In this case, we want to wake it up without forking
again.
*
/
/
/
子进程收到停止信号,此时子进程可能是停止或结束。
if
(WIFSTOPPED(status)) child_stopped
=
1
;
/
/
child_stopped
=
1
则不确定究竟是否彻底结束
/
/
向状态管道写入
4
字节
if
(write(FORKSRV_FD
+
1
, &status,
4
) !
=
4
) _exit(
1
);
}
}