about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xafl-cmin1
-rw-r--r--docs/Changelog.md2
-rw-r--r--docs/env_variables.md4
-rw-r--r--src/afl-forkserver.c45
-rw-r--r--src/afl-fuzz.c30
-rw-r--r--src/afl-showmap.c37
-rw-r--r--src/afl-tmin.c29
7 files changed, 104 insertions, 44 deletions
diff --git a/afl-cmin b/afl-cmin
index eef2b7ef..726e90ab 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -120,6 +120,7 @@ function usage() {
 "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
 "AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
 "AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
+"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
 "AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \
 "AFL_SKIP_BIN_CHECK: skip check for target binary\n"
    exit 1
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 03b8e036..81ac91b0 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -32,7 +32,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
     already building with all cores, the gcc plugin needs only one.
   - added dummy Makefile to instrumentation/
   - Updated utils/afl_frida to be 5% faster
-
+  - Added AFL_KILL_SIGNAL env variable for custom targets (thanks @v-p-b)
 
 ### Version ++3.00c (release)
   - llvm_mode/ and gcc_plugin/ moved to instrumentation/
diff --git a/docs/env_variables.md b/docs/env_variables.md
index e6b9381b..26128b01 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -350,6 +350,10 @@ checks or alter some of the more exotic semantics of the tool:
   - Note that `AFL_POST_LIBRARY` is deprecated, use `AFL_CUSTOM_MUTATOR_LIBRARY`
     instead (see below).
 
+  - `AFL_KILL_SIGNAL`: Set the signal ID to be delivered to child processes on timeout.
+    Unless you implement your own targets or instrumentation, you likely don't have to set it.
+    By default, on timeout and on exit, `SIGKILL` (`AFL_KILL_SIGNAL=9`) will be delivered to the child.
+
   - Setting `AFL_CUSTOM_MUTATOR_LIBRARY` to a shared library with
     afl_custom_fuzz() creates additional mutations through this library.
     If afl-fuzz is compiled with Python (which is autodetected during builing
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 70fb9572..b7aa87f8 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -84,6 +84,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
   fsrv->mem_limit = MEM_LIMIT;
   fsrv->out_file = NULL;
+  fsrv->kill_signal = SIGKILL;
 
   /* exec related stuff */
   fsrv->child_pid = -1;
@@ -95,30 +96,6 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
   fsrv->uses_asan = false;
 
   fsrv->init_child_func = fsrv_exec_child;
-  fsrv->kill_signal = SIGKILL;
-
-  char *kill_signal_env = get_afl_env("AFL_KILL_SIGNAL");
-  if (kill_signal_env) {
-
-    char *endptr;
-    u8    signal_code;
-    signal_code = (u8)strtoul(kill_signal_env, &endptr, 10);
-    /* Did we manage to parse the full string? */
-    if (*endptr != '\0' || endptr == kill_signal_env) {
-
-      FATAL("Invalid kill signal value!");
-
-    }
-
-    fsrv->kill_signal = signal_code;
-
-  } else {
-
-    /* Using hardcoded code for SIGKILL for the sake of simplicity */
-    setenv("AFL_KILL_SIGNAL", "9", 1);
-
-  }
-
   list_append(&fsrv_list, fsrv);
 
 }
@@ -139,6 +116,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->no_unlink = from->no_unlink;
   fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
   fsrv_to->crash_exitcode = from->crash_exitcode;
+  fsrv_to->kill_signal = from->kill_signal;
 
   // These are forkserver specific.
   fsrv_to->out_dir_fd = -1;
@@ -149,8 +127,6 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
   fsrv_to->init_child_func = from->init_child_func;
   // Note: do not copy ->add_extra_func
 
-  fsrv_to->kill_signal = from->kill_signal;
-
   list_append(&fsrv_list, fsrv_to);
 
 }
@@ -1162,25 +1138,18 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
 
   /* Report outcome to caller. */
 
-  /* TODO We use SIGTERM here as an indicator of Xen mode,
-     although it's not equivalent! */
-  if (fsrv->kill_signal == SIGTERM && !*stop_soon_p &&
-      fsrv->last_run_timed_out) {
+  /* Did we timeout? */
+  if (unlikely(fsrv->last_run_timed_out)) {
 
+    fsrv->last_kill_signal = fsrv->kill_signal;
     return FSRV_RUN_TMOUT;
 
   }
 
-  if (WIFSIGNALED(fsrv->child_status) && !*stop_soon_p) {
+  /* Did we crash? */
+  if (unlikely(WIFSIGNALED(fsrv->child_status) && !*stop_soon_p)) {
 
     fsrv->last_kill_signal = WTERMSIG(fsrv->child_status);
-
-    if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) {
-
-      return FSRV_RUN_TMOUT;
-
-    }
-
     return FSRV_RUN_CRASH;
 
   }
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index 00625f2e..5c363c63 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -194,10 +194,11 @@ static void usage(u8 *argv0, int more_help) {
       "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"
-      "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
       "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
+      "AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
       "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
       "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
+      "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
       "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
       "              the target was compiled for\n"
       "AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
@@ -986,6 +987,33 @@ int main(int argc, char **argv_orig, char **envp) {
 
   #endif
 
+  afl->fsrv.kill_signal = SIGKILL;
+  if (afl->afl_env.afl_kill_signal) {
+
+    char *endptr;
+    u8    signal_code;
+    signal_code = (u8)strtoul(afl->afl_env.afl_kill_signal, &endptr, 10);
+    /* Did we manage to parse the full string? */
+    if (*endptr != '\0' || endptr == (char *)afl->afl_env.afl_kill_signal) {
+
+      FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
+            afl->afl_env.afl_kill_signal);
+
+    }
+
+    afl->fsrv.kill_signal = signal_code;
+
+  } else {
+
+    char *sigstr = alloc_printf("%d", (int)SIGKILL);
+    if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
+
+    /* Set the env for signal handler */
+    setenv("AFL_KILL_SIGNAL", sigstr, 1);
+    free(sigstr);
+
+  }
+
   setup_signal_handlers();
   check_asan_opts(afl);
 
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index d50601fc..2c9c38ed 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -693,12 +693,13 @@ static void usage(u8 *argv0) {
       "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as "
       "crash\n"
       "AFL_DEBUG: enable extra developer output\n"
-      "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
-      "size\n"
-      "              the target was compiled for\n"
-      "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
       "startup (in milliseconds)\n"
+      "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, "
+      "etc. (default: SIGKILL)\n"
+      "AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
+      "size the target was compiled for\n"
+      "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
       "AFL_QUIET: do not print extra informational output\n",
       argv0, MEM_LIMIT, doc_path);
 
@@ -1115,6 +1116,34 @@ int main(int argc, char **argv_orig, char **envp) {
 
     }
 
+    fsrv->kill_signal = SIGKILL;
+    char *afl_kill_signal_env = getenv("AFL_KILL_SIGNAL");
+    if (afl_kill_signal_env && afl_kill_signal_env[0]) {
+
+      char *endptr;
+      u8    signal_code;
+      signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10);
+      /* Did we manage to parse the full string? */
+      if (*endptr != '\0' || endptr == afl_kill_signal_env) {
+
+        FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
+              afl_kill_signal_env);
+
+      }
+
+      fsrv->kill_signal = signal_code;
+
+    } else {
+
+      char *sigstr = alloc_printf("%d", (int)SIGKILL);
+      if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
+
+      /* Set the env for signal handler */
+      setenv("AFL_KILL_SIGNAL", sigstr, 1);
+      free(sigstr);
+
+    }
+
     if (getenv("AFL_CRASH_EXITCODE")) {
 
       long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 09d97f58..342de9c8 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -855,6 +855,7 @@ static void usage(u8 *argv0) {
       "Environment variables used:\n"
       "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
       "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
+      "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
       "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
       "              the target was compiled for\n"
       "AFL_PRELOAD:  LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
@@ -1134,6 +1135,34 @@ int main(int argc, char **argv_orig, char **envp) {
 
   }
 
+  fsrv->kill_signal = SIGKILL;
+  char *afl_kill_signal_env = getenv("AFL_KILL_SIGNAL");
+  if (afl_kill_signal_env && afl_kill_signal_env[0]) {
+
+    char *endptr;
+    u8    signal_code;
+    signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10);
+    /* Did we manage to parse the full string? */
+    if (*endptr != '\0' || endptr == afl_kill_signal_env) {
+
+      FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
+            afl_kill_signal_env);
+
+    }
+
+    fsrv->kill_signal = signal_code;
+
+  } else {
+
+    char *sigstr = alloc_printf("%d", (int)SIGKILL);
+    if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
+
+    /* Set the env for signal handler */
+    setenv("AFL_KILL_SIGNAL", sigstr, 1);
+    free(sigstr);
+
+  }
+
   if (getenv("AFL_CRASH_EXITCODE")) {
 
     long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);