about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/afl-cc.c4
-rw-r--r--src/afl-forkserver.c5
-rw-r--r--src/afl-fuzz-bitmap.c2
-rw-r--r--src/afl-fuzz-cmplog.c2
-rw-r--r--src/afl-fuzz-init.c10
-rw-r--r--src/afl-fuzz-mutators.c54
-rw-r--r--src/afl-fuzz-one.c4
-rw-r--r--src/afl-fuzz-run.c10
-rw-r--r--src/afl-fuzz-state.c8
-rw-r--r--src/afl-fuzz-stats.c16
-rw-r--r--src/afl-fuzz.c38
-rw-r--r--src/afl-ld-lto.c11
12 files changed, 118 insertions, 46 deletions
diff --git a/src/afl-cc.c b/src/afl-cc.c
index 1f89bac5..09009334 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -560,12 +560,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
     if (lto_mode && !have_c) {
 
       u8 *ld_path = strdup(AFL_REAL_LD);
-      if (!*ld_path) ld_path = "ld.lld";
+      if (!ld_path || !*ld_path) { ld_path = strdup("ld.lld"); }
+      if (!ld_path) { PFATAL("Could not allocate mem for ld_path"); }
 #if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 12
       cc_params[cc_par_cnt++] = alloc_printf("--ld-path=%s", ld_path);
 #else
       cc_params[cc_par_cnt++] = alloc_printf("-fuse-ld=%s", ld_path);
 #endif
+      free(ld_path);
 
       cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
 
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 727e7f8d..a07e78b4 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -416,7 +416,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
 
     struct rlimit r;
 
-    if (!fsrv->cmplog_binary && fsrv->qemu_mode == false) {
+    if (!fsrv->cmplog_binary && fsrv->qemu_mode == false &&
+        fsrv->frida_mode == false) {
 
       unsetenv(CMPLOG_SHM_ENV_VAR);  // we do not want that in non-cmplog fsrv
 
@@ -1089,7 +1090,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
 
 #endif
 
-  if (likely(fsrv->use_shmem_fuzz && fsrv->shmem_fuzz)) {
+  if (likely(fsrv->use_shmem_fuzz)) {
 
     if (unlikely(len > MAX_FILE)) len = MAX_FILE;
 
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index 3d0228db..97f10e6f 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -397,7 +397,7 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) {
 
 /* Write a message accompanying the crash directory :-) */
 
-static void write_crash_readme(afl_state_t *afl) {
+void write_crash_readme(afl_state_t *afl) {
 
   u8    fn[PATH_MAX];
   s32   fd;
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index 27c6c413..c2e9c80f 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -35,7 +35,7 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
 
   if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); }
 
-  if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) {
+  if (!fsrv->qemu_mode && !fsrv->frida_mode && argv[0] != fsrv->cmplog_binary) {
 
     argv[0] = fsrv->cmplog_binary;
 
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index b6bfbc29..cb586111 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -2031,7 +2031,7 @@ void setup_dirs_fds(afl_state_t *afl) {
 
     fprintf(
         afl->fsrv.plot_file,
-        "# unix_time, cycles_done, cur_path, paths_total, "
+        "# relative_time, cycles_done, cur_path, paths_total, "
         "pending_total, pending_favs, map_size, unique_crashes, "
         "unique_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
 
@@ -2774,6 +2774,14 @@ void check_binary(afl_state_t *afl, u8 *fname) {
 
     WARNF("AFL_PERSISTENT is no longer supported and may misbehave!");
 
+  } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
+
+    OKF("FRIDA Persistent mode configuration options detected.");
+    setenv(PERSIST_ENV_VAR, "1", 1);
+    afl->persistent_mode = 1;
+
+    afl->shmem_testcase_mode = 1;
+
   }
 
   if (afl->fsrv.frida_mode ||
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index c99d9a4d..e27d6fae 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -308,9 +308,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
 u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
                     struct custom_mutator *mutator) {
 
-  u8  needs_write = 0, fault = 0;
+  u8  fault = 0;
   u32 trim_exec = 0;
   u32 orig_len = q->len;
+  u32 out_len = 0;
+  u8 *out_buf = NULL;
 
   u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
 
@@ -397,33 +399,33 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
 
     if (likely(retlen && cksum == q->exec_cksum)) {
 
-      if (afl_realloc((void **)&in_buf, retlen) == NULL) {
-
-        FATAL("can not allocate memory for trim");
-
-      }
-
-      memcpy(in_buf, retbuf, retlen);
-      q->len = retlen;
-
       /* Let's save a clean trace, which will be needed by
-         update_bitmap_score once we're done with the trimming stuff. */
+         update_bitmap_score once we're done with the trimming stuff.
+         Use out_buf NULL check to make this only happen once per trim. */
 
-      if (!needs_write) {
+      if (!out_buf) {
 
-        needs_write = 1;
         memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits,
                afl->fsrv.map_size);
 
       }
 
+      if (afl_realloc((void **)&out_buf, retlen) == NULL) {
+
+        FATAL("can not allocate memory for trim");
+
+      }
+
+      out_len = retlen;
+      memcpy(out_buf, retbuf, retlen);
+
       /* Tell the custom mutator that the trimming was successful */
       afl->stage_cur = mutator->afl_custom_post_trim(mutator->data, 1);
 
       if (afl->not_on_tty && afl->debug) {
 
         SAYF("[Custom Trimming] SUCCESS: %u/%u iterations (now at %u bytes)",
-             afl->stage_cur, afl->stage_max, q->len);
+             afl->stage_cur, afl->stage_max, out_len);
 
       }
 
@@ -456,16 +458,10 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
 
   }
 
-  if (afl->not_on_tty && afl->debug) {
-
-    SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len);
-
-  }
-
-  /* If we have made changes to in_buf, we also need to update the on-disk
+  /* If we have made changes, we also need to update the on-disk
      version of the test case. */
 
-  if (needs_write) {
+  if (out_buf) {
 
     s32 fd;
 
@@ -475,16 +471,28 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
 
     if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); }
 
-    ck_write(fd, in_buf, q->len, q->fname);
+    ck_write(fd, out_buf, out_len, q->fname);
     close(fd);
 
+    /* Update the queue's knowledge of length as soon as we write the file.
+       We do this here so that exit/error cases that *don't* update the file
+       also don't update q->len. */
+    q->len = out_len;
+
     memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size);
     update_bitmap_score(afl, q);
 
   }
 
+  if (afl->not_on_tty && afl->debug) {
+
+    SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len);
+
+  }
+
 abort_trimming:
 
+  if (out_buf) afl_free(out_buf);
   afl->bytes_trim_out += q->len;
   return fault;
 
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index d72d4145..4eeb93de 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -3010,13 +3010,13 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
     u8 res = trim_case(afl, afl->queue_cur, in_buf);
     orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur);
 
-    if (res == FSRV_RUN_ERROR) {
+    if (unlikely(res == FSRV_RUN_ERROR)) {
 
       FATAL("Unable to execute target application");
 
     }
 
-    if (afl->stop_soon) {
+    if (unlikely(afl->stop_soon)) {
 
       ++afl->cur_skipped_paths;
       goto abandon_entry;
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 832f17bb..6e5210b8 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -203,7 +203,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
 
   }
 
-  if (afl->fsrv.shmem_fuzz) {
+  if (likely(afl->fsrv.use_shmem_fuzz)) {
 
     if (!post_process_skipped) {
 
@@ -211,9 +211,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
 
       memcpy(afl->fsrv.shmem_fuzz, new_mem, new_size);
 
-    }
-
-    else {
+    } else {
 
       memcpy(afl->fsrv.shmem_fuzz, mem, skip_at);
 
@@ -244,7 +242,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
 
     return;
 
-  } else if (afl->fsrv.out_file) {
+  } else if (unlikely(!afl->fsrv.use_stdin)) {
 
     if (unlikely(afl->no_unlink)) {
 
@@ -279,7 +277,7 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at,
 
   }
 
-  if (!afl->fsrv.out_file) {
+  if (afl->fsrv.use_stdin) {
 
     if (ftruncate(fd, new_size)) { PFATAL("ftruncate() failed"); }
     lseek(fd, 0, SEEK_SET);
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 28d3339a..c886cb28 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -99,6 +99,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
   afl->cal_cycles = CAL_CYCLES;
   afl->cal_cycles_long = CAL_CYCLES_LONG;
   afl->hang_tmout = EXEC_TIMEOUT;
+  afl->exit_on_time = 0;
   afl->stats_update_freq = 1;
   afl->stats_avg_exec = 0;
   afl->skip_deterministic = 1;
@@ -187,6 +188,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
             afl->afl_env.afl_exit_when_done =
                 get_afl_env(afl_environment_variables[i]) ? 1 : 0;
 
+          } else if (!strncmp(env, "AFL_EXIT_ON_TIME",
+
+                              afl_environment_variable_len)) {
+
+            afl->afl_env.afl_exit_on_time =
+                (u8 *)get_afl_env(afl_environment_variables[i]);
+
           } else if (!strncmp(env, "AFL_NO_AFFINITY",
 
                               afl_environment_variable_len)) {
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 22c0cbd2..313263f9 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -179,6 +179,8 @@ void load_stats_file(afl_state_t *afl) {
 
   }
 
+  if (afl->unique_crashes) { write_crash_readme(afl); }
+
   return;
 
 }
@@ -384,7 +386,7 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
 
   /* Fields in the file:
 
-     unix_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed,
+     relative_time, afl->cycles_done, cur_path, paths_total, paths_not_fuzzed,
      favored_not_fuzzed, unique_crashes, unique_hangs, max_depth,
      execs_per_sec, edges_found */
 
@@ -544,7 +546,7 @@ void show_stats(afl_state_t *afl) {
 
   if (unlikely(afl->afl_env.afl_statsd)) {
 
-    if (unlikely(afl->force_ui_update && cur_ms - afl->statsd_last_send_ms >
+    if (unlikely(afl->force_ui_update || cur_ms - afl->statsd_last_send_ms >
                                              STATSD_UPDATE_SEC * 1000)) {
 
       /* reset counter, even if send failed. */
@@ -574,6 +576,16 @@ void show_stats(afl_state_t *afl) {
 
   }
 
+  /* AFL_EXIT_ON_TIME. */
+
+  if (unlikely(afl->last_path_time && !afl->non_instrumented_mode &&
+               afl->afl_env.afl_exit_on_time &&
+               (cur_ms - afl->last_path_time) > afl->exit_on_time)) {
+
+    afl->stop_soon = 2;
+
+  }
+
   if (unlikely(afl->total_crashes && afl->afl_env.afl_bench_until_crash)) {
 
     afl->stop_soon = 2;
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 3606533d..8de3ed6b 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -204,6 +204,7 @@ static void usage(u8 *argv0, int more_help) {
       "AFL_DISABLE_TRIM: disable the trimming of test cases\n"
       "AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
       "AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
+      "AFL_EXIT_ON_TIME: exit when no new paths are found within the specified time period\n"
       "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n"
       "AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
       "AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
@@ -1246,6 +1247,13 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+  if (afl->afl_env.afl_exit_on_time) {
+
+    u64 exit_on_time = atoi(afl->afl_env.afl_exit_on_time);
+    afl->exit_on_time = (u64)exit_on_time * 1000;
+
+  }
+
   if (afl->afl_env.afl_max_det_extras) {
 
     s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@@ -1358,6 +1366,7 @@ int main(int argc, char **argv_orig, char **envp) {
 
       afl_preload = getenv("AFL_PRELOAD");
       u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+      OKF("Injecting %s ...", frida_binary);
       if (afl_preload) {
 
         frida_afl_preload = alloc_printf("%s:%s", afl_preload, frida_binary);
@@ -1383,6 +1392,7 @@ int main(int argc, char **argv_orig, char **envp) {
   } else if (afl->fsrv.frida_mode) {
 
     u8 *frida_binary = find_afl_binary(argv[0], "afl-frida-trace.so");
+    OKF("Injecting %s ...", frida_binary);
     setenv("LD_PRELOAD", frida_binary, 1);
     setenv("DYLD_INSERT_LIBRARIES", frida_binary, 1);
     ck_free(frida_binary);
@@ -1697,13 +1707,14 @@ int main(int argc, char **argv_orig, char **envp) {
     // TODO: this is semi-nice
     afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits;
     afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
+    afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
     afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
     afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
 
     if ((map_size <= DEFAULT_SHMEM_SIZE ||
          afl->cmplog_fsrv.map_size < map_size) &&
         !afl->non_instrumented_mode && !afl->fsrv.qemu_mode &&
-        !afl->unicorn_mode) {
+        !afl->fsrv.frida_mode && !afl->unicorn_mode) {
 
       afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);
       char vbuf[16];
@@ -2209,6 +2220,31 @@ stop_fuzzing:
   }
 
   afl_fsrv_deinit(&afl->fsrv);
+
+  /* remove tmpfile */
+  if (afl->tmp_dir != NULL && !afl->in_place_resume) {
+
+    char tmpfile[PATH_MAX];
+
+    if (afl->file_extension) {
+
+      snprintf(tmpfile, PATH_MAX, "%s/.cur_input.%s", afl->tmp_dir,
+               afl->file_extension);
+
+    } else {
+
+      snprintf(tmpfile, PATH_MAX, "%s/.cur_input", afl->tmp_dir);
+
+    }
+
+    if (unlink(tmpfile) != 0) {
+
+      FATAL("Could not unlink current input file: %s.", tmpfile);
+
+    }
+
+  }
+
   if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
   ck_free(afl->fsrv.target_path);
   ck_free(afl->fsrv.out_file);
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index d0113af9..1ce97649 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -298,13 +298,12 @@ int main(int argc, char **argv) {
 
     SAYF(
         "\n"
-        "This is a helper application for afl-clang-lto. It is a wrapper "
-        "around GNU "
-        "llvm's 'lld',\n"
-        "executed by the toolchain whenever using "
-        "afl-clang-lto/afl-clang-lto++.\n"
+        "This is a helper application for afl-clang-lto.\n"
+        "It is a wrapper around llvm's 'lld' in case afl-clang-lto cannot be "
+        "used.\n"
+        "Note that the target still has to be compiled with -flto=full!\n"
         "You probably don't want to run this program directly but rather pass "
-        "it as LD parameter to configure scripts\n\n"
+        "it as LD\nparameter to e.g. configure scripts.\n\n"
 
         "Environment variables:\n"
         "  AFL_LD_PASSTHROUGH   do not link+optimize == no instrumentation\n"