about summary refs log tree commit diff
path: root/src/afl-forkserver.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-forkserver.c')
-rw-r--r--src/afl-forkserver.c124
1 files changed, 118 insertions, 6 deletions
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index c2d552cd..727e7f8d 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -42,6 +42,7 @@
 #include <errno.h>
 #include <signal.h>
 #include <fcntl.h>
+#include <limits.h>
 #include <sys/time.h>
 #include <sys/wait.h>
 #include <sys/resource.h>
@@ -126,7 +127,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->last_run_timed_out = 0;
 
   fsrv_to->init_child_func = from->init_child_func;
-  // Note: do not copy ->add_extra_func
+  // Note: do not copy ->add_extra_func or ->persistent_record*
 
   list_append(&fsrv_list, fsrv_to);
 
@@ -364,6 +365,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
   if (!be_quiet) { ACTF("Spinning up the fork server..."); }
 
+#ifdef AFL_PERSISTENT_RECORD
+  if (unlikely(fsrv->persistent_record)) {
+
+    fsrv->persistent_record_data =
+        (u8 **)ck_alloc(fsrv->persistent_record * sizeof(u8 *));
+    fsrv->persistent_record_len =
+        (u32 *)ck_alloc(fsrv->persistent_record * sizeof(u32));
+
+    if (!fsrv->persistent_record_data || !fsrv->persistent_record_len) {
+
+      FATAL("Unable to allocate memory for persistent replay.");
+
+    }
+
+  }
+
+#endif
+
   if (fsrv->use_fauxsrv) {
 
     /* TODO: Come up with some nice way to initialize this all */
@@ -483,7 +502,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); }
 
-    /* Set sane defaults for ASAN if nothing else specified. */
+    /* Set sane defaults for ASAN if nothing else is specified. */
 
     if (!getenv("ASAN_OPTIONS"))
       setenv("ASAN_OPTIONS",
@@ -500,7 +519,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
              "handle_sigill=0",
              1);
 
-    /* Set sane defaults for UBSAN if nothing else specified. */
+    /* Set sane defaults for UBSAN if nothing else is specified. */
 
     if (!getenv("UBSAN_OPTIONS"))
       setenv("UBSAN_OPTIONS",
@@ -538,6 +557,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
            "handle_sigill=0",
            1);
 
+    /* LSAN, too, does not support abort_on_error=1. */
+
+    if (!getenv("LSAN_OPTIONS"))
+      setenv("LSAN_OPTIONS",
+            "exitcode=" STRINGIFY(LSAN_ERROR) ":"
+            "fast_unwind_on_malloc=0:"
+            "symbolize=0:"
+            "print_suppressions=0",
+            1);
+
     fsrv->init_child_func(fsrv, argv);
 
     /* Use a distinctive bitmap signature to tell the parent about execv()
@@ -792,7 +821,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
   if (fsrv->last_run_timed_out) {
 
-    FATAL("Timeout while initializing fork server (adjusting -t may help)");
+    FATAL(
+        "Timeout while initializing fork server (setting "
+        "AFL_FORKSRV_INIT_TMOUT may help)");
 
   }
 
@@ -1032,6 +1063,32 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv,
 
 void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
+#ifdef AFL_PERSISTENT_RECORD
+  if (unlikely(fsrv->persistent_record)) {
+
+    fsrv->persistent_record_len[fsrv->persistent_record_idx] = len;
+    fsrv->persistent_record_data[fsrv->persistent_record_idx] = afl_realloc(
+        (void **)&fsrv->persistent_record_data[fsrv->persistent_record_idx],
+        len);
+
+    if (unlikely(!fsrv->persistent_record_data[fsrv->persistent_record_idx])) {
+
+      FATAL("allocating replay memory failed.");
+
+    }
+
+    memcpy(fsrv->persistent_record_data[fsrv->persistent_record_idx], buf, len);
+
+    if (unlikely(++fsrv->persistent_record_idx >= fsrv->persistent_record)) {
+
+      fsrv->persistent_record_idx = 0;
+
+    }
+
+  }
+
+#endif
+
   if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) {
 
     if (unlikely(len > MAX_FILE)) len = MAX_FILE;
@@ -1146,6 +1203,26 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
 
   }
 
+#ifdef AFL_PERSISTENT_RECORD
+  // end of persistent loop?
+  if (unlikely(fsrv->persistent_record &&
+               fsrv->persistent_record_pid != fsrv->child_pid)) {
+
+    fsrv->persistent_record_pid = fsrv->child_pid;
+    u32 idx, val;
+    if (unlikely(!fsrv->persistent_record_idx))
+      idx = fsrv->persistent_record - 1;
+    else
+      idx = fsrv->persistent_record_idx - 1;
+    val = fsrv->persistent_record_len[idx];
+    memset((void *)fsrv->persistent_record_len, 0,
+           fsrv->persistent_record * sizeof(u32));
+    fsrv->persistent_record_len[idx] = val;
+
+  }
+
+#endif
+
   if (fsrv->child_pid <= 0) {
 
     if (*stop_soon_p) { return 0; }
@@ -1238,12 +1315,47 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
   if (unlikely(
           /* A normal crash/abort */
           (WIFSIGNALED(fsrv->child_status)) ||
-          /* special handling for msan */
-          (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
+          /* 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))) {
 
+#ifdef AFL_PERSISTENT_RECORD
+    if (unlikely(fsrv->persistent_record)) {
+
+      char fn[PATH_MAX];
+      u32  i, writecnt = 0;
+      for (i = 0; i < fsrv->persistent_record; ++i) {
+
+        u32 entry = (i + fsrv->persistent_record_idx) % fsrv->persistent_record;
+        u8 *data = fsrv->persistent_record_data[entry];
+        u32 len = fsrv->persistent_record_len[entry];
+        if (likely(len && data)) {
+
+          snprintf(fn, sizeof(fn), "%s/RECORD:%06u,cnt:%06u",
+                   fsrv->persistent_record_dir, fsrv->persistent_record_cnt,
+                   writecnt++);
+          int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
+          if (fd >= 0) {
+
+            ck_write(fd, data, len, fn);
+            close(fd);
+
+          }
+
+        }
+
+      }
+
+      ++fsrv->persistent_record_cnt;
+
+    }
+
+#endif
+
     /* For a proper crash, set last_kill_signal to WTERMSIG, else set it to 0 */
     fsrv->last_kill_signal =
         WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;