about summary refs log tree commit diff
path: root/src/afl-fuzz-run.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-fuzz-run.c')
-rw-r--r--src/afl-fuzz-run.c65
1 files changed, 34 insertions, 31 deletions
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 850a18bc..3a178e87 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -27,10 +27,12 @@
 #include <sys/time.h>
 #include <signal.h>
 
+#include "cmplog.h"
+
 /* Execute target application, monitoring for timeouts. Return status
-   information. The called program will update afl->fsrv.trace_bits. */
+   information. The called program will update afl->fsrv->trace_bits. */
 
-u8 run_target(afl_state_t *afl, u32 timeout) {
+u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
 
   s32 res;
   u32 exec_ms;
@@ -38,46 +40,46 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
   int status = 0;
   u32 tb4;
 
-  afl->fsrv.child_timed_out = 0;
+  fsrv->child_timed_out = 0;
 
-  /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we
+  /* After this memset, fsrv->trace_bits[] are effectively volatile, so we
      must prevent any earlier operations from venturing into that
      territory. */
 
-  memset(afl->fsrv.trace_bits, 0, afl->fsrv.map_size);
+  memset(fsrv->trace_bits, 0, fsrv->map_size);
 
   MEM_BARRIER();
 
   /* we have the fork server (or faux server) up and running, so simply
       tell it to have at it, and then read back PID. */
 
-  if ((res = write(afl->fsrv.fsrv_ctl_fd, &afl->fsrv.prev_timed_out, 4)) != 4) {
+  if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
 
     if (afl->stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
 
   }
 
-  if ((res = read(afl->fsrv.fsrv_st_fd, &afl->fsrv.child_pid, 4)) != 4) {
+  if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
 
     if (afl->stop_soon) return 0;
     RPFATAL(res, "Unable to request new process from fork server (OOM?)");
 
   }
 
-  if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
+  if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
 
   exec_ms =
-      read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout, &afl->stop_soon);
+      read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, &afl->stop_soon);
 
   if (exec_ms > timeout) {
 
     /* If there was no response from forkserver after timeout seconds,
     we kill the child. The forkserver should inform us afterwards */
 
-    kill(afl->fsrv.child_pid, SIGKILL);
-    afl->fsrv.child_timed_out = 1;
-    if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
+    kill(fsrv->child_pid, SIGKILL);
+    fsrv->child_timed_out = 1;
+    if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
 
   }
 
@@ -104,30 +106,30 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
          "\n\n"
          "If all else fails you can disable the fork server via "
          "AFL_NO_FORKSRV=1.\n",
-         afl->fsrv.mem_limit);
+         fsrv->mem_limit);
     RPFATAL(res, "Unable to communicate with fork server");
 
   }
 
-  if (!WIFSTOPPED(status)) afl->fsrv.child_pid = 0;
+  if (!WIFSTOPPED(status)) fsrv->child_pid = 0;
 
   ++afl->total_execs;
 
-  /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the
-     compiler below this point. Past this location, afl->fsrv.trace_bits[]
+  /* Any subsequent operations on fsrv->trace_bits must not be moved by the
+     compiler below this point. Past this location, fsrv->trace_bits[]
      behave very normally and do not have to be treated as volatile. */
 
   MEM_BARRIER();
 
-  tb4 = *(u32 *)afl->fsrv.trace_bits;
+  tb4 = *(u32 *)fsrv->trace_bits;
 
 #ifdef WORD_SIZE_64
-  classify_counts(afl, (u64 *)afl->fsrv.trace_bits);
+  classify_counts(afl, (u64 *)fsrv->trace_bits);
 #else
-  classify_counts(afl, (u32 *)afl->fsrv.trace_bits);
+  classify_counts(afl, (u32 *)fsrv->trace_bits);
 #endif                                                     /* ^WORD_SIZE_64 */
 
-  afl->fsrv.prev_timed_out = afl->fsrv.child_timed_out;
+  fsrv->prev_timed_out = fsrv->child_timed_out;
 
   /* Report outcome to caller. */
 
@@ -135,7 +137,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
 
     afl->kill_signal = WTERMSIG(status);
 
-    if (afl->fsrv.child_timed_out && afl->kill_signal == SIGKILL)
+    if (fsrv->child_timed_out && afl->kill_signal == SIGKILL)
       return FAULT_TMOUT;
 
     return FAULT_CRASH;
@@ -145,7 +147,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
   /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
      must use a special exit code. */
 
-  if (afl->fsrv.uses_asan && WEXITSTATUS(status) == MSAN_ERROR) {
+  if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) {
 
     afl->kill_signal = 0;
     return FAULT_CRASH;
@@ -309,11 +311,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
   /* Make sure the forkserver is up before we do anything, and let's not
      count its spin-up time toward binary calibration. */
 
-  if (!afl->fsrv.fsrv_pid)
-    afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon);
-  if (afl->dumb_mode != 1 && !afl->no_forkserver && !afl->cmplog_fsrv_pid &&
-      afl->shm.cmplog_mode)
-    init_cmplog_forkserver(afl);
+  if (!afl->fsrv.fsrv_pid) {
+    if (afl->shm.cmplog_mode && afl->fsrv.init_child_func != cmplog_exec_child) {
+      FATAL("BUG in afl-fuzz detected. Cmplog mode not set correctly.");
+    }
+    afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child_output);
+  }
 
   if (q->exec_cksum)
     memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size);
@@ -329,7 +332,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
 
     write_to_testcase(afl, use_mem, q->len);
 
-    fault = run_target(afl, use_tmout);
+    fault = run_target(afl, &afl->fsrv, use_tmout);
 
     /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
        we want to bail out quickly. */
@@ -546,7 +549,7 @@ void sync_fuzzers(afl_state_t *afl) {
 
         write_to_testcase(afl, mem, st.st_size);
 
-        fault = run_target(afl, afl->fsrv.exec_tmout);
+        fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
 
         if (afl->stop_soon) goto close_sync;
 
@@ -633,7 +636,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
 
       write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail);
 
-      fault = run_target(afl, afl->fsrv.exec_tmout);
+      fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
       ++afl->trim_execs;
 
       if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming;
@@ -740,7 +743,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
 
   write_to_testcase(afl, out_buf, len);
 
-  fault = run_target(afl, afl->fsrv.exec_tmout);
+  fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
 
   if (afl->stop_soon) return 1;