aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2019-08-19 12:54:55 +0200
committervan Hauser <vh@thc.org>2019-08-19 12:54:55 +0200
commitd3d0682310b840b027083133837bcd9be0638281 (patch)
treef2ae082998937985ec14a3df10c0d7a94d9369ec
parent7cb0658b0091ecae9458c250505a05d1402a4fc8 (diff)
downloadafl++-d3d0682310b840b027083133837bcd9be0638281.tar.gz
seperated the forkserver from afl-fuzz and afl-tmin
-rw-r--r--Makefile23
-rw-r--r--TODO23
-rw-r--r--afl-analyze.c2
-rw-r--r--afl-common.c2
-rw-r--r--afl-forkserver.c401
-rw-r--r--afl-forkserver.h25
-rw-r--r--afl-fuzz.c344
-rw-r--r--afl-sharedmem.c (renamed from sharedmem.c)2
-rw-r--r--afl-sharedmem.h (renamed from sharedmem.h)5
-rw-r--r--afl-showmap.c2
-rw-r--r--afl-tmin.c124
-rw-r--r--docs/ChangeLog5
12 files changed, 553 insertions, 405 deletions
diff --git a/Makefile b/Makefile
index e6e3af85..3d5059f7 100644
--- a/Makefile
+++ b/Makefile
@@ -134,20 +134,23 @@ afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86
afl-common.o : afl-common.c
$(CC) $(CFLAGS) -c afl-common.c
-sharedmem.o : sharedmem.c
- $(CC) $(CFLAGS) -c sharedmem.c
+afl-forkserver.o : afl-forkserver.c
+ $(CC) $(CFLAGS) -c afl-forkserver.c
-afl-fuzz: afl-fuzz.c afl-common.o sharedmem.o $(COMM_HDR) | test_x86
- $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS) $(PYFLAGS)
+afl-sharedmem.o : afl-sharedmem.c
+ $(CC) $(CFLAGS) -c afl-sharedmem.c
-afl-showmap: afl-showmap.c afl-common.o sharedmem.o $(COMM_HDR) | test_x86
- $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS)
+afl-fuzz: afl-fuzz.c afl-common.o afl-sharedmem.o afl-forkserver.o $(COMM_HDR) | test_x86
+ $(CC) $(CFLAGS) $@.c afl-common.o afl-sharedmem.o afl-forkserver.o -o $@ $(LDFLAGS) $(PYFLAGS)
-afl-tmin: afl-tmin.c afl-common.o sharedmem.o $(COMM_HDR) | test_x86
- $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS)
+afl-showmap: afl-showmap.c afl-common.o afl-sharedmem.o $(COMM_HDR) | test_x86
+ $(CC) $(CFLAGS) $@.c afl-common.o afl-sharedmem.o -o $@ $(LDFLAGS)
-afl-analyze: afl-analyze.c afl-common.o sharedmem.o $(COMM_HDR) | test_x86
- $(CC) $(CFLAGS) $@.c afl-common.o sharedmem.o -o $@ $(LDFLAGS)
+afl-tmin: afl-tmin.c afl-common.o afl-sharedmem.o afl-forkserver.o $(COMM_HDR) | test_x86
+ $(CC) $(CFLAGS) $@.c afl-common.o afl-sharedmem.o afl-forkserver.o -o $@ $(LDFLAGS)
+
+afl-analyze: afl-analyze.c afl-common.o afl-sharedmem.o $(COMM_HDR) | test_x86
+ $(CC) $(CFLAGS) $@.c afl-common.o afl-sharedmem.o -o $@ $(LDFLAGS)
afl-gotcpu: afl-gotcpu.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS)
diff --git a/TODO b/TODO
index 42987cb9..cc075abd 100644
--- a/TODO
+++ b/TODO
@@ -1,12 +1,24 @@
Roadmap 2.53d:
==============
- - indent all the code: .clang-format
- - update docs/sister_projects.txt
+all:
+ - indent all the code: .clang-format?
+ (vh: tried, the variable definion look very ugly then, what to do?)
afl-fuzz:
- - put mutator, scheduler, forkserver and input channels in individual files
- - reuse forkserver for showmap, afl-cmin, etc.
+ - modularize: forkserver is in a module
+ others:
+ mutator - is deeply integrated and would loose performance if split
+ scheduler - is within this and as the values it operates on are afl
+ specific it does not make sense to seperate this
+ input - if we get different input vectors then this would make sense,
+ e.g. network (which we have seen is super non-performant and using
+ desock is much faster)
+ so for the moment we are done? (vh)
+
+docs/:
+ - update docs/sister_projects.txt
+ - doc + example for AFL_CUSTOM_MUTATOR_LIBRARY
gcc_plugin:
- needs to be rewritten
@@ -17,8 +29,9 @@ gcc_plugin:
- neverZero
qemu_mode:
+ - update to 4.x
- deferred mode with AFL_DEFERRED_QEMU=0xaddress
- @andrea - dont we have that already with AFL_ENTRYPOINT?
+ (vh: @andrea - dont we have that already with AFL_ENTRYPOINT?)
unit testing / or large testcase campaign
diff --git a/afl-analyze.c b/afl-analyze.c
index af93150e..18b7456d 100644
--- a/afl-analyze.c
+++ b/afl-analyze.c
@@ -26,7 +26,7 @@
#include "debug.h"
#include "alloc-inl.h"
#include "hash.h"
-#include "sharedmem.h"
+#include "afl-sharedmem.h"
#include "afl-common.h"
#include <stdio.h>
diff --git a/afl-common.c b/afl-common.c
index 5e2d0628..f3bbdfb4 100644
--- a/afl-common.c
+++ b/afl-common.c
@@ -15,6 +15,8 @@
#ifndef __glibc__
#include <unistd.h>
#endif
+
+
void detect_file_args(char** argv, u8* prog_in) {
u32 i = 0;
diff --git a/afl-forkserver.c b/afl-forkserver.c
new file mode 100644
index 00000000..226175e1
--- /dev/null
+++ b/afl-forkserver.c
@@ -0,0 +1,401 @@
+#include "config.h"
+#include "types.h"
+#include "debug.h"
+#include "afl-forkserver.h"
+
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+
+/* a program that includes afl-forkserver needs to define these */
+extern u8 uses_asan;
+extern u8 *trace_bits;
+extern s32 forksrv_pid, child_pid, fsrv_ctl_fd, fsrv_st_fd;
+extern s32 out_fd, out_dir_fd, dev_urandom_fd, dev_null_fd; /* initialize these with -1 */
+extern u32 exec_tmout;
+extern u64 mem_limit;
+extern u8 *out_file, *target_path, *doc_path;
+extern FILE *plot_file;
+
+/* we need this internally but can be defined and read extern in the main source */
+u8 child_timed_out;
+
+
+/* Describe integer as memory size. */
+
+u8* forkserver_DMS(u64 val) {
+
+ static u8 tmp[12][16];
+ static u8 cur;
+
+#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) do { \
+ if (val < (_divisor) * (_limit_mult)) { \
+ sprintf(tmp[cur], _fmt, ((_cast)val) / (_divisor)); \
+ return tmp[cur]; \
+ } \
+ } while (0)
+
+
+ cur = (cur + 1) % 12;
+
+ /* 0-9999 */
+ CHK_FORMAT(1, 10000, "%llu B", u64);
+
+ /* 10.0k - 99.9k */
+ CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
+
+ /* 100k - 999k */
+ CHK_FORMAT(1024, 1000, "%llu kB", u64);
+
+ /* 1.00M - 9.99M */
+ CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
+
+ /* 10.0M - 99.9M */
+ CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
+
+ /* 100M - 999M */
+ CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
+
+ /* 1.00G - 9.99G */
+ CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
+
+ /* 10.0G - 99.9G */
+ CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
+
+ /* 100G - 999G */
+ CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
+
+ /* 1.00T - 9.99G */
+ CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
+
+ /* 10.0T - 99.9T */
+ CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
+
+#undef CHK_FORMAT
+
+ /* 100T+ */
+ strcpy(tmp[cur], "infty");
+ return tmp[cur];
+
+}
+
+
+
+/* the timeout handler */
+
+void handle_timeout(int sig) {
+ if (child_pid > 0) {
+ child_timed_out = 1;
+ kill(child_pid, SIGKILL);
+ } else if (child_pid == -1 && forksrv_pid > 0) {
+ child_timed_out = 1;
+ kill(forksrv_pid, SIGKILL);
+ }
+}
+
+
+/* Spin up fork server (instrumented mode only). The idea is explained here:
+
+ http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
+
+ In essence, the instrumentation allows us to skip execve(), and just keep
+ cloning a stopped child. So, we just execute once, and then send commands
+ through a pipe. The other part of this logic is in afl-as.h / llvm_mode */
+
+void init_forkserver(char **argv) {
+
+ static struct itimerval it;
+ int st_pipe[2], ctl_pipe[2];
+ int status;
+ s32 rlen;
+
+ ACTF("Spinning up the fork server...");
+
+ if (pipe(st_pipe) || pipe(ctl_pipe))
+ PFATAL("pipe() failed");
+
+ child_timed_out = 0;
+ forksrv_pid = fork();
+
+ if (forksrv_pid < 0)
+ PFATAL("fork() failed");
+
+ if (!forksrv_pid) {
+
+ /* CHILD PROCESS */
+
+ struct rlimit r;
+
+ /* Umpf. On OpenBSD, the default fd limit for root users is set to
+ soft 128. Let's try to fix that... */
+
+ if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) {
+ r.rlim_cur = FORKSRV_FD + 2;
+ setrlimit(RLIMIT_NOFILE, &r); /* Ignore errors */
+ }
+
+ if (mem_limit) {
+ r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
+
+#ifdef RLIMIT_AS
+ setrlimit(RLIMIT_AS, &r); /* Ignore errors */
+#else
+ /* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but
+ according to reliable sources, RLIMIT_DATA covers anonymous
+ maps - so we should be getting good protection against OOM bugs. */
+
+ setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
+#endif /* ^RLIMIT_AS */
+ }
+
+ /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered
+ before the dump is complete. */
+
+// r.rlim_max = r.rlim_cur = 0;
+// setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
+
+ /* Isolate the process and configure standard descriptors. If out_file is
+ specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */
+
+ setsid();
+
+ if (!getenv("AFL_DEBUG_CHILD_OUTPUT")) {
+ dup2(dev_null_fd, 1);
+ dup2(dev_null_fd, 2);
+ }
+
+ if (out_file) {
+ dup2(dev_null_fd, 0);
+ } else {
+ dup2(out_fd, 0);
+ close(out_fd);
+ }
+
+ /* Set up control and status pipes, close the unneeded original fds. */
+
+ if (dup2(ctl_pipe[0], FORKSRV_FD) < 0)
+ PFATAL("dup2() failed");
+ if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0)
+ PFATAL("dup2() failed");
+
+ close(ctl_pipe[0]);
+ close(ctl_pipe[1]);
+ close(st_pipe[0]);
+ close(st_pipe[1]);
+
+ close(out_dir_fd);
+ close(dev_null_fd);
+ close(dev_urandom_fd);
+ close(plot_file == NULL ? -1 : fileno(plot_file));
+
+ /* This should improve performance a bit, since it stops the linker from
+ doing extra work post-fork(). */
+
+ if (!getenv("LD_BIND_LAZY"))
+ setenv("LD_BIND_NOW", "1", 0);
+
+ /* Set sane defaults for ASAN if nothing else specified. */
+
+ setenv("ASAN_OPTIONS",
+ "abort_on_error=1:"
+ "detect_leaks=0:"
+ "symbolize=0:"
+ "allocator_may_return_null=1",
+ 0);
+
+ /* MSAN is tricky, because it doesn't support abort_on_error=1 at this
+ point. So, we do this in a very hacky way. */
+
+ setenv("MSAN_OPTIONS",
+ "exit_code=" STRINGIFY(MSAN_ERROR) ":"
+ "symbolize=0:"
+ "abort_on_error=1:"
+ "allocator_may_return_null=1:"
+ "msan_track_origins=0",
+ 0);
+
+ execv(target_path, argv);
+
+ /* Use a distinctive bitmap signature to tell the parent about execv()
+ falling through. */
+
+ *(u32 *)trace_bits = EXEC_FAIL_SIG;
+ exit(0);
+ }
+
+ /* PARENT PROCESS */
+
+ /* Close the unneeded endpoints. */
+
+ close(ctl_pipe[0]);
+ close(st_pipe[1]);
+
+ fsrv_ctl_fd = ctl_pipe[1];
+ fsrv_st_fd = st_pipe[0];
+
+ /* Wait for the fork server to come up, but don't wait too long. */
+
+ if (exec_tmout) {
+ it.it_value.tv_sec = ((exec_tmout * FORK_WAIT_MULT) / 1000);
+ it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
+ }
+
+ setitimer(ITIMER_REAL, &it, NULL);
+
+ rlen = read(fsrv_st_fd, &status, 4);
+
+ it.it_value.tv_sec = 0;
+ it.it_value.tv_usec = 0;
+
+ setitimer(ITIMER_REAL, &it, NULL);
+
+ /* If we have a four-byte "hello" message from the server, we're all set.
+ Otherwise, try to figure out what went wrong. */
+
+ if (rlen == 4) {
+ OKF("All right - fork server is up.");
+ return;
+ }
+
+ if (child_timed_out)
+ FATAL("Timeout while initializing fork server (adjusting -t may help)");
+
+ if (waitpid(forksrv_pid, &status, 0) <= 0)
+ PFATAL("waitpid() failed");
+
+ if (WIFSIGNALED(status)) {
+
+ if (mem_limit && mem_limit < 500 && uses_asan) {
+
+ SAYF("\n" cLRD "[-] " cRST "Whoops, the target binary crashed suddenly, "
+ "before receiving any input\n"
+ " from the fuzzer! Since it seems to be built with ASAN and you "
+ "have a\n"
+ " restrictive memory limit configured, this is expected; please "
+ "read\n"
+ " %s/notes_for_asan.txt for help.\n",
+ doc_path);
+
+ } else if (!mem_limit) {
+
+ 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 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
+
+ " - Less likely, there is a horrible bug in the fuzzer. If other "
+ "options\n"
+ " fail, poke <afl-users@googlegroups.com> for troubleshooting "
+ "tips.\n");
+
+ } else {
+
+ 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 current memory limit (%s) is too restrictive, causing "
+ "the\n"
+ " target to hit an OOM condition in the dynamic linker. Try "
+ "bumping up\n"
+ " the limit with the -m setting in the command line. A simple "
+ "way confirm\n"
+ " this diagnosis would be:\n\n"
+
+ MSG_ULIMIT_USAGE " /path/to/fuzzed_app )\n\n"
+
+ " Tip: you can use http://jwilk.net/software/recidivm to "
+ "quickly\n"
+ " 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
+
+ " - Less likely, there is a horrible bug in the fuzzer. If other "
+ "options\n"
+ " fail, poke <afl-users@googlegroups.com> for troubleshooting "
+ "tips.\n",
+ forkserver_DMS(mem_limit << 20), mem_limit - 1);
+ }
+
+ FATAL("Fork server crashed with signal %d", WTERMSIG(status));
+ }
+
+ if (*(u32 *)trace_bits == EXEC_FAIL_SIG)
+ FATAL("Unable to execute target application ('%s')", argv[0]);
+
+ if (mem_limit && mem_limit < 500 && uses_asan) {
+
+ SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated "
+ "before we could complete a\n"
+ " handshake with the injected code. Since it seems to be built "
+ "with ASAN and\n"
+ " you have a restrictive memory limit configured, this is "
+ "expected; please\n"
+ " read %s/notes_for_asan.txt for help.\n",
+ doc_path);
+
+ } else if (!mem_limit) {
+
+ SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated "
+ "before we could complete a\n"
+ " handshake with the injected code. Perhaps there is a horrible "
+ "bug in the\n"
+ " fuzzer. Poke <afl-users@googlegroups.com> for troubleshooting "
+ "tips.\n");
+
+ } else {
+
+ SAYF(
+ "\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"
+
+ "%s"
+ " - The current memory limit (%s) is too restrictive, causing an "
+ "OOM\n"
+ " fault in the dynamic linker. This can be fixed with the -m "
+ "option. A\n"
+ " simple way to confirm the diagnosis may be:\n\n"
+
+ MSG_ULIMIT_USAGE " /path/to/fuzzed_app )\n\n"
+
+ " Tip: you can use http://jwilk.net/software/recidivm to quickly\n"
+ " estimate the required amount of virtual memory for the "
+ "binary.\n\n"
+
+ " - Less likely, there is a horrible bug in the fuzzer. If other "
+ "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"
+ " reached before the program terminates.\n\n"
+ : "",
+ forkserver_DMS(mem_limit << 20), mem_limit - 1);
+ }
+
+ FATAL("Fork server handshake failed");
+}
+
diff --git a/afl-forkserver.h b/afl-forkserver.h
new file mode 100644
index 00000000..fa40d9c6
--- /dev/null
+++ b/afl-forkserver.h
@@ -0,0 +1,25 @@
+#ifndef __AFL_FORKSERVER_H
+#define __AFL_FORKSERVER_H
+
+void handle_timeout(int sig);
+void init_forkserver(char **argv);
+
+#ifdef __APPLE__
+#define MSG_FORK_ON_APPLE \
+ " - On MacOS X, the semantics of fork() syscalls are non-standard and " \
+ "may\n" \
+ " break afl-fuzz performance optimizations when running " \
+ "platform-specific\n" \
+ " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n"
+#else
+#define MSG_FORK_ON_APPLE ""
+#endif
+
+#ifdef RLIMIT_AS
+ #define MSG_ULIMIT_USAGE " ( ulimit -Sv $[%llu << 10];"
+#else
+ #define MSG_ULIMIT_USAGE " ( ulimit -Sd $[%llu << 10];"
+#endif /* ^RLIMIT_AS */
+
+
+#endif
diff --git a/afl-fuzz.c b/afl-fuzz.c
index 2accde86..ec54cc85 100644
--- a/afl-fuzz.c
+++ b/afl-fuzz.c
@@ -33,7 +33,8 @@
#include "debug.h"
#include "alloc-inl.h"
#include "hash.h"
-#include "sharedmem.h"
+#include "afl-sharedmem.h"
+#include "afl-forkserver.h"
#include "afl-common.h"
#include <stdio.h>
@@ -144,7 +145,6 @@ double period_pilot_tmp = 5000.0;
int key_lv = 0;
EXP_ST u8 *in_dir, /* Input directory with test cases */
- *out_file, /* File to fuzz, if any */
*out_dir, /* Working & output directory */
*tmp_dir , /* Temporary directory for input */
*sync_dir, /* Synchronization directory */
@@ -152,15 +152,16 @@ EXP_ST u8 *in_dir, /* Input directory with test cases */
*power_name, /* Power schedule name */
*use_banner, /* Display banner */
*in_bitmap, /* Input bitmap */
- *doc_path, /* Path to documentation dir */
- *target_path, /* Path to target binary */
*file_extension, /* File extension */
*orig_cmdline; /* Original command line */
+ u8 *doc_path, /* Path to documentation dir */
+ *target_path, /* Path to target binary */
+ *out_file; /* File to fuzz, if any */
-EXP_ST u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */
+ u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */
static u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */
-EXP_ST u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */
+ u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */
EXP_ST u8 cal_cycles = CAL_CYCLES; /* Calibration cycles defaults */
EXP_ST u8 cal_cycles_long = CAL_CYCLES_LONG;
@@ -200,7 +201,6 @@ EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */
timeout_given, /* Specific timeout given? */
not_on_tty, /* stdout is not a tty */
term_too_small, /* terminal dimensions too small */
- uses_asan, /* Target uses ASAN? */
no_forkserver, /* Disable forkserver? */
crash_mode, /* Crash mode! Yeah! */
in_place_resume, /* Attempt in-place resume? */
@@ -217,14 +217,15 @@ EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */
deferred_mode, /* Deferred forkserver mode? */
fixed_seed, /* do not reseed */
fast_cal; /* Try to calibrate faster? */
+ u8 uses_asan; /* Target uses ASAN? */
-static s32 out_fd, /* Persistent fd for out_file */
+ s32 out_fd, /* Persistent fd for out_file */
dev_urandom_fd = -1, /* Persistent fd for /dev/urandom */
dev_null_fd = -1, /* Persistent fd for /dev/null */
fsrv_ctl_fd, /* Fork server control pipe (write) */
fsrv_st_fd; /* Fork server status pipe (read) */
-static s32 forksrv_pid, /* PID of the fork server */
+ s32 forksrv_pid, /* PID of the fork server */
child_pid = -1, /* PID of the fuzzed program */
out_dir_fd = -1; /* FD of the lock file */
@@ -313,7 +314,7 @@ static s32 cpu_aff = -1; /* Selected CPU core */
#endif /* HAVE_AFFINITY */
-static FILE* plot_file; /* Gnuplot output file */
+FILE* plot_file; /* Gnuplot output file */
struct queue_entry {
@@ -2308,299 +2309,6 @@ static void destroy_extras(void) {
}
-/* Spin up fork server (instrumented mode only). The idea is explained here:
-
- http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html
-
- In essence, the instrumentation allows us to skip execve(), and just keep
- cloning a stopped child. So, we just execute once, and then send commands
- through a pipe. The other part of this logic is in afl-as.h. */
-
-EXP_ST void init_forkserver(char** argv) {
-
- static struct itimerval it;
- int st_pipe[2], ctl_pipe[2];
- int status;
- s32 rlen;
-
- ACTF("Spinning up the fork server...");
-
- if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed");
-
- forksrv_pid = fork();
-
- if (forksrv_pid < 0) PFATAL("fork() failed");
-
- if (!forksrv_pid) {
-
- /* CHILD PROCESS */
-
- struct rlimit r;
-
- /* Umpf. On OpenBSD, the default fd limit for root users is set to
- soft 128. Let's try to fix that... */
-
- if (!getrlimit(RLIMIT_NOFILE, &r) && r.rlim_cur < FORKSRV_FD + 2) {
-
- r.rlim_cur = FORKSRV_FD + 2;
- setrlimit(RLIMIT_NOFILE, &r); /* Ignore errors */
-
- }
-
- if (mem_limit) {
-
- r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
-
-#ifdef RLIMIT_AS
-
- setrlimit(RLIMIT_AS, &r); /* Ignore errors */
-
-#else
-
- /* This takes care of OpenBSD, which doesn't have RLIMIT_AS, but
- according to reliable sources, RLIMIT_DATA covers anonymous
- maps - so we should be getting good protection against OOM bugs. */
-
- setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
-
-#endif /* ^RLIMIT_AS */
-
-
- }
-
- /* Dumping cores is slow and can lead to anomalies if SIGKILL is delivered
- before the dump is complete. */
-
- r.rlim_max = r.rlim_cur = 0;
-
- setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
-
- /* Isolate the process and configure standard descriptors. If out_file is
- specified, stdin is /dev/null; otherwise, out_fd is cloned instead. */
-
- setsid();
-
- if (!getenv("AFL_DEBUG_CHILD_OUTPUT")) {
- dup2(dev_null_fd, 1);
- dup2(dev_null_fd, 2);
- }
-
- if (out_file) {
-
- dup2(dev_null_fd, 0);
-
- } else {
-
- dup2(out_fd, 0);
- close(out_fd);
-
- }
-
- /* Set up control and status pipes, close the unneeded original fds. */
-
- if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed");
- if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed");
-
- close(ctl_pipe[0]);
- close(ctl_pipe[1]);
- close(st_pipe[0]);
- close(st_pipe[1]);
-
- close(out_dir_fd);
- close(dev_null_fd);
- close(dev_urandom_fd);
- close(fileno(plot_file));
-
- /* This should improve performance a bit, since it stops the linker from
- doing extra work post-fork(). */
-
- if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0);
-
- /* Set sane defaults for ASAN if nothing else specified. */
-
- setenv("ASAN_OPTIONS", "abort_on_error=1:"
- "detect_leaks=0:"
- "symbolize=0:"
- "allocator_may_return_null=1", 0);
-
- /* MSAN is tricky, because it doesn't support abort_on_error=1 at this
- point. So, we do this in a very hacky way. */
-
- setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "symbolize=0:"
- "abort_on_error=1:"
- "allocator_may_return_null=1:"
- "msan_track_origins=0", 0);
-
- execv(target_path, argv);
-
- /* Use a distinctive bitmap signature to tell the parent about execv()
- falling through. */
-
- *(u32*)trace_bits = EXEC_FAIL_SIG;
- exit(0);
-
- }
-
- /* PARENT PROCESS */
-
- /* Close the unneeded endpoints. */
-
- close(ctl_pipe[0]);
- close(st_pipe[1]);
-
- fsrv_ctl_fd = ctl_pipe[1];
- fsrv_st_fd = st_pipe[0];
-
- /* Wait for the fork server to come up, but don't wait too long. */
-
- it.it_value.tv_sec = ((exec_tmout * FORK_WAIT_MULT) / 1000);
- it.it_value.tv_usec = ((exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
-
- setitimer(ITIMER_REAL, &it, NULL);
-
- rlen = read(fsrv_st_fd, &status, 4);
-
- it.it_value.tv_sec = 0;
- it.it_value.tv_usec = 0;
-
- setitimer(ITIMER_REAL, &it, NULL);
-
- /* If we have a four-byte "hello" message from the server, we're all set.
- Otherwise, try to figure out what went wrong. */
-
- if (rlen == 4) {
- OKF("All right - fork server is up.");
- return;
- }
-
- if (child_timed_out)
- FATAL("Timeout while initializing fork server (adjusting -t may help)");
-
- if (waitpid(forksrv_pid, &status, 0) <= 0)
- PFATAL("waitpid() failed");
-
- if (WIFSIGNALED(status)) {
-
- if (mem_limit && mem_limit < 500 && uses_asan) {
-
- SAYF("\n" cLRD "[-] " cRST
- "Whoops, the target binary crashed suddenly, before receiving any input\n"
- " from the fuzzer! Since it seems to be built with ASAN and you have a\n"
- " restrictive memory limit configured, this is expected; please read\n"
- " %s/notes_for_asan.txt for help.\n", doc_path);
-
- } else if (!mem_limit) {
-
-#ifdef __APPLE__
-#define MSG_FORK_ON_APPLE \
- " - On MacOS X, the semantics of fork() syscalls are non-standard and may\n" \
- " break afl-fuzz performance optimizations when running platform-specific\n" \
- " targets. To fix this, set AFL_NO_FORKSRV=1 in the environment.\n\n"
-#else
-#define MSG_FORK_ON_APPLE ""
-#endif
-
- 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 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
-
- " - Less likely, there is a horrible bug in the fuzzer. If other options\n"
- " fail, poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
-
- } else {
-
-#ifdef RLIMIT_AS
-#define MSG_ULIMIT_USAGE \
- " ( ulimit -Sv $[%llu << 10];"
-#else
-#define MSG_ULIMIT_USAGE \
- " ( ulimit -Sd $[%llu << 10];"
-#endif /* ^RLIMIT_AS */
-
- 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 current memory limit (%s) is too restrictive, causing the\n"
- " target to hit an OOM condition in the dynamic linker. Try bumping up\n"
- " the limit with the -m setting in the command line. A simple way confirm\n"
- " this diagnosis would be:\n\n"
-
- MSG_ULIMIT_USAGE " /path/to/fuzzed_app )\n\n"
-
- " Tip: you can use http://jwilk.net/software/recidivm to quickly\n"
- " 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
-
- " - Less likely, there is a horrible bug in the fuzzer. If other options\n"
- " fail, poke <afl-users@googlegroups.com> for troubleshooting tips.\n",
- DMS(mem_limit << 20), mem_limit - 1);
-
- }
-
-
- FATAL("Fork server crashed with signal %d", WTERMSIG(status));
-
- }
-
- if (*(u32*)trace_bits == EXEC_FAIL_SIG)
- FATAL("Unable to execute target application ('%s')", argv[0]);
-
- if (mem_limit && mem_limit < 500 && uses_asan) {
-
- SAYF("\n" cLRD "[-] " cRST
- "Hmm, looks like the target binary terminated before we could complete a\n"
- " handshake with the injected code. Since it seems to be built with ASAN and\n"
- " you have a restrictive memory limit configured, this is expected; please\n"
- " read %s/notes_for_asan.txt for help.\n", doc_path);
-
- } else if (!mem_limit) {
-
- SAYF("\n" cLRD "[-] " cRST
- "Hmm, looks like the target binary terminated before we could complete a\n"
- " handshake with the injected code. Perhaps there is a horrible bug in the\n"
- " fuzzer. Poke <afl-users@googlegroups.com> for troubleshooting tips.\n");
-
- } else {
-
- SAYF("\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"
-
- "%s"
- " - The current memory limit (%s) is too restrictive, causing an OOM\n"
- " fault in the dynamic linker. This can be fixed with the -m option. A\n"
- " simple way to confirm the diagnosis may be:\n\n"
-
- MSG_ULIMIT_USAGE " /path/to/fuzzed_app )\n\n"
-
- " Tip: you can use http://jwilk.net/software/recidivm to quickly\n"
- " estimate the required amount of virtual memory for the binary.\n\n"
-
- " - Less likely, there is a horrible bug in the fuzzer. If other 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"
- " reached before the program terminates.\n\n" : "",
- DMS(mem_limit << 20), mem_limit - 1);
-
- }
-
- FATAL("Fork server handshake failed");
-
-}
-
/* Execute target application, monitoring for timeouts. Return status
information. The called program will update trace_bits[]. */
@@ -5165,6 +4873,12 @@ static u32 calculate_score(struct queue_entry* q) {
global average. Multiplier ranges from 0.1x to 3x. Fast inputs are
less expensive to fuzz, so we're giving them more air time. */
+ // TODO BUG FIXME: is this really a good idea?
+ // This sounds like looking for lost keys under a street light just because
+ // the light is better there.
+ // Longer execution time means longer work on the input, the deeper in
+ // coverage, the better the fuzzing, right? -mh
+
if (q->exec_us * 0.1 > avg_exec_us) perf_score = 10;
else if (q->exec_us * 0.25 > avg_exec_us) perf_score = 25;
else if (q->exec_us * 0.5 > avg_exec_us) perf_score = 50;
@@ -5188,15 +4902,11 @@ static u32 calculate_score(struct queue_entry* q) {
for a bit longer until they catch up with the rest. */
if (q->handicap >= 4) {
-
perf_score *= 4;
q->handicap -= 4;
-
} else if (q->handicap) {
-
perf_score *= 2;
--q->handicap;
-
}
/* Final adjustment based on input depth, under the assumption that fuzzing
@@ -11041,24 +10751,6 @@ static void handle_skipreq(int sig) {
}
-/* Handle timeout (SIGALRM). */
-
-static void handle_timeout(int sig) {
-
- if (child_pid > 0) {
-
- child_timed_out = 1;
- kill(child_pid, SIGKILL);
-
- } else if (child_pid == -1 && forksrv_pid > 0) {
-
- child_timed_out = 1;
- kill(forksrv_pid, SIGKILL);
-
- }
-
-}
-
/* Do a PATH search and find target binary to see that it exists and
isn't a shell script - a common and painful mistake. We also check for
@@ -12443,9 +12135,7 @@ int main(int argc, char** argv) {
#ifdef USE_PYTHON
if (init_py())
FATAL("Failed to initialize Python module");
- u8 with_python_support = 1;
#else
-
if (getenv("AFL_PYTHON_MODULE"))
FATAL("Your AFL binary was built without Python support");
#endif
diff --git a/sharedmem.c b/afl-sharedmem.c
index 3fd38444..400a0a46 100644
--- a/sharedmem.c
+++ b/afl-sharedmem.c
@@ -9,7 +9,7 @@
#include "debug.h"
#include "alloc-inl.h"
#include "hash.h"
-#include "sharedmem.h"
+#include "afl-sharedmem.h"
#include <stdio.h>
#include <unistd.h>
diff --git a/sharedmem.h b/afl-sharedmem.h
index 53a85fcb..9aa44d0e 100644
--- a/sharedmem.h
+++ b/afl-sharedmem.h
@@ -1,6 +1,7 @@
-#ifndef __SHAREDMEM_H
-#define __SHAREDMEM_H
+#ifndef __AFL_SHAREDMEM_H
+#define __AFL_SHAREDMEM_H
void setup_shm(unsigned char dumb_mode);
void remove_shm(void);
+
#endif
diff --git a/afl-showmap.c b/afl-showmap.c
index af3b36ee..96b7b5e0 100644
--- a/afl-showmap.c
+++ b/afl-showmap.c
@@ -28,7 +28,7 @@
#include "debug.h"
#include "alloc-inl.h"
#include "hash.h"
-#include "sharedmem.h"
+#include "afl-sharedmem.h"
#include "afl-common.h"
#include <stdio.h>
diff --git a/afl-tmin.c b/afl-tmin.c
index 09ce8c62..e83b217d 100644
--- a/afl-tmin.c
+++ b/afl-tmin.c
@@ -21,12 +21,14 @@
#define AFL_MAIN
+
#include "config.h"
#include "types.h"
#include "debug.h"
#include "alloc-inl.h"
#include "hash.h"
-#include "sharedmem.h"
+#include "afl-forkserver.h"
+#include "afl-sharedmem.h"
#include "afl-common.h"
#include <stdio.h>
@@ -46,22 +48,22 @@
#include <sys/types.h>
#include <sys/resource.h>
-static s32 forksrv_pid, /* PID of the fork server */
- child_pid; /* PID of the tested program */
+s32 forksrv_pid, /* PID of the fork server */
+ child_pid; /* PID of the tested program */
-static s32 fsrv_ctl_fd, /* Fork server control pipe (write) */
- fsrv_st_fd; /* Fork server status pipe (read) */
+s32 fsrv_ctl_fd, /* Fork server control pipe (write) */
+ fsrv_st_fd; /* Fork server status pipe (read) */
u8 *trace_bits; /* SHM with instrumentation bitmap */
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
-static u8 *in_file, /* Minimizer input test case */
- *out_file, /* Minimizer output file */
- *prog_in, /* Targeted program input file */
+ u8 *in_file, /* Minimizer input test case */
+ *output_file, /* Minimizer output file */
+ *out_file, /* Targeted program input file */
*target_path, /* Path to target binary */
*doc_path; /* Path to docs */
-static s32 prog_in_fd; /* Persistent fd for prog_in */
+ s32 out_fd; /* Persistent fd for out_file */
static u8* in_data; /* Input data for trimming */
@@ -70,12 +72,12 @@ static u32 in_len, /* Input data length */
total_execs, /* Total number of execs */
missed_hangs, /* Misses due to hangs */
missed_crashes, /* Misses due to crashes */
- missed_paths, /* Misses due to exec path diffs */
- exec_tmout = EXEC_TIMEOUT; /* Exec timeout (ms) */
+ missed_paths; /* Misses due to exec path diffs */
+ u32 exec_tmout = EXEC_TIMEOUT; /* Exec timeout (ms) */
-static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
+ u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
-static s32 dev_null_fd = -1; /* FD to /dev/null */
+ s32 dev_null_fd = -1; /* FD to /dev/null */
static u8 crash_mode, /* Crash-centric mode? */
exit_crash, /* Treat non-zero exit as crash? */
@@ -84,8 +86,19 @@ static u8 crash_mode, /* Crash-centric mode? */
use_stdin = 1; /* Use stdin for program input? */
static volatile u8
- stop_soon, /* Ctrl-C pressed? */
- child_timed_out; /* Child timed out? */
+ stop_soon; /* Ctrl-C pressed? */
+
+/*
+ * forkserver section
+ */
+
+/* we only need this to use afl-forkserver */
+FILE *plot_file;
+u8 uses_asan;
+s32 out_fd = -1, out_dir_fd = -1, dev_urandom_fd = -1;
+
+/* we import this as we need this information */
+extern u8 child_timed_out;
/* Classify tuple counts. This is a slow & naive version, but good enough here. */
@@ -163,7 +176,7 @@ static inline u8 anything_set(void) {
/* Get rid of temp files (atexit handler). */
static void at_exit_handler(void) {
- if (prog_in) unlink(prog_in); /* Ignore errors */
+ if (out_file) unlink(out_file); /* Ignore errors */
}
/* Read initial file. */
@@ -214,24 +227,24 @@ static s32 write_to_file(u8* path, u8* mem, u32 len) {
}
/* Write modified data to file for testing. If use_stdin is clear, the old file
- is unlinked and a new one is created. Otherwise, prog_in_fd is rewound and
+ is unlinked and a new one is created. Otherwise, out_fd is rewound and
truncated. */
static void write_to_testcase(void* mem, u32 len) {
- s32 fd = prog_in_fd;
+ s32 fd = out_fd;
if (!use_stdin) {
- unlink(prog_in); /* Ignore errors. */
+ unlink(out_file); /* Ignore errors. */
- fd = open(prog_in, O_WRONLY | O_CREAT | O_EXCL, 0600);
+ fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
- if (fd < 0) PFATAL("Unable to create '%s'", prog_in);
+ if (fd < 0) PFATAL("Unable to create '%s'", out_file);
} else lseek(fd, 0, SEEK_SET);
- ck_write(fd, mem, len, prog_in);
+ ck_write(fd, mem, len, out_file);
if (use_stdin) {
@@ -245,7 +258,7 @@ static void write_to_testcase(void* mem, u32 len) {
/* Handle timeout signal. */
-
+/*
static void handle_timeout(int sig) {
if (child_pid > 0) {
@@ -261,8 +274,10 @@ static void handle_timeout(int sig) {
}
}
+*/
/* start the app and it's forkserver */
+/*
static void init_forkserver(char **argv) {
static struct itimerval it;
int st_pipe[2], ctl_pipe[2];
@@ -280,7 +295,7 @@ static void init_forkserver(char **argv) {
struct rlimit r;
- if (dup2(use_stdin ? prog_in_fd : dev_null_fd, 0) < 0 ||
+ if (dup2(use_stdin ? out_fd : dev_null_fd, 0) < 0 ||
dup2(dev_null_fd, 1) < 0 ||
dup2(dev_null_fd, 2) < 0) {
@@ -290,7 +305,7 @@ static void init_forkserver(char **argv) {
}
close(dev_null_fd);
- close(prog_in_fd);
+ close(out_fd);
setsid();
@@ -300,20 +315,20 @@ static void init_forkserver(char **argv) {
#ifdef RLIMIT_AS
- setrlimit(RLIMIT_AS, &r); /* Ignore errors */
+ setrlimit(RLIMIT_AS, &r); // Ignore errors
#else
- setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
+ setrlimit(RLIMIT_DATA, &r); // Ignore errors
-#endif /* ^RLIMIT_AS */
+#endif // ^RLIMIT_AS
}
r.rlim_max = r.rlim_cur = 0;
- setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
+ setrlimit(RLIMIT_CORE, &r); // Ignore errors
- /* Set up control and status pipes, close the unneeded original fds. */
+ // Set up control and status pipes, close the unneeded original fds.
if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed");
if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed");
@@ -330,7 +345,7 @@ static void init_forkserver(char **argv) {
}
- /* Close the unneeded endpoints. */
+ // Close the unneeded endpoints.
close(ctl_pipe[0]);
close(st_pipe[1]);
@@ -338,7 +353,7 @@ static void init_forkserver(char **argv) {
fsrv_ctl_fd = ctl_pipe[1];
fsrv_st_fd = st_pipe[0];
- /* Configure timeout, wait for child, cancel timeout. */
+ // Configure timeout, wait for child, cancel timeout.
if (exec_tmout) {
@@ -356,8 +371,8 @@ static void init_forkserver(char **argv) {
it.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &it, NULL);
- /* If we have a four-byte "hello" message from the server, we're all set.
- Otherwise, try to figure out what went wrong. */
+ // If we have a four-byte "hello" message from the server, we're all set.
+ // Otherwise, try to figure out what went wrong.
if (rlen == 4) {
ACTF("All right - fork server is up.");
@@ -380,7 +395,7 @@ static void init_forkserver(char **argv) {
SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status));
}
-
+*/
/* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */
@@ -422,11 +437,8 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
/* Configure timeout, wait for child, cancel timeout. */
if (exec_tmout) {
-
- child_timed_out = 0;
- it.it_value.tv_sec = (exec_tmout / 1000);
- it.it_value.tv_usec = (exec_tmout % 1000) * 1000;
-
+ it.it_value.tv_sec = (exec_tmout / 1000);
+ it.it_value.tv_usec = (exec_tmout % 1000) * 1000;
}
setitimer(ITIMER_REAL, &it, NULL);
@@ -458,7 +470,7 @@ static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
if (stop_soon) {
SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST);
- close(write_to_file(out_file, in_data, in_len));
+ close(write_to_file(output_file, in_data, in_len));
exit(1);
}
@@ -787,7 +799,7 @@ static void set_up_environment(void) {
dev_null_fd = open("/dev/null", O_RDWR);
if (dev_null_fd < 0) PFATAL("Unable to open /dev/null");
- if (!prog_in) {
+ if (!out_file) {
u8* use_dir = ".";
@@ -798,15 +810,15 @@ static void set_up_environment(void) {
}
- prog_in = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid());
+ out_file = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid());
}
- unlink(prog_in);
+ unlink(out_file);
- prog_in_fd = open(prog_in, O_RDWR | O_CREAT | O_EXCL, 0600);
+ out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600);
- if (prog_in_fd < 0) PFATAL("Unable to create '%s'", prog_in);
+ if (out_fd < 0) PFATAL("Unable to create '%s'", out_file);
/* Set sane defaults... */
@@ -1067,15 +1079,15 @@ int main(int argc, char** argv) {
case 'o':
- if (out_file) FATAL("Multiple -o options not supported");
- out_file = optarg;
+ if (output_file) FATAL("Multiple -o options not supported");
+ output_file = optarg;
break;
case 'f':
- if (prog_in) FATAL("Multiple -f options not supported");
+ if (out_file) FATAL("Multiple -f options not supported");
use_stdin = 0;
- prog_in = optarg;
+ out_file = optarg;
break;
case 'e':
@@ -1181,7 +1193,7 @@ int main(int argc, char** argv) {
}
- if (optind == argc || !in_file || !out_file) usage(argv[0]);
+ if (optind == argc || !in_file || !output_file) usage(argv[0]);
setup_shm(0);
atexit(at_exit_handler);
@@ -1190,7 +1202,7 @@ int main(int argc, char** argv) {
set_up_environment();
find_binary(argv[optind]);
- detect_file_args(argv + optind, prog_in);
+ detect_file_args(argv + optind, out_file);
if (qemu_mode)
use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
@@ -1229,12 +1241,12 @@ int main(int argc, char** argv) {
minimize(use_argv);
- ACTF("Writing output to '%s'...", out_file);
+ ACTF("Writing output to '%s'...", output_file);
- unlink(prog_in);
- prog_in = NULL;
+ unlink(out_file);
+ out_file = NULL;
- close(write_to_file(out_file, in_data, in_len));
+ close(write_to_file(output_file, in_data, in_len));
OKF("We're done here. Have a nice day!\n");
diff --git a/docs/ChangeLog b/docs/ChangeLog
index dfebb68a..ed8e0022 100644
--- a/docs/ChangeLog
+++ b/docs/ChangeLog
@@ -20,12 +20,13 @@ Version ++2.53d (dev):
- llvm 9 is now supported (still needs testing)
- fix building qemu on some Ubuntus (thanks to floyd!)
- custom mutator by a loaded library is now supported (thanks to kyakdan!)
+ - more support for *BSD (thanks to devnexen!)
+ - fix building on *BSD (thanks to tobias.kortkamp for the patch)
- fix for a few features to support different map sized than 2^16
- afl-showmap: new option -r now shows the real values in the buckets (stock
afl never did), plus shows tuple content summary information now
- - fix building on *BSD (thanks to tobias.kortkamp for the patch)
+ - the forkserver is now in its own C file to be easily integratable
- small docu updates
- - ... your patch? :)
--------------------------