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.c204
1 files changed, 165 insertions, 39 deletions
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index ac7a1600..cd04e23d 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 */
@@ -819,7 +838,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
            "have a\n"
            "    restrictive memory limit configured, this is expected; please "
            "read\n"
-           "    %s/notes_for_asan.md for help.\n",
+           "    %s/notes_for_asan.md for help and run with '-m 0'.\n",
            doc_path);
 
     } else if (!fsrv->mem_limit) {
@@ -827,18 +846,21 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
       SAYF("\n" cLRD "[-] " cRST
            "Whoops, the target binary crashed suddenly, "
            "before receiving any input\n"
-           "    from the fuzzer! There are several probable explanations:\n\n"
-
-           "    - The target binary requires a large map and crashes before "
-           "reporting.\n"
-           "      Set a high value (e.g. AFL_MAP_SIZE=8000000) or use "
-           "AFL_DEBUG=1 to see the\n"
-           "      message from the target binary\n\n"
-
-           "    - The binary is just buggy and explodes entirely on its own. "
-           "If so, you\n"
-           "      need to fix the underlying problem or find a better "
-           "replacement.\n\n"
+           "    from the fuzzer! You can try the following:\n\n"
+
+           "    - The target binary crashes because necessary runtime "
+           "conditions it needs\n"
+           "      are not met. Try to:\n"
+           "      1. Run again with AFL_DEBUG=1 set and check the output of "
+           "the target\n"
+           "         binary for clues.\n"
+           "      2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
+           "analyze the\n"
+           "         generated core dump.\n\n"
+
+           "    - Possibly the target requires a huge coverage map and has "
+           "CTORS.\n"
+           "      Retry with setting AFL_MAP_SIZE=10000000.\n\n"
 
            MSG_FORK_ON_APPLE
 
@@ -854,13 +876,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
       SAYF("\n" cLRD "[-] " cRST
            "Whoops, the target binary crashed suddenly, "
            "before receiving any input\n"
-           "    from the fuzzer! There are several probable explanations:\n\n"
-
-           "    - The target binary requires a large map and crashes before "
-           "reporting.\n"
-           "      Set a high value (e.g. AFL_MAP_SIZE=8000000) or use "
-           "AFL_DEBUG=1 to see the\n"
-           "      message from the target binary\n\n"
+           "    from the fuzzer! You can try the following:\n\n"
+
+           "    - The target binary crashes because necessary runtime "
+           "conditions it needs\n"
+           "      are not met. Try to:\n"
+           "      1. Run again with AFL_DEBUG=1 set and check the output of "
+           "the target\n"
+           "         binary for clues.\n"
+           "      2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
+           "analyze the\n"
+           "         generated core dump.\n\n"
 
            "    - The current memory limit (%s) is too restrictive, causing "
            "the\n"
@@ -878,13 +904,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
            "      estimate the required amount of virtual memory for the "
            "binary.\n\n"
 
-           "    - The binary is just buggy and explodes entirely on its own. "
-           "If so, you\n"
-           "      need to fix the underlying problem or find a better "
-           "replacement.\n\n"
-
            MSG_FORK_ON_APPLE
 
+           "    - Possibly the target requires a huge coverage map and has "
+           "CTORS.\n"
+           "      Retry with setting AFL_MAP_SIZE=10000000.\n\n"
+
            "    - Less likely, there is a horrible bug in the fuzzer. If other "
            "options\n"
            "      fail, poke <afl-users@googlegroups.com> for troubleshooting "
@@ -913,7 +938,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
          "with ASAN and\n"
          "    you have a restrictive memory limit configured, this is "
          "expected; please\n"
-         "    read %s/notes_for_asan.md for help.\n",
+         "    read %s/notes_for_asan.md for help and run with '-m 0'.\n",
          doc_path);
 
   } else if (!fsrv->mem_limit) {
@@ -921,10 +946,22 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
     SAYF("\n" cLRD "[-] " cRST
          "Hmm, looks like the target binary terminated before we could complete"
          " a\n"
-         "handshake with the injected code.\n"
-         "Most likely the target has a huge coverage map, retry with setting"
-         " the\n"
-         "environment variable AFL_MAP_SIZE=8000000\n"
+         "handshake with the injected code. You can try the following:\n\n"
+
+         "    - The target binary crashes because necessary runtime conditions "
+         "it needs\n"
+         "      are not met. Try to:\n"
+         "      1. Run again with AFL_DEBUG=1 set and check the output of the "
+         "target\n"
+         "         binary for clues.\n"
+         "      2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
+         "analyze the\n"
+         "         generated core dump.\n\n"
+
+         "    - Possibly the target requires a huge coverage map and has "
+         "CTORS.\n"
+         "      Retry with setting AFL_MAP_SIZE=10000000.\n\n"
+
          "Otherwise there is a horrible bug in the fuzzer.\n"
          "Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
 
@@ -936,14 +973,23 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
         "\n" cLRD "[-] " cRST
         "Hmm, looks like the target binary terminated "
         "before we could complete a\n"
-        "    handshake with the injected code. There are %s probable "
-        "explanations:\n\n"
+        "    handshake with the injected code. You can try the following:\n\n"
 
         "%s"
 
-        "    - Most likely the target has a huge coverage map, retry with "
-        "setting the\n"
-        "      environment variable AFL_MAP_SIZE=8000000\n\n"
+        "    - The target binary crashes because necessary runtime conditions "
+        "it needs\n"
+        "      are not met. Try to:\n"
+        "      1. Run again with AFL_DEBUG=1 set and check the output of the "
+        "target\n"
+        "         binary for clues.\n"
+        "      2. Run again with AFL_DEBUG=1 and 'ulimit -c unlimited' and "
+        "analyze the\n"
+        "         generated core dump.\n\n"
+
+        "    - Possibly the target requires a huge coverage map and has "
+        "CTORS.\n"
+        "      Retry with setting AFL_MAP_SIZE=10000000.\n\n"
 
         "    - The current memory limit (%s) is too restrictive, causing an "
         "OOM\n"
@@ -968,7 +1014,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
         "options\n"
         "      fail, poke <afl-users@googlegroups.com> for troubleshooting "
         "tips.\n",
-        getenv(DEFER_ENV_VAR) ? "three" : "two",
         getenv(DEFER_ENV_VAR)
             ? "    - You are using deferred forkserver, but __AFL_INIT() is "
               "never\n"
@@ -1016,6 +1061,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;
@@ -1048,12 +1119,14 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
       if (unlikely(fsrv->no_unlink)) {
 
-        fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
+        fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC,
+                  DEFAULT_PERMISSION);
 
       } else {
 
         unlink(fsrv->out_file);                           /* Ignore errors. */
-        fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
+        fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL,
+                  DEFAULT_PERMISSION);
 
       }
 
@@ -1128,6 +1201,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; }
@@ -1227,6 +1320,39 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
           (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;