From fbf5e08425abcb0db2866067c4ede8134b8f9e98 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Thu, 9 Apr 2020 18:11:39 +0000 Subject: merge PR#306 from neoni (thanks), silence test when bash is not found --- src/afl-fuzz-init.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index efdde463..ce30e599 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -134,8 +134,17 @@ void bind_to_free_cpu(afl_state_t *afl) { for (i = 0; i < proccount; i++) { #if defined(__FreeBSD__) - if (procs[i].ki_oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60) - cpu_used[procs[i].ki_oncpu] = 1; + if (!strcmp(procs[i].ki_comm, "idle")) + continue; + + // fix when ki_oncpu = -1 + int oncpu; + oncpu = procs[i].ki_oncpu; + if (oncpu == -1) + oncpu = procs[i].ki_lastcpu; + + if (oncpu != -1 && oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60) + cpu_used[oncpu] = 1; #elif defined(__DragonFly__) if (procs[i].kp_lwp.kl_cpuid < sizeof(cpu_used) && procs[i].kp_lwp.kl_pctcpu > 10) -- cgit 1.4.1 From f0f83bab5299098a441af40236f3758171b69889 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 10 Apr 2020 17:47:22 +0200 Subject: resize fix + code format --- include/common.h | 4 +++- include/forkserver.h | 3 ++- src/afl-common.c | 8 +++++--- src/afl-forkserver.c | 5 +++-- src/afl-fuzz-cmplog.c | 6 ++++-- src/afl-fuzz-init.c | 6 ++---- src/afl-fuzz-run.c | 6 ++++-- src/afl-fuzz-stats.c | 14 +++++++------- src/afl-showmap.c | 2 +- src/afl-tmin.c | 2 +- 10 files changed, 32 insertions(+), 24 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/include/common.h b/include/common.h index c9436e81..8dd66355 100644 --- a/include/common.h +++ b/include/common.h @@ -99,9 +99,11 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); /* Wrapper for select() and read(), reading exactly len bytes. Returns the time passed to read. + stop_soon should point to a variable indicating ctrl+c was pressed. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms); +u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, + volatile u8 *stop_soon_p); #endif diff --git a/include/forkserver.h b/include/forkserver.h index 5d1bd2cf..4110df7d 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -67,7 +67,8 @@ typedef struct afl_forkserver { } afl_forkserver_t; void afl_fsrv_init(afl_forkserver_t *fsrv); -void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv); +void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, + volatile u8 *stop_soon_p); void afl_fsrv_deinit(afl_forkserver_t *fsrv); void afl_fsrv_killall(); diff --git a/src/afl-common.c b/src/afl-common.c index 7eee5265..12b0355e 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -40,6 +40,7 @@ u8 be_quiet = 0; u8 *doc_path = ""; +u8 last_intr = 0; char *afl_environment_variables[] = { @@ -754,7 +755,8 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { +u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, + volatile u8 *stop_soon_p) { struct timeval timeout; fd_set readfds; @@ -779,8 +781,8 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { } else if (sret < 0) { - // perror("sret malloc"); - // TODO: catch other (errno == EINTR) than ctrl+c? + /* Retry select for all signals other than than ctrl+c */ + if (errno == EINTR && !*stop_soon_p) { continue; } return 0; } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index b3b86685..56c3c9d5 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -160,7 +160,8 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { 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 afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { +void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, + volatile u8 *stop_soon_p) { int st_pipe[2], ctl_pipe[2]; int status; @@ -317,7 +318,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { rlen = 4; u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen, - fsrv->exec_tmout * FORK_WAIT_MULT); + fsrv->exec_tmout * FORK_WAIT_MULT, stop_soon_p); if (time > fsrv->exec_tmout * FORK_WAIT_MULT) { diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 98f7db05..5ad73539 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -187,7 +187,8 @@ void init_cmplog_forkserver(afl_state_t *afl) { rlen = 4; u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT; /* Reuse readfds as exceptfds to see when the child closed the pipe */ - u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); + u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms, + &afl->stop_soon); if (!exec_ms) { @@ -416,7 +417,8 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { /* Configure timeout, as requested by user, then wait for child to terminate. */ - exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); + exec_ms = + read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout, &afl->stop_soon); if (exec_ms > timeout) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index ce30e599..6e0485e5 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -134,14 +134,12 @@ void bind_to_free_cpu(afl_state_t *afl) { for (i = 0; i < proccount; i++) { #if defined(__FreeBSD__) - if (!strcmp(procs[i].ki_comm, "idle")) - continue; + if (!strcmp(procs[i].ki_comm, "idle")) continue; // fix when ki_oncpu = -1 int oncpu; oncpu = procs[i].ki_oncpu; - if (oncpu == -1) - oncpu = procs[i].ki_lastcpu; + if (oncpu == -1) oncpu = procs[i].ki_lastcpu; if (oncpu != -1 && oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60) cpu_used[oncpu] = 1; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 47f6e9d9..9bbdd23a 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -67,7 +67,8 @@ u8 run_target(afl_state_t *afl, u32 timeout) { if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - exec_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); + exec_ms = + read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout, &afl->stop_soon); if (exec_ms > timeout) { @@ -308,7 +309,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, /* Make sure the forkserver is up before we do anything, and let's not count its spin-up time toward binary calibration. */ - if (!afl->fsrv.fsrv_pid) afl_fsrv_start(&afl->fsrv, afl->argv); + if (!afl->fsrv.fsrv_pid) + afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon); if (afl->dumb_mode != 1 && !afl->no_forkserver && !afl->cmplog_fsrv_pid && afl->shm.cmplog_mode) init_cmplog_forkserver(afl); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 850555b5..ab84bf3f 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -366,9 +366,9 @@ void show_stats(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->dumb_mode) { @@ -450,9 +450,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -481,9 +481,9 @@ void show_stats(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); @@ -557,7 +557,7 @@ void show_stats(afl_state_t *afl) { /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index e4463dc4..2fd17fb1 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -951,7 +951,7 @@ int main(int argc, char **argv_orig, char **envp) { } - afl_fsrv_start(fsrv, use_argv); + afl_fsrv_start(fsrv, use_argv, &stop_soon); while (done == 0 && (dir_ent = readdir(dir_in))) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 30e76d42..f899a6b5 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -1133,7 +1133,7 @@ int main(int argc, char **argv_orig, char **envp) { read_initial_file(); - afl_fsrv_start(fsrv, use_argv); + afl_fsrv_start(fsrv, use_argv, &stop_soon); ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : ""); -- cgit 1.4.1 From 3a509c61689112cc321c4c78f058014abff66c8a Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 10 Apr 2020 22:33:11 +0200 Subject: LTO optimization, variable map size, autodictionary (#307) * lto module clean-up * step 1/3 * step 1/3 completed * if tmp is ever made non-static * parts 2 and 3 - autodictionary is complete * variable map_size support * variable map size: changed overlooked functions * remove debug for autodict * 64 bit alignment of map size * fix review comments * force 64 bit alignment on both sides * typo --- docs/env_variables.md | 11 +- gcc_plugin/afl-gcc-rt.o.c | 4 +- include/afl-fuzz.h | 22 +- include/config.h | 14 +- include/forkserver.h | 6 + llvm_mode/GNUmakefile | 3 +- llvm_mode/README.lto.md | 41 ++-- llvm_mode/afl-clang-fast.c | 3 + llvm_mode/afl-llvm-lto-instrumentation.so.cc | 330 +++++++++++++++++++++++++-- llvm_mode/afl-llvm-rt.o.c | 170 ++++++++++++-- qemu_mode/patches/afl-qemu-cpu-inl.h | 2 +- src/afl-common.c | 1 + src/afl-forkserver.c | 96 +++++++- src/afl-fuzz-bitmap.c | 61 +++-- src/afl-fuzz-cmplog.c | 6 +- src/afl-fuzz-extras.c | 10 +- src/afl-fuzz-init.c | 4 +- src/afl-fuzz-mutators.c | 7 +- src/afl-fuzz-one.c | 16 +- src/afl-fuzz-queue.c | 19 +- src/afl-fuzz-redqueen.c | 14 +- src/afl-fuzz-run.c | 27 +-- src/afl-fuzz-state.c | 4 + src/afl-fuzz-stats.c | 11 +- src/afl-tmin.c | 4 +- 25 files changed, 726 insertions(+), 160 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/docs/env_variables.md b/docs/env_variables.md index cd002145..7890da35 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -111,10 +111,15 @@ Then there are a few specific features that are only available in llvm_mode: instrumentation which is 100% collision free (collisions are a big issue in afl and afl-like instrumentations). This is performed by using afl-clang-lto/afl-clang-lto++ instead of afl-clang-fast, but is only - built if LLVM 9 or newer is used. + built if LLVM 11 or newer is used. - None of these options are necessary to be used and are rather for manual - use (which only ever the author of this LTO implementation will use ;-) + - AFL_LLVM_LTO_AUTODICTIONARY will generate a dictionary in the target + binary based on string compare and memory compare functions. + afl-fuzz will automatically get these transmitted when starting to + fuzz. + + None of the following options are necessary to be used and are rather for + manual use (which only ever the author of this LTO implementation will use). These are used if several seperated instrumentation are performed which are then later combined. diff --git a/gcc_plugin/afl-gcc-rt.o.c b/gcc_plugin/afl-gcc-rt.o.c index 30606150..b157b50f 100644 --- a/gcc_plugin/afl-gcc-rt.o.c +++ b/gcc_plugin/afl-gcc-rt.o.c @@ -138,8 +138,8 @@ static void __afl_map_shm(void) { static void __afl_start_forkserver(void) { - static u8 tmp[4]; - s32 child_pid; + u8 tmp[4] = {0, 0, 0, 0}; + s32 child_pid; u8 child_stopped = 0; diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 56135d0e..edda81e1 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -577,7 +577,9 @@ typedef struct afl_state { u32 document_counter; #endif - /* statis file */ + void *maybe_add_auto; + + /* statistics file */ double last_bitmap_cvg, last_stability, last_eps; /* plot file saves from last run */ @@ -840,18 +842,18 @@ u32 calculate_score(afl_state_t *, struct queue_entry *); void read_bitmap(afl_state_t *, u8 *); void write_bitmap(afl_state_t *); -u32 count_bits(u8 *); -u32 count_bytes(u8 *); -u32 count_non_255_bytes(u8 *); +u32 count_bits(afl_state_t *, u8 *); +u32 count_bytes(afl_state_t *, u8 *); +u32 count_non_255_bytes(afl_state_t *, u8 *); #ifdef WORD_SIZE_64 -void simplify_trace(u64 *); -void classify_counts(u64 *); +void simplify_trace(afl_state_t *, u64 *); +void classify_counts(afl_state_t *, u64 *); #else -void simplify_trace(u32 *); -void classify_counts(u32 *); +void simplify_trace(afl_state_t *, u32 *); +void classify_counts(afl_state_t *, u32 *); #endif void init_count_class16(void); -void minimize_bits(u8 *, u8 *); +void minimize_bits(afl_state_t *, u8 *, u8 *); #ifndef SIMPLE_FILES u8 *describe_op(afl_state_t *, u8); #endif @@ -862,7 +864,7 @@ u8 has_new_bits(afl_state_t *, u8 *); void load_extras_file(afl_state_t *, u8 *, u32 *, u32 *, u32); void load_extras(afl_state_t *, u8 *); -void maybe_add_auto(afl_state_t *, u8 *, u32); +void maybe_add_auto(void *, u8 *, u32); void save_auto(afl_state_t *); void load_auto(afl_state_t *); void destroy_extras(afl_state_t *); diff --git a/include/config.h b/include/config.h index cf73772f..f0274fd3 100644 --- a/include/config.h +++ b/include/config.h @@ -201,8 +201,8 @@ (first value), and to keep in memory as candidates. The latter should be much higher than the former. */ -#define USE_AUTO_EXTRAS 50 -#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 10) +#define USE_AUTO_EXTRAS 128 +#define MAX_AUTO_EXTRAS (USE_AUTO_EXTRAS * 64) /* Scaling factor for the effector map used to skip some of the more expensive deterministic steps. The actual divisor is set to @@ -400,5 +400,15 @@ #endif #endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ +/* Extended forkserver option values */ + +#define FS_OPT_ENABLED 0x8f000001 +#define FS_OPT_MAPSIZE 0x40000000 +#define FS_OPT_SNAPSHOT 0x20000000 +#define FS_OPT_AUTODICT 0x10000000 +#define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) +#define FS_OPT_SET_MAPSIZE(x) \ + (x <= 1 || x > MAP_SIZE || x > 0x1000000 ? 0 : ((x - 1) << 1)) + #endif /* ! _HAVE_CONFIG_H */ diff --git a/include/forkserver.h b/include/forkserver.h index 4110df7d..7470dbbc 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -51,6 +51,8 @@ typedef struct afl_forkserver { fsrv_st_fd; /* Fork server status pipe (read) */ u32 exec_tmout; /* Configurable exec timeout (ms) */ + u32 map_size; /* map size used by the target */ + u32 snapshot; /* is snapshot feature used */ u64 mem_limit; /* Memory cap for child (MB) */ u8 *out_file, /* File to fuzz, if any */ @@ -64,6 +66,10 @@ typedef struct afl_forkserver { u32 prev_timed_out; /* if prev forkserver run timed out */ + u8 *function_opt; /* for autodictionary: afl ptr */ + + void (*function_ptr)(void *afl_tmp, u8 *mem, u32 len); + } afl_forkserver_t; void afl_fsrv_init(afl_forkserver_t *fsrv); diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 7432b061..b176a24f 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -273,6 +273,7 @@ endif ../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc ifeq "$(LLVM_LTO)" "1" $(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) + $(CC) $(CFLAGS) -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o endif # laf @@ -318,7 +319,7 @@ all_done: test_build install: all install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi - if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 ../afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi + if [ -f ../afl-clang-lto ]; then set -e; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 ../afl-llvm-lto-instrumentation.so ../afl-llvm-rt-lto.o ../afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index a3c7ddc3..48d0e36c 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -12,6 +12,8 @@ This version requires a current llvm 11 compiled from the github master. 3. It only works with llvm 11 (current github master state) +4. AUTODICTIONARY feature! see below + ## Introduction and problem description A big issue with how afl/afl++ works is that the basic block IDs that are @@ -33,33 +35,22 @@ and many dead ends until we got to this: * Our compiler (afl-clang-lto/afl-clang-lto++) takes care of setting the correct LTO options and runs our own afl-ld linker instead of the system linker - * Our linker collects all LTO files to link and instruments them so that + * The LLVM linker collects all LTO files to link and instruments them so that we have non-colliding edge overage * We use a new (for afl) edge coverage - which is the same as in llvm -fsanitize=coverage edge coverage mode :) - * after inserting our instrumentation in all interesting edges we link - all parts of the program together to our executable The result: - * 10-15% speed gain compared to llvm_mode + * 10-20% speed gain compared to llvm_mode * guaranteed non-colliding edge coverage :-) * The compile time especially for libraries can be longer Example build output from a libtiff build: ``` -/bin/bash ../libtool --tag=CC --mode=link afl-clang-lto -g -O2 -Wall -W -o thumbnail thumbnail.o ../libtiff/libtiff.la ../port/libport.la -llzma -ljbig -ljpeg -lz -lm libtool: link: afl-clang-lto -g -O2 -Wall -W -o thumbnail thumbnail.o ../libtiff/.libs/libtiff.a ../port/.libs/libport.a -llzma -ljbig -ljpeg -lz -lm -afl-clang-lto++2.62d by Marc "vanHauser" Heuse -afl-ld++2.62d by Marc "vanHauser" Heuse (level 0) -[+] Running ar unpacker on /prg/tests/lto/tiff-4.0.4/tools/../libtiff/.libs/libtiff.a into /tmp/.afl-3914343-1583339800.dir -[+] Running ar unpacker on /prg/tests/lto/tiff-4.0.4/tools/../port/.libs/libport.a into /tmp/.afl-3914343-1583339800.dir -[+] Running bitcode linker, creating /tmp/.afl-3914343-1583339800-1.ll -[+] Performing optimization via opt, creating /tmp/.afl-3914343-1583339800-2.bc -[+] Performing instrumentation via opt, creating /tmp/.afl-3914343-1583339800-3.bc -afl-llvm-lto++2.62d by Marc "vanHauser" Heuse -[+] Instrumented 15833 locations with no collisions (on average 1767 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode). -[+] Running real linker /bin/x86_64-linux-gnu-ld -[+] Linker was successful +afl-clang-lto++2.63d by Marc "vanHauser" Heuse in mode LTO +afl-llvm-lto++2.63d by Marc "vanHauser" Heuse +[+] Instrumented 11836 locations with no collisions (on average 1007 collisions would be in afl-gcc/afl-clang-fast) (non-hardened mode). ``` ## Building llvm 11 @@ -70,8 +61,8 @@ $ git clone https://github.com/llvm/llvm-project $ cd llvm-project $ mkdir build $ cd build -$ cmake -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;compiler-rt;libclc;libcxx;libcxxabi;libunwind;lld' -DLLVM_BINUTILS_INCDIR=/usr/include/ ../llvm/ -$ make +$ cmake -DLLVM_ENABLE_PROJECTS='clang;clang-tools-extra;compiler-rt;libclc;libcxx;libcxxabi;libunwind;lld' -DCMAKE_BUILD_TYPE=Release -DLLVM_BINUTILS_INCDIR=/usr/include/ ../llvm/ +$ make -j $(nproc) $ export PATH=`pwd`/bin:$PATH $ export LLVM_CONFIG=`pwd`/bin/llcm-config $ cd /path/to/AFLplusplus/ @@ -96,6 +87,13 @@ CC=afl-clang-lto CXX=afl-clang-lto++ ./configure make ``` +## AUTODICTIONARY feature + +Setting `AFL_LLVM_LTO_AUTODICTIONARY` will generate a dictionary in the +target binary based on string compare and memory compare functions. +afl-fuzz will automatically get these transmitted when starting to fuzz. +This improves coverage on a lot of targets. + ## Potential issues ### compiling libraries fails @@ -121,11 +119,8 @@ Please report issues at: ## Upcoming Work -1. Currently the LTO whitelist feature does not allow to not instrument main, start and init functions -2. Modify the forkserver + afl-fuzz so that only the necessary map size is - loaded and used - and communicated to afl-fuzz too. - Result: faster fork in the target and faster map analysis in afl-fuzz - => more speed :-) +1. Currently the LTO whitelist feature does not allow to not instrument main, + start and init functions ## History diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 26ee0bab..cdb22cb9 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -477,6 +477,9 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + if (instrument_mode == INSTRUMENT_LTO) + cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-lto.o", obj_path); + #ifndef __ANDROID__ switch (bit_mode) { diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 93968984..f387e79c 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -38,17 +38,24 @@ #include #include "llvm/Config/llvm-config.h" +#include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/BasicBlock.h" #include "llvm/IR/Module.h" +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/CFG.h" +#include "llvm/IR/Verifier.h" #include "llvm/Support/Debug.h" +#include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Analysis/LoopInfo.h" #include "llvm/Analysis/MemorySSAUpdater.h" -#include "llvm/IR/DebugInfo.h" -#include "llvm/IR/CFG.h" +#include "llvm/Analysis/ValueTracking.h" +#include "llvm/Pass.h" + +#include using namespace llvm; @@ -145,7 +152,7 @@ class AFLLTOPass : public ModulePass { bool runOnModule(Module &M) override; protected: - int afl_global_id = 1, debug = 0; + int afl_global_id = 1, debug = 0, autodictionary = 0; uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0, total_instr = 0; }; @@ -154,7 +161,9 @@ class AFLLTOPass : public ModulePass { bool AFLLTOPass::runOnModule(Module &M) { - LLVMContext &C = M.getContext(); + LLVMContext & C = M.getContext(); + std::vector dictionary; + std::vector calls; IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int32Ty = IntegerType::getInt32Ty(C); @@ -172,6 +181,10 @@ bool AFLLTOPass::runOnModule(Module &M) { be_quiet = 1; + if (getenv("AFL_LLVM_AUTODICTIONARY") || + getenv("AFL_LLVM_LTO_AUTODICTIONARY")) + autodictionary = 1; + /* Get globals for the SHM region and the previous location. Note that __afl_prev_loc is thread-local. */ @@ -193,6 +206,110 @@ bool AFLLTOPass::runOnModule(Module &M) { std::vector InsBlocks; + if (autodictionary) { + + for (auto &BB : F) { + + for (auto &IN : BB) { + + CallInst *callInst = nullptr; + + if ((callInst = dyn_cast(&IN))) { + + bool isStrcmp = true; + bool isMemcmp = true; + bool isStrncmp = true; + bool isStrcasecmp = true; + bool isStrncasecmp = true; + + Function *Callee = callInst->getCalledFunction(); + if (!Callee) continue; + if (callInst->getCallingConv() != llvm::CallingConv::C) continue; + StringRef FuncName = Callee->getName(); + isStrcmp &= !FuncName.compare(StringRef("strcmp")); + isMemcmp &= !FuncName.compare(StringRef("memcmp")); + isStrncmp &= !FuncName.compare(StringRef("strncmp")); + isStrcasecmp &= !FuncName.compare(StringRef("strcasecmp")); + isStrncasecmp &= !FuncName.compare(StringRef("strncasecmp")); + + if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp && + !isStrncasecmp) + continue; + + /* Verify the strcmp/memcmp/strncmp/strcasecmp/strncasecmp function + * prototype */ + FunctionType *FT = Callee->getFunctionType(); + + isStrcmp &= FT->getNumParams() == 2 && + FT->getReturnType()->isIntegerTy(32) && + FT->getParamType(0) == FT->getParamType(1) && + FT->getParamType(0) == + IntegerType::getInt8PtrTy(M.getContext()); + isStrcasecmp &= FT->getNumParams() == 2 && + FT->getReturnType()->isIntegerTy(32) && + FT->getParamType(0) == FT->getParamType(1) && + FT->getParamType(0) == + IntegerType::getInt8PtrTy(M.getContext()); + isMemcmp &= FT->getNumParams() == 3 && + FT->getReturnType()->isIntegerTy(32) && + FT->getParamType(0)->isPointerTy() && + FT->getParamType(1)->isPointerTy() && + FT->getParamType(2)->isIntegerTy(); + isStrncmp &= FT->getNumParams() == 3 && + FT->getReturnType()->isIntegerTy(32) && + FT->getParamType(0) == FT->getParamType(1) && + FT->getParamType(0) == + IntegerType::getInt8PtrTy(M.getContext()) && + FT->getParamType(2)->isIntegerTy(); + isStrncasecmp &= FT->getNumParams() == 3 && + FT->getReturnType()->isIntegerTy(32) && + FT->getParamType(0) == FT->getParamType(1) && + FT->getParamType(0) == + IntegerType::getInt8PtrTy(M.getContext()) && + FT->getParamType(2)->isIntegerTy(); + + if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp && + !isStrncasecmp) + continue; + + /* is a str{n,}{case,}cmp/memcmp, check if we have + * str{case,}cmp(x, "const") or str{case,}cmp("const", x) + * strn{case,}cmp(x, "const", ..) or strn{case,}cmp("const", x, ..) + * memcmp(x, "const", ..) or memcmp("const", x, ..) */ + Value *Str1P = callInst->getArgOperand(0), + *Str2P = callInst->getArgOperand(1); + StringRef Str1, Str2; + bool HasStr1 = getConstantStringInfo(Str1P, Str1); + bool HasStr2 = getConstantStringInfo(Str2P, Str2); + + /* handle cases of one string is const, one string is variable */ + if (!(HasStr1 ^ HasStr2)) continue; + + if (isMemcmp || isStrncmp || isStrncasecmp) { + + /* check if third operand is a constant integer + * strlen("constStr") and sizeof() are treated as constant */ + Value * op2 = callInst->getArgOperand(2); + ConstantInt *ilen = dyn_cast(op2); + if (!ilen) continue; + /* final precaution: if size of compare is larger than constant + * string skip it*/ + uint64_t literalLength = + HasStr1 ? GetStringLength(Str1P) : GetStringLength(Str2P); + if (literalLength < ilen->getZExtValue()) continue; + + } + + calls.push_back(callInst); + + } + + } + + } + + } + for (auto &BB : F) { uint32_t succ = 0; @@ -282,32 +399,201 @@ bool AFLLTOPass::runOnModule(Module &M) { } + // save highest location ID to global variable + // do this after each function to fail faster + if (afl_global_id > MAP_SIZE) { + + uint32_t pow2map = 1, map = afl_global_id; + while ((map = map >> 1)) + pow2map++; + FATAL( + "We have %u blocks to instrument but the map size is only %u! Edit " + "config.h and set MAP_SIZE_POW2 from %u to %u, then recompile " + "afl-fuzz and llvm_mode.", + afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map); + + } + } - // save highest location ID to global variable + if (calls.size()) { - if (afl_global_id > MAP_SIZE) { + for (auto &callInst : calls) { - uint32_t pow2map = 1, map = afl_global_id; - while ((map = map >> 1)) - pow2map++; - FATAL( - "We have %u blocks to instrument but the map size is only %u! Edit " - "config.h and set MAP_SIZE_POW2 from %u to %u, then recompile " - "afl-fuzz and llvm_mode.", - afl_global_id, MAP_SIZE, MAP_SIZE_POW2, pow2map); + Value *Str1P = callInst->getArgOperand(0), + *Str2P = callInst->getArgOperand(1); + StringRef Str1, Str2, ConstStr; + std::string TmpConstStr; + Value * VarStr; + bool HasStr1 = getConstantStringInfo(Str1P, Str1); + getConstantStringInfo(Str2P, Str2); + uint64_t constLen, sizedLen; + bool isMemcmp = !callInst->getCalledFunction()->getName().compare( + StringRef("memcmp")); + bool isSizedcmp = isMemcmp || + !callInst->getCalledFunction()->getName().compare( + StringRef("strncmp")) || + !callInst->getCalledFunction()->getName().compare( + StringRef("strncasecmp")); + + if (isSizedcmp) { + + Value * op2 = callInst->getArgOperand(2); + ConstantInt *ilen = dyn_cast(op2); + sizedLen = ilen->getZExtValue(); + + } else { + + sizedLen = 0; + + } + + if (HasStr1) { + + TmpConstStr = Str1.str(); + VarStr = Str2P; + constLen = isMemcmp ? sizedLen : GetStringLength(Str1P); + + } else { + + TmpConstStr = Str2.str(); + VarStr = Str1P; + constLen = isMemcmp ? sizedLen : GetStringLength(Str2P); + + } + + /* properly handle zero terminated C strings by adding the terminating 0 + * to the StringRef (in comparison to std::string a StringRef has built-in + * runtime bounds checking, which makes debugging easier) */ + TmpConstStr.append("\0", 1); + ConstStr = StringRef(TmpConstStr); + + if (isSizedcmp && constLen > sizedLen) { constLen = sizedLen; } + + /* + if (!be_quiet) + errs() << callInst->getCalledFunction()->getName() << ": len " + << constLen << ": " << ConstStr << "\n"; + */ + + if (constLen && constLen < MAX_DICT_FILE) + dictionary.push_back(ConstStr.str().substr(0, constLen)); + + } } - if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) { + if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL || dictionary.size()) { + + // yes we could create our own function, insert it into ctors ... + // but this would be a pain in the butt ... so we use afl-llvm-rt-lto.o - GlobalVariable *AFLFinalLoc = new GlobalVariable( - M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc", 0, - GlobalVariable::GeneralDynamicTLSModel, 0, false); - ConstantInt *const_loc = ConstantInt::get(Int32Ty, afl_global_id); - MaybeAlign Align = MaybeAlign(4); - AFLFinalLoc->setAlignment(Align); - AFLFinalLoc->setInitializer(const_loc); + Function *f = M.getFunction("__afl_auto_init_globals"); + + if (!f) { + + fprintf(stderr, + "Error: init function could not be found (this hould not " + "happen)\n"); + exit(-1); + + } + + BasicBlock *bb = &f->getEntryBlock(); + if (!bb) { + + fprintf(stderr, + "Error: init function does not have an EntryBlock (this should " + "not happen)\n"); + exit(-1); + + } + + BasicBlock::iterator IP = bb->getFirstInsertionPt(); + IRBuilder<> IRB(&(*IP)); + + if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) { + + GlobalVariable *AFLFinalLoc = new GlobalVariable( + M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc", + 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); + ConstantInt *const_loc = ConstantInt::get(Int32Ty, (((afl_global_id + 8) >> 3) << 3)); + StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); + StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } + + if (dictionary.size()) { + + size_t memlen = 0, count = 0, offset = 0; + char * ptr; + + for (auto token : dictionary) { + + memlen += token.length(); + count++; + + } + + if (!be_quiet) printf("AUTODICTIONARY: %lu strings found\n", count); + + if (count) { + + if ((ptr = (char *)malloc(memlen + count)) == NULL) { + + fprintf(stderr, "Error: malloc for %lu bytes failed!\n", + memlen + count); + exit(-1); + + } + + for (auto token : dictionary) { + + if (offset + token.length() < 0xfffff0) { + + ptr[offset++] = (uint8_t)token.length(); + memcpy(ptr + offset, token.c_str(), token.length()); + offset += token.length(); + + } + + } + + GlobalVariable *AFLDictionaryLen = new GlobalVariable( + M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, + "__afl_dictionary_len", 0, GlobalVariable::GeneralDynamicTLSModel, + 0, false); + ConstantInt *const_len = ConstantInt::get(Int32Ty, offset); + StoreInst *StoreDictLen = IRB.CreateStore(const_len, AFLDictionaryLen); + StoreDictLen->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + ArrayType *ArrayTy = ArrayType::get(IntegerType::get(C, 8), offset); + GlobalVariable *AFLInternalDictionary = new GlobalVariable( + M, ArrayTy, true, GlobalValue::ExternalLinkage, + ConstantDataArray::get(C, + *(new ArrayRef((char *)ptr, offset))), + "__afl_internal_dictionary", 0, + GlobalVariable::GeneralDynamicTLSModel, 0, false); + AFLInternalDictionary->setInitializer(ConstantDataArray::get( + C, *(new ArrayRef((char *)ptr, offset)))); + AFLInternalDictionary->setConstant(true); + + GlobalVariable *AFLDictionary = new GlobalVariable( + M, PointerType::get(Int8Ty, 0), false, GlobalValue::ExternalLinkage, + 0, "__afl_dictionary"); + + Value *AFLDictOff = IRB.CreateGEP(AFLInternalDictionary, Zero); + Value *AFLDictPtr = + IRB.CreatePointerCast(AFLDictOff, PointerType::get(Int8Ty, 0)); + StoreInst *StoreDict = IRB.CreateStore(AFLDictPtr, AFLDictionary); + StoreDict->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } + + } } diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 3651fd97..cbc4648d 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -50,11 +50,7 @@ Basically, we need to make sure that the forkserver is initialized after the LLVM-generated runtime initialization pass, not before. */ -#ifdef USE_TRACE_PC #define CONST_PRIO 5 -#else -#define CONST_PRIO 0 -#endif /* ^USE_TRACE_PC */ #include #include @@ -65,17 +61,20 @@ u8 __afl_area_initial[MAP_SIZE]; u8 *__afl_area_ptr = __afl_area_initial; +u8 *__afl_dictionary; #ifdef __ANDROID__ PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; u32 __afl_final_loc; u32 __afl_prev_ctx; u32 __afl_cmp_counter; +u32 __afl_dictionary_len; #else __thread PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; __thread u32 __afl_final_loc; __thread u32 __afl_prev_ctx; __thread u32 __afl_cmp_counter; +__thread u32 __afl_dictionary_len; #endif struct cmp_map *__afl_cmp_map; @@ -100,6 +99,10 @@ static void __afl_map_shm(void) { const char * shm_file_path = id_str; int shm_fd = -1; unsigned char *shm_base = NULL; + unsigned int map_size = MAP_SIZE + + if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) map_size = + __afl_final_loc; /* create the shared memory segment as if it was a file */ shm_fd = shm_open(shm_file_path, O_RDWR, 0600); @@ -111,7 +114,7 @@ static void __afl_map_shm(void) { } /* map the shared memory segment to the address space of the process */ - shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + shm_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); if (shm_base == MAP_FAILED) { close(shm_fd); @@ -187,8 +190,15 @@ static void __afl_map_shm(void) { #ifdef __linux__ static void __afl_start_snapshots(void) { - static u8 tmp[4]; + static u8 tmp[4] = {0, 0, 0, 0}; s32 child_pid; + u32 status = 0; + u32 map_size = MAP_SIZE; + u32 already_read_first = 0; + u32 was_killed; + + if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) + map_size = __afl_final_loc; u8 child_stopped = 0; @@ -197,16 +207,74 @@ static void __afl_start_snapshots(void) { /* Phone home and tell the parent that we're OK. If parent isn't there, assume we're not running in forkserver mode and just execute program. */ + status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT); + if (map_size <= 0x1000000) + status |= (FS_OPT_SET_MAPSIZE(map_size) | FS_OPT_MAPSIZE); + if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT; + memcpy(tmp, &status, 4); + if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; + if (__afl_dictionary_len > 0 && __afl_dictionary) { + + if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) == + (FS_OPT_ENABLED | FS_OPT_AUTODICT)) { + + // great lets pass the dictionary through the forkserver FD + u32 len = __afl_dictionary_len, offset = 0; + s32 ret; + + if (write(FORKSRV_FD + 1, &len, 4) != 4) { + + write(2, "Error: could not send dictionary len\n", + strlen("Error: could not send dictionary len\n")); + _exit(1); + + } + + while (len != 0) { + + ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + + if (ret < 1) { + + write(2, "Error: could not send dictionary\n", + strlen("Error: could not send dictionary\n")); + _exit(1); + + } + + len -= ret; + offset += ret; + + } + + } else { + + // uh this forkserver master does not understand extended option passing + // or does not want the dictionary + already_read_first = 1; + + } + + } + while (1) { - u32 was_killed; int status; - /* Wait for parent by reading from the pipe. Abort if read fails. */ + if (already_read_first) { - if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + already_read_first = 0; + + } else { + + /* Wait for parent by reading from the pipe. Abort if read fails. */ + if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + + } /* If we stopped the child in persistent mode, but there was a race condition and afl-fuzz already issued SIGKILL, write off the old @@ -291,26 +359,92 @@ static void __afl_start_forkserver(void) { #endif - static u8 tmp[4]; - s32 child_pid; + u8 tmp[4] = {0, 0, 0, 0}; + s32 child_pid; + u32 status = 0; + u32 map_size = MAP_SIZE; + u32 already_read_first = 0; + u32 was_killed; + + if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) + map_size = __afl_final_loc; u8 child_stopped = 0; void (*old_sigchld_handler)(int) = 0; // = signal(SIGCHLD, SIG_DFL); + if (map_size <= 0x1000000) + status |= (FS_OPT_SET_MAPSIZE(map_size) | FS_OPT_MAPSIZE); + if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT; + if (status) status |= (FS_OPT_ENABLED); + memcpy(tmp, &status, 4); + /* Phone home and tell the parent that we're OK. If parent isn't there, assume we're not running in forkserver mode and just execute program. */ if (write(FORKSRV_FD + 1, tmp, 4) != 4) return; + if (__afl_dictionary_len > 0 && __afl_dictionary) { + + if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + + if ((was_killed & (FS_OPT_ENABLED | FS_OPT_AUTODICT)) == + (FS_OPT_ENABLED | FS_OPT_AUTODICT)) { + + // great lets pass the dictionary through the forkserver FD + u32 len = __afl_dictionary_len, offset = 0; + s32 ret; + + if (write(FORKSRV_FD + 1, &len, 4) != 4) { + + write(2, "Error: could not send dictionary len\n", + strlen("Error: could not send dictionary len\n")); + _exit(1); + + } + + while (len != 0) { + + ret = write(FORKSRV_FD + 1, __afl_dictionary + offset, len); + + if (ret < 1) { + + write(2, "Error: could not send dictionary\n", + strlen("Error: could not send dictionary\n")); + _exit(1); + + } + + len -= ret; + offset += ret; + + } + + } else { + + // uh this forkserver master does not understand extended option passing + // or does not want the dictionary + already_read_first = 1; + + } + + } + while (1) { - u32 was_killed; int status; /* Wait for parent by reading from the pipe. Abort if read fails. */ - if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + if (already_read_first) { + + already_read_first = 0; + + } else { + + if (read(FORKSRV_FD, &was_killed, 4) != 4) _exit(1); + + } /* If we stopped the child in persistent mode, but there was a race condition and afl-fuzz already issued SIGKILL, write off the old @@ -378,8 +512,12 @@ static void __afl_start_forkserver(void) { int __afl_persistent_loop(unsigned int max_cnt) { - static u8 first_pass = 1; - static u32 cycle_cnt; + static u8 first_pass = 1; + static u32 cycle_cnt; + unsigned int map_size = MAP_SIZE; + + if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) + map_size = __afl_final_loc; if (first_pass) { @@ -390,7 +528,7 @@ int __afl_persistent_loop(unsigned int max_cnt) { if (is_persistent) { - memset(__afl_area_ptr, 0, MAP_SIZE); + memset(__afl_area_ptr, 0, map_size); __afl_area_ptr[0] = 1; memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T)); diff --git a/qemu_mode/patches/afl-qemu-cpu-inl.h b/qemu_mode/patches/afl-qemu-cpu-inl.h index 3bd107d7..d73566fc 100644 --- a/qemu_mode/patches/afl-qemu-cpu-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-inl.h @@ -293,7 +293,7 @@ static void print_mappings(void) { void afl_forkserver(CPUState *cpu) { - static unsigned char tmp[4]; + static unsigned char tmp[4] = {0, 0, 0, 0}; if (forkserver_installed == 1) return; forkserver_installed = 1; diff --git a/src/afl-common.c b/src/afl-common.c index 825cd827..5216c7e0 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -59,6 +59,7 @@ char *afl_environment_variables[] = { "AFL_LD_HARD_FAIL", "AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CTX", "AFL_LLVM_INSTRUMENT", "AFL_LLVM_INSTRIM_LOOPHEAD", + "AFL_LLVM_LTO_AUTODICTIONARY", "AFL_LLVM_AUTODICTIONARY", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_TRANSFORM_COMPARES", diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 56c3c9d5..d1037194 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -69,7 +69,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->mem_limit = MEM_LIMIT; fsrv->child_pid = -1; fsrv->out_dir_fd = -1; - + fsrv->map_size = MAP_SIZE; fsrv->use_fauxsrv = 0; fsrv->prev_timed_out = 0; @@ -82,7 +82,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { - unsigned char tmp[4] = {0}; + unsigned char tmp[4] = {0, 0, 0, 0}; pid_t child_pid = -1; /* Phone home and tell the parent that we're OK. If parent isn't there, @@ -167,9 +167,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, int status; s32 rlen; - if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:"); + if (!be_quiet) ACTF("Using Fauxserver:"); - if (!getenv("AFL_QUIET")) ACTF("Spinning up the fork server..."); + if (!be_quiet) ACTF("Spinning up the fork server..."); if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); @@ -340,7 +340,93 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (rlen == 4) { - if (!getenv("AFL_QUIET")) OKF("All right - fork server is up."); + if (!be_quiet) OKF("All right - fork server is up."); + + if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { + + if (!be_quiet) + ACTF("Extended forkserver functions received (%08x).", status); + + if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { + + fsrv->snapshot = 1; + if (!be_quiet) ACTF("Using SNAPSHOT feature."); + + } + + if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { + + fsrv->map_size = FS_OPT_GET_MAPSIZE(status); + if (fsrv->map_size % 8) + fsrv->map_size = (((fsrv->map_size + 8) >> 3) << 3); + if (!be_quiet) ACTF("Target map size: %u", fsrv->map_size); + + } + + if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) { + + // this is not afl-fuzz - we deny and return + status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT)); + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) + FATAL("Writing to forkserver failed."); + return; + + } + + if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { + + if (!be_quiet) ACTF("Using AUTODICT feature."); + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) + FATAL("Writing to forkserver failed."); + if (read(fsrv->fsrv_st_fd, &status, 4) != 4) + FATAL("Reading from forkserver failed."); + + if (status < 2 || (u32)status > 0xffffff) + FATAL("Dictionary has an illegal size: %d", status); + + u32 len = status, offset = 0, count = 0; + u8 *dict = ck_alloc(len); + if (dict == NULL) + FATAL("Could not allocate %u bytes of autodictionary memmory", len); + + while (len != 0) { + + rlen = read(fsrv->fsrv_st_fd, dict + offset, len); + if (rlen > 0) { + + len -= rlen; + offset += rlen; + + } else { + + FATAL( + "Reading autodictionary fail at position %u with %u bytes " + "left.", + offset, len); + + } + + } + + len = status; + offset = 0; + while (offset < status && (u8)dict[offset] + offset < status) { + + fsrv->function_ptr(fsrv->function_opt, dict + offset + 1, + (u8)dict[offset]); + offset += (1 + dict[offset]); + count++; + + } + + if (!be_quiet) ACTF("Loaded %u autodictionary entries", count); + ck_free(dict); + + } + + } + return; } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index c5347dcb..1c965532 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -78,16 +78,17 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { u64 *current = (u64 *)afl->fsrv.trace_bits; u64 *virgin = (u64 *)virgin_map; - u32 i = (MAP_SIZE >> 3); + u32 i = (afl->fsrv.map_size >> 3); #else u32 *current = (u32 *)afl->fsrv.trace_bits; u32 *virgin = (u32 *)virgin_map; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); #endif /* ^WORD_SIZE_64 */ + if (i == 0) i = 1; u8 ret = 0; @@ -148,12 +149,14 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { /* Count the number of bits set in the provided bitmap. Used for the status screen several times every second, does not have to be fast. */ -u32 count_bits(u8 *mem) { +u32 count_bits(afl_state_t *afl, u8 *mem) { u32 *ptr = (u32 *)mem; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; + if (i == 0) i = 1; + while (i--) { u32 v = *(ptr++); @@ -182,12 +185,14 @@ u32 count_bits(u8 *mem) { mostly to update the status screen or calibrate and examine confirmed new paths. */ -u32 count_bytes(u8 *mem) { +u32 count_bytes(afl_state_t *afl, u8 *mem) { u32 *ptr = (u32 *)mem; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; + if (i == 0) i = 1; + while (i--) { u32 v = *(ptr++); @@ -207,12 +212,14 @@ u32 count_bytes(u8 *mem) { /* Count the number of non-255 bytes set in the bitmap. Used strictly for the status screen, several calls per second or so. */ -u32 count_non_255_bytes(u8 *mem) { +u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) { u32 *ptr = (u32 *)mem; - u32 i = (MAP_SIZE >> 2); + u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; + if (i == 0) i = 1; + while (i--) { u32 v = *(ptr++); @@ -245,9 +252,11 @@ const u8 simplify_lookup[256] = { #ifdef WORD_SIZE_64 -void simplify_trace(u64 *mem) { +void simplify_trace(afl_state_t *afl, u64 *mem) { + + u32 i = (afl->fsrv.map_size >> 3); - u32 i = MAP_SIZE >> 3; + if (i == 0) i = 1; while (i--) { @@ -278,9 +287,11 @@ void simplify_trace(u64 *mem) { #else -void simplify_trace(u32 *mem) { +void simplify_trace(afl_state_t *afl, u32 *mem) { - u32 i = MAP_SIZE >> 2; + u32 i = (afl->fsrv.map_size >> 2); + + if (i == 0) i = 1; while (i--) { @@ -340,9 +351,11 @@ void init_count_class16(void) { #ifdef WORD_SIZE_64 -void classify_counts(u64 *mem) { +void classify_counts(afl_state_t *afl, u64 *mem) { + + u32 i = (afl->fsrv.map_size >> 3); - u32 i = MAP_SIZE >> 3; + if (i == 0) i = 1; while (i--) { @@ -367,9 +380,11 @@ void classify_counts(u64 *mem) { #else -void classify_counts(u32 *mem) { +void classify_counts(afl_state_t *afl, u32 *mem) { + + u32 i = (afl->fsrv.map_size >> 2); - u32 i = MAP_SIZE >> 2; + if (i == 0) i = 1; while (i--) { @@ -396,11 +411,11 @@ void classify_counts(u32 *mem) { count information here. This is called only sporadically, for some new paths. */ -void minimize_bits(u8 *dst, u8 *src) { +void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) { u32 i = 0; - while (i < MAP_SIZE) { + while (i < afl->fsrv.map_size) { if (*(src++)) dst[i >> 3] |= 1 << (i & 7); ++i; @@ -527,7 +542,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 fn[PATH_MAX]; /* Update path frequency. */ - u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + u32 cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); struct queue_entry *q = afl->queue; while (q) { @@ -611,9 +626,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (likely(!afl->dumb_mode)) { #ifdef WORD_SIZE_64 - simplify_trace((u64 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u64 *)afl->fsrv.trace_bits); #else - simplify_trace((u32 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ if (!has_new_bits(afl, afl->virgin_tmout)) return keeping; @@ -675,9 +690,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (likely(!afl->dumb_mode)) { #ifdef WORD_SIZE_64 - simplify_trace((u64 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u64 *)afl->fsrv.trace_bits); #else - simplify_trace((u32 *)afl->fsrv.trace_bits); + simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ if (!has_new_bits(afl, afl->virgin_crash)) return keeping; diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 5ad73539..ed4be6e4 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -389,7 +389,7 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { must prevent any earlier operations from venturing into that territory. */ - memset(afl->fsrv.trace_bits, 0, MAP_SIZE); + memset(afl->fsrv.trace_bits, 0, afl->fsrv.map_size); MEM_BARRIER(); /* Since we always have a forkserver (or a fauxserver) running, we can simply @@ -469,9 +469,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { tb4 = *(u32 *)afl->fsrv.trace_bits; #ifdef WORD_SIZE_64 - classify_counts((u64 *)afl->fsrv.trace_bits); + classify_counts(afl, (u64 *)afl->fsrv.trace_bits); #else - classify_counts((u32 *)afl->fsrv.trace_bits); + classify_counts(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ afl->cmplog_prev_timed_out = afl->fsrv.child_timed_out; diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 16806934..55146dd9 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -305,10 +305,14 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) { } /* Maybe add automatic extra. */ +/* Ugly hack: afl state is transfered as u8* because we import data via + afl-forkserver.c - which is shared with other afl tools that do not + have the afl state struct */ -void maybe_add_auto(afl_state_t *afl, u8 *mem, u32 len) { +void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { - u32 i; + afl_state_t *afl = (afl_state_t *)afl_tmp; + u32 i; /* Allow users to specify that they don't want auto dictionaries. */ @@ -469,7 +473,7 @@ void load_auto(afl_state_t *afl) { if (len < 0) PFATAL("Unable to read from '%s'", fn); if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) - maybe_add_auto(afl, tmp, len); + maybe_add_auto((u8 *)afl, tmp, len); close(fd); ck_free(fn); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 6e0485e5..94ce9604 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -448,11 +448,13 @@ static void check_map_coverage(afl_state_t *afl) { u32 i; - if (count_bytes(afl->fsrv.trace_bits) < 100) return; + if (count_bytes(afl, afl->fsrv.trace_bits) < 100) return; for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; ++i) if (afl->fsrv.trace_bits[i]) return; + if (afl->fsrv.map_size != MAP_SIZE) return; + WARNF("Recompile binary with newer version of afl to improve coverage!"); } diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 754b2190..81504e29 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -244,7 +244,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; } - cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (cksum == q->exec_cksum) { @@ -257,7 +257,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { if (!needs_write) { needs_write = 1; - memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits, MAP_SIZE); + memcpy(afl->clean_trace_custom, afl->fsrv.trace_bits, + afl->fsrv.map_size); } @@ -307,7 +308,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { ck_write(fd, in_buf, q->len, q->fname); close(fd); - memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, MAP_SIZE); + memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size); update_bitmap_score(afl, q); } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index b20bde90..80567160 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -601,7 +601,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (!afl->dumb_mode && (afl->stage_cur & 7) == 7) { - u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + u32 cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (afl->stage_cur == afl->stage_max - 1 && cksum == prev_cksum) { @@ -613,7 +613,7 @@ u8 fuzz_one_original(afl_state_t *afl) { ++a_len; if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) - maybe_add_auto(afl, a_collect, a_len); + maybe_add_auto((u8 *)afl, a_collect, a_len); } else if (cksum != prev_cksum) { @@ -621,7 +621,7 @@ u8 fuzz_one_original(afl_state_t *afl) { worthwhile queued up, and collect that if the answer is yes. */ if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) - maybe_add_auto(afl, a_collect, a_len); + maybe_add_auto((u8 *)afl, a_collect, a_len); a_len = 0; prev_cksum = cksum; @@ -761,7 +761,7 @@ u8 fuzz_one_original(afl_state_t *afl) { without wasting time on checksums. */ if (!afl->dumb_mode && len >= EFF_MIN_LEN) - cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); else cksum = ~afl->queue_cur->exec_cksum; @@ -2615,7 +2615,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (!afl->dumb_mode && (afl->stage_cur & 7) == 7) { - u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + u32 cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (afl->stage_cur == afl->stage_max - 1 && cksum == prev_cksum) { @@ -2627,7 +2627,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { ++a_len; if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) - maybe_add_auto(afl, a_collect, a_len); + maybe_add_auto((u8 *)afl, a_collect, a_len); } else if (cksum != prev_cksum) { @@ -2635,7 +2635,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { worthwhile queued up, and collect that if the answer is yes. */ if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) - maybe_add_auto(afl, a_collect, a_len); + maybe_add_auto((u8 *)afl, a_collect, a_len); a_len = 0; prev_cksum = cksum; @@ -2775,7 +2775,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { without wasting time on checksums. */ if (!afl->dumb_mode && len >= EFF_MIN_LEN) - cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); else cksum = ~afl->queue_cur->exec_cksum; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 174d7d92..346c2639 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -195,7 +195,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous winner, and how it compares to us. */ - for (i = 0; i < MAP_SIZE; ++i) + for (i = 0; i < afl->fsrv.map_size; ++i) if (afl->fsrv.trace_bits[i]) { @@ -248,8 +248,10 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { if (!q->trace_mini) { - q->trace_mini = ck_alloc(MAP_SIZE >> 3); - minimize_bits(q->trace_mini, afl->fsrv.trace_bits); + u32 len = (afl->fsrv.map_size >> 3); + if (len == 0) len = 1; + q->trace_mini = ck_alloc(len); + minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); } @@ -268,14 +270,17 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { void cull_queue(afl_state_t *afl) { struct queue_entry *q; - u8 temp_v[MAP_SIZE >> 3]; + u32 len = (afl->fsrv.map_size >> 3); u32 i; + u8 temp_v[MAP_SIZE >> 3]; + + if (len == 0) len = 1; if (afl->dumb_mode || !afl->score_changed) return; afl->score_changed = 0; - memset(temp_v, 255, MAP_SIZE >> 3); + memset(temp_v, 255, len); afl->queued_favored = 0; afl->pending_favored = 0; @@ -292,10 +297,10 @@ void cull_queue(afl_state_t *afl) { /* Let's see if anything in the bitmap isn't captured in temp_v. If yes, and if it has a afl->top_rated[] contender, let's use it. */ - for (i = 0; i < MAP_SIZE; ++i) + for (i = 0; i < afl->fsrv.map_size; ++i) if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { - u32 j = MAP_SIZE >> 3; + u32 j = len; /* Remove all bits belonging to the current entry from temp_v. */ diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 4acc204b..517f8d7c 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -88,7 +88,7 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) { if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1; - *cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + *cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); return 0; } @@ -332,7 +332,7 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { } - maybe_add_auto(afl, (u8 *)&v, shape); + maybe_add_auto((u8 *)afl, (u8 *)&v, shape); u64 rev; switch (shape) { @@ -340,15 +340,15 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { case 1: break; case 2: rev = SWAP16((u16)v); - maybe_add_auto(afl, (u8 *)&rev, shape); + maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); break; case 4: rev = SWAP32((u32)v); - maybe_add_auto(afl, (u8 *)&rev, shape); + maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); break; case 8: rev = SWAP64(v); - maybe_add_auto(afl, (u8 *)&rev, shape); + maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); break; } @@ -486,8 +486,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { // If failed, add to dictionary if (fails == 8) { - maybe_add_auto(afl, o->v0, SHAPE_BYTES(h->shape)); - maybe_add_auto(afl, o->v1, SHAPE_BYTES(h->shape)); + maybe_add_auto((u8 *)afl, o->v0, SHAPE_BYTES(h->shape)); + maybe_add_auto((u8 *)afl, o->v1, SHAPE_BYTES(h->shape)); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 9bbdd23a..850a18bc 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -44,7 +44,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) { must prevent any earlier operations from venturing into that territory. */ - memset(afl->fsrv.trace_bits, 0, MAP_SIZE); + memset(afl->fsrv.trace_bits, 0, afl->fsrv.map_size); MEM_BARRIER(); @@ -122,9 +122,9 @@ u8 run_target(afl_state_t *afl, u32 timeout) { tb4 = *(u32 *)afl->fsrv.trace_bits; #ifdef WORD_SIZE_64 - classify_counts((u64 *)afl->fsrv.trace_bits); + classify_counts(afl, (u64 *)afl->fsrv.trace_bits); #else - classify_counts((u32 *)afl->fsrv.trace_bits); + classify_counts(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ afl->fsrv.prev_timed_out = afl->fsrv.child_timed_out; @@ -315,7 +315,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, afl->shm.cmplog_mode) init_cmplog_forkserver(afl); - if (q->exec_cksum) memcpy(afl->first_trace, afl->fsrv.trace_bits, MAP_SIZE); + if (q->exec_cksum) + memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); start_us = get_cur_time_us(); @@ -336,14 +337,14 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (afl->stop_soon || fault != afl->crash_mode) goto abort_calibration; if (!afl->dumb_mode && !afl->stage_cur && - !count_bytes(afl->fsrv.trace_bits)) { + !count_bytes(afl, afl->fsrv.trace_bits)) { fault = FAULT_NOINST; goto abort_calibration; } - cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); if (q->exec_cksum != cksum) { @@ -354,7 +355,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u32 i; - for (i = 0; i < MAP_SIZE; ++i) { + for (i = 0; i < afl->fsrv.map_size; ++i) { if (unlikely(!afl->var_bytes[i]) && unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i])) @@ -368,7 +369,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } else { q->exec_cksum = cksum; - memcpy(afl->first_trace, afl->fsrv.trace_bits, MAP_SIZE); + memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); } @@ -385,7 +386,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, This is used for fuzzing air time calculations in calculate_score(). */ q->exec_us = (stop_us - start_us) / afl->stage_max; - q->bitmap_size = count_bytes(afl->fsrv.trace_bits); + q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits); q->handicap = handicap; q->cal_failed = 0; @@ -413,7 +414,7 @@ abort_calibration: if (var_detected) { - afl->var_byte_count = count_bytes(afl->var_bytes); + afl->var_byte_count = count_bytes(afl, afl->var_bytes); if (!q->var_behavior) { @@ -640,7 +641,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ - cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); /* If the deletion had no impact on the trace, make it permanent. This isn't perfect for variable-path inputs, but we're just making a @@ -663,7 +664,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { if (!needs_write) { needs_write = 1; - memcpy(afl->clean_trace, afl->fsrv.trace_bits, MAP_SIZE); + memcpy(afl->clean_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); } @@ -705,7 +706,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { ck_write(fd, in_buf, q->len, q->fname); close(fd); - memcpy(afl->fsrv.trace_bits, afl->clean_trace, MAP_SIZE); + memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size); update_bitmap_score(afl, q); } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index a8c14c31..80039d6f 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -99,6 +99,10 @@ void afl_state_init(afl_state_t *afl) { afl->fsrv.use_stdin = 1; + afl->fsrv.map_size = MAP_SIZE; + afl->fsrv.function_opt = (u8 *)afl; + afl->fsrv.function_ptr = &maybe_add_auto; + afl->cal_cycles = CAL_CYCLES; afl->cal_cycles_long = CAL_CYCLES_LONG; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index ab84bf3f..58a37298 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -37,7 +37,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, u8 fn[PATH_MAX]; s32 fd; FILE * f; - uint32_t t_bytes = count_non_255_bytes(afl->virgin_bits); + uint32_t t_bytes = count_non_255_bytes(afl, afl->virgin_bits); snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir); @@ -258,8 +258,8 @@ void show_stats(afl_state_t *afl) { /* Do some bitmap stats. */ - t_bytes = count_non_255_bytes(afl->virgin_bits); - t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE; + t_bytes = count_non_255_bytes(afl, afl->virgin_bits); + t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.map_size; if (likely(t_bytes) && unlikely(afl->var_byte_count)) stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes); @@ -305,7 +305,7 @@ void show_stats(afl_state_t *afl) { /* Compute some mildly useful bitmap stats. */ - t_bits = (MAP_SIZE << 3) - count_bits(afl->virgin_bits); + t_bits = (afl->fsrv.map_size << 3) - count_bits(afl, afl->virgin_bits); /* Now, for the visuals... */ @@ -465,7 +465,8 @@ void show_stats(afl_state_t *afl) { SAYF(bV bSTOP " now processing : " cRST "%-16s " bSTG bV bSTOP, tmp); sprintf(tmp, "%0.02f%% / %0.02f%%", - ((double)afl->queue_cur->bitmap_size) * 100 / MAP_SIZE, t_byte_ratio); + ((double)afl->queue_cur->bitmap_size) * 100 / afl->fsrv.map_size, + t_byte_ratio); SAYF(" map density : %s%-21s" bSTG bV "\n", t_byte_ratio > 70 ? cLRD diff --git a/src/afl-tmin.c b/src/afl-tmin.c index f899a6b5..53e8705d 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -258,7 +258,7 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, fsrv->child_timed_out = 0; - memset(fsrv->trace_bits, 0, MAP_SIZE); + memset(fsrv->trace_bits, 0, fsrv->map_size); MEM_BARRIER(); write_to_testcase(fsrv, mem, len); @@ -393,7 +393,7 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, } - cksum = hash32(fsrv->trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST); if (first_run) orig_cksum = cksum; -- cgit 1.4.1 From 29ee3a1ffca2aa5a3939beb84d7c6a81621f3355 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 11 Apr 2020 01:09:07 +0200 Subject: refactored cmplog --- include/afl-fuzz.h | 6 +- include/cmplog.h | 6 + include/forkserver.h | 10 +- src/afl-analyze.c | 10 +- src/afl-common.c | 4 +- src/afl-forkserver.c | 32 ++-- src/afl-fuzz-bitmap.c | 2 +- src/afl-fuzz-cmplog.c | 477 +----------------------------------------------- src/afl-fuzz-init.c | 6 +- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-run.c | 65 +++---- src/afl-fuzz-stats.c | 6 +- src/afl-fuzz.c | 29 ++- src/afl-showmap.c | 18 +- src/afl-tmin.c | 14 +- 15 files changed, 129 insertions(+), 558 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index edda81e1..97c1f31c 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -439,7 +439,6 @@ typedef struct afl_state { no_arith, /* Skip most arithmetic ops */ shuffle_queue, /* Shuffle input queue? */ bitmap_changed, /* Time to update bitmap? */ - qemu_mode, /* Running in QEMU mode? */ unicorn_mode, /* Running in Unicorn mode? */ use_wine, /* Use WINE with QEMU mode */ skip_requested, /* Skip request, via SIGUSR1 */ @@ -560,7 +559,7 @@ typedef struct afl_state { /* CmpLog */ char *cmplog_binary; - s32 cmplog_child_pid, cmplog_fsrv_pid; + afl_forkserver_t cmplog_fsrv; /* cmplog has its own little forkserver */ /* Custom mutators */ struct custom_mutator *mutator; @@ -878,7 +877,7 @@ void show_init_stats(afl_state_t *); /* Run */ -u8 run_target(afl_state_t *, u32); +u8 run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); void write_to_testcase(afl_state_t *, void *, u32); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); void sync_fuzzers(afl_state_t *); @@ -922,7 +921,6 @@ void save_cmdline(afl_state_t *, u32, char **); /* CmpLog */ -void init_cmplog_forkserver(afl_state_t *afl); u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len); /* RedQueen */ diff --git a/include/cmplog.h b/include/cmplog.h index 36f8f2c5..4731f779 100644 --- a/include/cmplog.h +++ b/include/cmplog.h @@ -29,6 +29,7 @@ #define _AFL_CMPLOG_H #include "config.h" +#include "forkserver.h" #define CMP_MAP_W 65536 #define CMP_MAP_H 256 @@ -74,5 +75,10 @@ struct cmp_map { }; +/* Execs the child */ + +void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv); + + #endif diff --git a/include/forkserver.h b/include/forkserver.h index 7470dbbc..24fa3e1b 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -66,15 +66,23 @@ typedef struct afl_forkserver { u32 prev_timed_out; /* if prev forkserver run timed out */ + u8 qemu_mode; /* if running in qemu mode or not */ + + char *cmplog_binary; /* the name of the cmplog binary */ + + /* Function to kick off the forkserver child */ + void (*init_child_func)(struct afl_forkserver *fsrv, char **argv); + u8 *function_opt; /* for autodictionary: afl ptr */ void (*function_ptr)(void *afl_tmp, u8 *mem, u32 len); + } afl_forkserver_t; void afl_fsrv_init(afl_forkserver_t *fsrv); void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, - volatile u8 *stop_soon_p); + volatile u8 *stop_soon_p, u8 debug_child_output); void afl_fsrv_deinit(afl_forkserver_t *fsrv); void afl_fsrv_killall(); diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 427fbe6d..b0e8afcb 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -36,6 +36,7 @@ #include "hash.h" #include "sharedmem.h" #include "common.h" +#include "forkserver.h" #include #include @@ -57,7 +58,7 @@ static s32 child_pid; /* PID of the tested program */ -u8 *trace_bits; /* SHM with instrumentation bitmap */ +static u8 *trace_bits; /* SHM with instrumentation bitmap */ static u8 *in_file, /* Analyzer input test case */ *prog_in; /* Targeted program input file */ @@ -74,16 +75,15 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ static s32 dev_null_fd = -1; /* FD to /dev/null */ -u8 edges_only, /* Ignore hit counts? */ +static u8 edges_only, /* Ignore hit counts? */ use_hex_offsets, /* Show hex offsets? */ use_stdin = 1; /* Use stdin for program input? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_timed_out; /* Child timed out? */ -static u8 qemu_mode; - static u8 *target_path; +static u8 qemu_mode; /* Constants used for describing byte behavior. */ @@ -639,7 +639,7 @@ static void handle_stop_sig(int sig) { /* Do basic preparations - persistent fds, filenames, etc. */ -static void set_up_environment(void) { +static void set_up_environment() { u8 *x; diff --git a/src/afl-common.c b/src/afl-common.c index 5216c7e0..7eba6ae4 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -235,7 +235,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be " "built\n" " separately by following the instructions in " - "afl->qemu_mode/README.md. " + "qemu_mode/README.md. " "If you\n" " already have the binary installed, you may need to specify " "AFL_PATH in the\n" @@ -332,7 +332,7 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { "Oops, unable to find the '%s' binary. The binary must be " "built\n" " separately by following the instructions in " - "afl->qemu_mode/README.md. " + "qemu_mode/README.md. " "If you\n" " already have the binary installed, you may need to specify " "AFL_PATH in the\n" diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index d1ff0e4d..7ab8a4b5 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -51,6 +51,12 @@ list_t fsrv_list = {.element_prealloc_count = 0}; +static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { + + execv(fsrv->target_path, argv); + +} + /* Initializes the struct */ void afl_fsrv_init(afl_forkserver_t *fsrv) { @@ -73,6 +79,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->use_fauxsrv = 0; fsrv->prev_timed_out = 0; + fsrv->init_child_func = fsrv_exec_child; + list_append(&fsrv_list, fsrv); } @@ -163,7 +171,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { through a pipe. The other part of this logic is in afl-as.h / llvm_mode */ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, - volatile u8 *stop_soon_p) { + volatile u8 *stop_soon_p, u8 debug_child_output) { int st_pipe[2], ctl_pipe[2]; int status; @@ -171,6 +179,16 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!be_quiet) ACTF("Spinning up the fork server..."); + if (fsrv->use_fauxsrv) { + + /* TODO: Come up with sone nice way to initalize this all */ + + if (fsrv->init_child_func != fsrv_exec_child) + FATAL("Different forkserver not compatible with fauxserver"); + + fsrv->init_child_func = afl_fauxsrv_execv; + } + if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); fsrv->child_timed_out = 0; @@ -221,7 +239,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, setsid(); - if (!get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) { + if (!(debug_child_output)) { dup2(fsrv->dev_null_fd, 1); dup2(fsrv->dev_null_fd, 2); @@ -283,15 +301,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, "msan_track_origins=0", 0); - if (fsrv->use_fauxsrv) { - - afl_fauxsrv_execv(fsrv, argv); - - } else { - - execv(fsrv->target_path, argv); - - } + fsrv->init_child_func(fsrv, argv); /* Use a distinctive bitmap signature to tell the parent about execv() falling through. */ diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 1c965532..b6a494db 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -645,7 +645,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 new_fault; write_to_testcase(afl, mem, len); - new_fault = run_target(afl, afl->hang_tmout); + new_fault = run_target(afl, &afl->fsrv, afl->hang_tmout); /* A corner case that one user reported bumping into: increasing the timeout actually uncovers a crash. Make sure we don't discard it if diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index ed4be6e4..f9480dc4 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -29,480 +29,21 @@ #include "afl-fuzz.h" #include "cmplog.h" -void init_cmplog_forkserver(afl_state_t *afl) { +typedef struct cmplog_data { +} cmplog_data_t; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; +void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { - ACTF("Spinning up the cmplog fork server..."); + setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); + if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) { - afl->fsrv.child_timed_out = 0; - afl->cmplog_fsrv_pid = fork(); - - if (afl->cmplog_fsrv_pid < 0) PFATAL("fork() failed"); - - if (!afl->cmplog_fsrv_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 (afl->fsrv.mem_limit) { - - r.rlim_max = r.rlim_cur = ((rlim_t)afl->fsrv.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 - afl->fsrv.out_file is specified, stdin is /dev/null; otherwise, - afl->fsrv.out_fd is cloned instead. */ - - setsid(); - - if (!(afl->afl_env.afl_debug_child_output)) { - - dup2(afl->fsrv.dev_null_fd, 1); - dup2(afl->fsrv.dev_null_fd, 2); - - } - - if (!afl->fsrv.use_stdin) { - - dup2(afl->fsrv.dev_null_fd, 0); - - } else { - - dup2(afl->fsrv.out_fd, 0); - close(afl->fsrv.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(afl->fsrv.out_dir_fd); - close(afl->fsrv.dev_null_fd); -#ifndef HAVE_ARC4RANDOM - close(afl->fsrv.dev_urandom_fd); -#endif - if (afl->fsrv.plot_file != NULL) fclose(afl->fsrv.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:" - "malloc_context_size=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:" - "malloc_context_size=0:" - "allocator_may_return_null=1:" - "msan_track_origins=0", - 0); - - setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - - if (!afl->qemu_mode && afl->argv[0] != afl->cmplog_binary) { - - ck_free(afl->argv[0]); - afl->argv[0] = afl->cmplog_binary; - - } - - execv(afl->argv[0], afl->argv); - - /* Use a distinctive bitmap signature to tell the parent about execv() - falling through. */ - - *(u32 *)afl->fsrv.trace_bits = EXEC_FAIL_SIG; - exit(0); - - } - - /* PARENT PROCESS */ - - /* Close the unneeded endpoints. */ - - close(ctl_pipe[0]); - close(st_pipe[1]); - - afl->cmplog_fsrv_ctl_fd = ctl_pipe[1]; - afl->cmplog_fsrv_st_fd = st_pipe[0]; - - /* Wait for the fork server to come up, but don't wait too long. */ - - rlen = 0; - if (afl->fsrv.exec_tmout) { - - rlen = 4; - u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT; - /* Reuse readfds as exceptfds to see when the child closed the pipe */ - u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms, - &afl->stop_soon); - - if (!exec_ms) { - - PFATAL("Error in timed read"); - - } else if (exec_ms > timeout_ms) { - - afl->fsrv.child_timed_out = 1; - kill(afl->cmplog_fsrv_pid, SIGKILL); - rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); - - } - - } else { - - rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); - - } - - /* If we have a four-byte "hello" message from the server, we're all set. - Otherwise, try to figure out what went wrong. */ - - if (afl->fsrv.child_timed_out) - FATAL( - "Timeout while initializing cmplog fork server (adjusting -t may " - "help)"); - - if (rlen == 4) { - - OKF("All right - fork server is up."); - return; - - } - - if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0) - PFATAL("waitpid() failed"); - - if (WIFSIGNALED(status)) { - - if (afl->fsrv.mem_limit && afl->fsrv.mem_limit < 500 && - afl->fsrv.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.md for help.\n", - doc_path); - - } else if (!afl->fsrv.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 for troubleshooting " - "tips.\n"); - - } else { - - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - - 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 for troubleshooting " - "tips.\n", - stringify_mem_size(val_buf, sizeof(val_buf), - afl->fsrv.mem_limit << 20), - afl->fsrv.mem_limit - 1); - - } - - FATAL("Cmplog fork server crashed with signal %d", WTERMSIG(status)); - - } - - if (*(u32 *)afl->fsrv.trace_bits == EXEC_FAIL_SIG) - FATAL("Unable to execute target application ('%s')", afl->argv[0]); - - if (afl->fsrv.mem_limit && afl->fsrv.mem_limit < 500 && afl->fsrv.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.md for help.\n", - doc_path); - - } else if (!afl->fsrv.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 for troubleshooting " - "tips.\n"); - - } else { - - u8 val_buf[STRINGIFY_VAL_SIZE_MAX]; - - 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 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" - : "", - stringify_mem_size(val_buf, sizeof(val_buf), afl->fsrv.mem_limit << 20), - afl->fsrv.mem_limit - 1); - - } - - FATAL("Cmplog fork server handshake failed"); - -} - -u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { - - int status = 0; - u32 exec_ms; - - u32 tb4; - s32 res; - - afl->fsrv.child_timed_out = 0; - - /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we - must prevent any earlier operations from venturing into that - territory. */ - - memset(afl->fsrv.trace_bits, 0, afl->fsrv.map_size); - MEM_BARRIER(); - - /* Since we always have a forkserver (or a fauxserver) running, we can simply - tell them to have at it and read back the pid from it.*/ - - if ((res = write(afl->cmplog_fsrv_ctl_fd, &afl->cmplog_prev_timed_out, 4)) != - 4) { - - if (afl->stop_soon) return 0; - RPFATAL(res, - "Unable to request new process from cmplog fork server (OOM?)"); + ck_free(argv[0]); + argv[0] = fsrv->cmplog_binary; } - if ((res = read(afl->cmplog_fsrv_st_fd, &afl->cmplog_child_pid, 4)) != 4) { - - if (afl->stop_soon) return 0; - RPFATAL(res, - "Unable to request new process from cmplog fork server (OOM?)"); - - } - - if (afl->cmplog_child_pid <= 0) - FATAL("Cmplog fork server is misbehaving (OOM?)"); - - /* Configure timeout, as requested by user, then wait for child to terminate. - */ - exec_ms = - read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout, &afl->stop_soon); - - if (exec_ms > timeout) { - - /* If there was no response from forkserver after timeout seconds, - we kill the child. The forkserver should inform us afterwards */ - - kill(afl->cmplog_child_pid, SIGKILL); - afl->fsrv.child_timed_out = 1; - - /* After killing the child, the forkserver should tell us */ - if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) exec_ms = 0; - - } - - if (!exec_ms) { // Something went wrong. - - if (afl->stop_soon) return 0; - SAYF("\n" cLRD "[-] " cRST - "Unable to communicate with fork server. Some possible reasons:\n\n" - " - You've run out of memory. Use -m to increase the the memory " - "limit\n" - " to something higher than %lld.\n" - " - The binary or one of the libraries it uses manages to create\n" - " threads before the forkserver initializes.\n" - " - The binary, at least in some circumstances, exits in a way " - "that\n" - " also kills the parent process - raise() could be the " - "culprit.\n\n" - "If all else fails you can disable the fork server via " - "AFL_NO_FORKSRV=1.\n", - afl->fsrv.mem_limit); - RPFATAL(res, "Unable to communicate with fork server"); - - } - - if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0; - - if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms; - - ++afl->total_execs; - - /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the - compiler below this point. Past this location, afl->fsrv.trace_bits[] - behave very normally and do not have to be treated as volatile. */ - - MEM_BARRIER(); - - tb4 = *(u32 *)afl->fsrv.trace_bits; - -#ifdef WORD_SIZE_64 - classify_counts(afl, (u64 *)afl->fsrv.trace_bits); -#else - classify_counts(afl, (u32 *)afl->fsrv.trace_bits); -#endif /* ^WORD_SIZE_64 */ - - afl->cmplog_prev_timed_out = afl->fsrv.child_timed_out; - - /* Report outcome to caller. */ - - if (WIFSIGNALED(status) && !afl->stop_soon) { - - afl->kill_signal = WTERMSIG(status); - - if (afl->fsrv.child_timed_out && afl->kill_signal == SIGKILL) - return FAULT_TMOUT; - - return FAULT_CRASH; - - } - - /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and - must use a special exit code. */ - - if (afl->fsrv.uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { - - afl->kill_signal = 0; - return FAULT_CRASH; - - } - - if ((afl->dumb_mode == 1 || afl->no_forkserver) && tb4 == EXEC_FAIL_SIG) - return FAULT_ERROR; - - return FAULT_NONE; + execv(argv[0], argv); } @@ -524,7 +65,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { write_to_testcase(afl, out_buf, len); - fault = run_cmplog_target(afl, afl->fsrv.exec_tmout); + fault = run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); if (afl->stop_soon) return 1; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 94ce9604..54cc81ef 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1853,8 +1853,6 @@ static void handle_stop_sig(int sig) { if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, SIGKILL); if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, SIGKILL); - if (el->cmplog_child_pid > 0) kill(el->cmplog_child_pid, SIGKILL); - if (el->cmplog_fsrv_pid > 0) kill(el->cmplog_fsrv_pid, SIGKILL); }); @@ -1988,7 +1986,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { #endif /* ^!__APPLE__ */ - if (!afl->qemu_mode && !afl->unicorn_mode && !afl->dumb_mode && + if (!afl->fsrv.qemu_mode && !afl->unicorn_mode && !afl->dumb_mode && !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST @@ -2015,7 +2013,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } - if ((afl->qemu_mode) && + if ((afl->fsrv.qemu_mode) && memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 81504e29..a7d7ae18 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -239,7 +239,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { write_to_testcase(afl, retbuf, retlen); - fault = run_target(afl, afl->fsrv.exec_tmout); + fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 850a18bc..3a178e87 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -27,10 +27,12 @@ #include #include +#include "cmplog.h" + /* Execute target application, monitoring for timeouts. Return status - information. The called program will update afl->fsrv.trace_bits. */ + information. The called program will update afl->fsrv->trace_bits. */ -u8 run_target(afl_state_t *afl, u32 timeout) { +u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { s32 res; u32 exec_ms; @@ -38,46 +40,46 @@ u8 run_target(afl_state_t *afl, u32 timeout) { int status = 0; u32 tb4; - afl->fsrv.child_timed_out = 0; + fsrv->child_timed_out = 0; - /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we + /* After this memset, fsrv->trace_bits[] are effectively volatile, so we must prevent any earlier operations from venturing into that territory. */ - memset(afl->fsrv.trace_bits, 0, afl->fsrv.map_size); + memset(fsrv->trace_bits, 0, fsrv->map_size); MEM_BARRIER(); /* we have the fork server (or faux server) up and running, so simply tell it to have at it, and then read back PID. */ - if ((res = write(afl->fsrv.fsrv_ctl_fd, &afl->fsrv.prev_timed_out, 4)) != 4) { + if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) { if (afl->stop_soon) return 0; RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } - if ((res = read(afl->fsrv.fsrv_st_fd, &afl->fsrv.child_pid, 4)) != 4) { + if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { if (afl->stop_soon) return 0; RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } - if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); + if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); exec_ms = - read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout, &afl->stop_soon); + read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, &afl->stop_soon); if (exec_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ - kill(afl->fsrv.child_pid, SIGKILL); - afl->fsrv.child_timed_out = 1; - if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0; + kill(fsrv->child_pid, SIGKILL); + fsrv->child_timed_out = 1; + if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0; } @@ -104,30 +106,30 @@ u8 run_target(afl_state_t *afl, u32 timeout) { "\n\n" "If all else fails you can disable the fork server via " "AFL_NO_FORKSRV=1.\n", - afl->fsrv.mem_limit); + fsrv->mem_limit); RPFATAL(res, "Unable to communicate with fork server"); } - if (!WIFSTOPPED(status)) afl->fsrv.child_pid = 0; + if (!WIFSTOPPED(status)) fsrv->child_pid = 0; ++afl->total_execs; - /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the - compiler below this point. Past this location, afl->fsrv.trace_bits[] + /* Any subsequent operations on fsrv->trace_bits must not be moved by the + compiler below this point. Past this location, fsrv->trace_bits[] behave very normally and do not have to be treated as volatile. */ MEM_BARRIER(); - tb4 = *(u32 *)afl->fsrv.trace_bits; + tb4 = *(u32 *)fsrv->trace_bits; #ifdef WORD_SIZE_64 - classify_counts(afl, (u64 *)afl->fsrv.trace_bits); + classify_counts(afl, (u64 *)fsrv->trace_bits); #else - classify_counts(afl, (u32 *)afl->fsrv.trace_bits); + classify_counts(afl, (u32 *)fsrv->trace_bits); #endif /* ^WORD_SIZE_64 */ - afl->fsrv.prev_timed_out = afl->fsrv.child_timed_out; + fsrv->prev_timed_out = fsrv->child_timed_out; /* Report outcome to caller. */ @@ -135,7 +137,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) { afl->kill_signal = WTERMSIG(status); - if (afl->fsrv.child_timed_out && afl->kill_signal == SIGKILL) + if (fsrv->child_timed_out && afl->kill_signal == SIGKILL) return FAULT_TMOUT; return FAULT_CRASH; @@ -145,7 +147,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) { /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and must use a special exit code. */ - if (afl->fsrv.uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { + if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { afl->kill_signal = 0; return FAULT_CRASH; @@ -309,11 +311,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, /* Make sure the forkserver is up before we do anything, and let's not count its spin-up time toward binary calibration. */ - if (!afl->fsrv.fsrv_pid) - afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon); - if (afl->dumb_mode != 1 && !afl->no_forkserver && !afl->cmplog_fsrv_pid && - afl->shm.cmplog_mode) - init_cmplog_forkserver(afl); + if (!afl->fsrv.fsrv_pid) { + if (afl->shm.cmplog_mode && afl->fsrv.init_child_func != cmplog_exec_child) { + FATAL("BUG in afl-fuzz detected. Cmplog mode not set correctly."); + } + afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child_output); + } if (q->exec_cksum) memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); @@ -329,7 +332,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, write_to_testcase(afl, use_mem, q->len); - fault = run_target(afl, use_tmout); + fault = run_target(afl, &afl->fsrv, use_tmout); /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, we want to bail out quickly. */ @@ -546,7 +549,7 @@ void sync_fuzzers(afl_state_t *afl) { write_to_testcase(afl, mem, st.st_size); - fault = run_target(afl, afl->fsrv.exec_tmout); + fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); if (afl->stop_soon) goto close_sync; @@ -633,7 +636,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); - fault = run_target(afl, afl->fsrv.exec_tmout); + fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming; @@ -740,7 +743,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { write_to_testcase(afl, out_buf, len); - fault = run_target(afl, afl->fsrv.exec_tmout); + fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); if (afl->stop_soon) return 1; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 58a37298..d83a747f 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -124,12 +124,12 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, (unsigned long int)(rus.ru_maxrss >> 10), #endif t_bytes, afl->var_byte_count, afl->use_banner, - afl->unicorn_mode ? "unicorn" : "", afl->qemu_mode ? "qemu " : "", + afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->dumb_mode ? " dumb " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", afl->persistent_mode ? "persistent " : "", afl->deferred_mode ? "deferred " : "", - (afl->unicorn_mode || afl->qemu_mode || afl->dumb_mode || + (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->dumb_mode || afl->no_forkserver || afl->crash_mode || afl->persistent_mode || afl->deferred_mode) ? "" @@ -820,7 +820,7 @@ void show_init_stats(afl_state_t *afl) { SAYF("\n"); - if (avg_us > ((afl->qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) + if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.", doc_path); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 836393ac..44c48088 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -24,6 +24,7 @@ */ #include "afl-fuzz.h" +#include "cmplog.h" static u8 *get_libradamsa_path(u8 *own_loc) { @@ -213,6 +214,8 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) { static int stricmp(char const *a, char const *b) { + if (!a || !b) FATAL("Null reference"); + for (;; ++a, ++b) { int d; @@ -498,8 +501,8 @@ int main(int argc, char **argv_orig, char **envp) { case 'Q': /* QEMU mode */ - if (afl->qemu_mode) FATAL("Multiple -Q options not supported"); - afl->qemu_mode = 1; + if (afl->fsrv.qemu_mode) FATAL("Multiple -Q options not supported"); + afl->fsrv.qemu_mode = 1; if (!mem_limit_given) afl->fsrv.mem_limit = MEM_LIMIT_QEMU; @@ -524,7 +527,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'W': /* Wine+QEMU mode */ if (afl->use_wine) FATAL("Multiple -W options not supported"); - afl->qemu_mode = 1; + afl->fsrv.qemu_mode = 1; afl->use_wine = 1; if (!mem_limit_given) afl->fsrv.mem_limit = 0; @@ -748,7 +751,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->dumb_mode) { if (afl->crash_mode) FATAL("-C and -n are mutually exclusive"); - if (afl->qemu_mode) FATAL("-Q and -n are mutually exclusive"); + if (afl->fsrv.qemu_mode) FATAL("-Q and -n are mutually exclusive"); if (afl->unicorn_mode) FATAL("-U and -n are mutually exclusive"); } @@ -816,7 +819,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->afl_env.afl_preload) { - if (afl->qemu_mode) { + if (afl->fsrv.qemu_mode) { u8 *qemu_preload = getenv("QEMU_SET_ENV"); u8 *afl_preload = getenv("AFL_PRELOAD"); @@ -991,7 +994,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->unicorn_mode) FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry"); - if (!afl->qemu_mode) check_binary(afl, afl->cmplog_binary); + if (!afl->fsrv.qemu_mode) check_binary(afl, afl->cmplog_binary); } @@ -999,7 +1002,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->start_time = get_cur_time(); - if (afl->qemu_mode) { + if (afl->fsrv.qemu_mode) { if (afl->use_wine) use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind, @@ -1015,6 +1018,16 @@ int main(int argc, char **argv_orig, char **envp) { } afl->argv = use_argv; + + if (afl->cmplog_binary) { + + SAYF("Spawning cmplog forkserver"); + memcpy(&afl->cmplog_fsrv, &afl->fsrv, sizeof(afl->fsrv)); + afl->cmplog_fsrv.init_child_func = cmplog_exec_child; + afl_fsrv_start(&afl->cmplog_fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child_output); + + } + perform_dry_run(afl); cull_queue(afl); @@ -1152,8 +1165,6 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.child_pid > 0) kill(afl->fsrv.child_pid, SIGKILL); if (afl->fsrv.fsrv_pid > 0) kill(afl->fsrv.fsrv_pid, SIGKILL); - if (afl->cmplog_child_pid > 0) kill(afl->cmplog_child_pid, SIGKILL); - if (afl->cmplog_fsrv_pid > 0) kill(afl->cmplog_fsrv_pid, SIGKILL); /* Now that we've killed the forkserver, we wait for it to be able to get * rusage stats. */ if (waitpid(afl->fsrv.fsrv_pid, NULL, 0) <= 0) { WARNF("error waitpid\n"); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 2fd17fb1..a8198f79 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -81,8 +81,6 @@ u8 quiet_mode, /* Hide non-essential messages? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ -static u8 qemu_mode; - /* Classify tuple counts. Instead of mapping to individual bits, as in afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */ @@ -482,7 +480,7 @@ static void handle_stop_sig(int sig) { /* Do basic preparations - persistent fds, filenames, etc. */ -static void set_up_environment(void) { +static void set_up_environment(afl_forkserver_t *fsrv) { setenv("ASAN_OPTIONS", "abort_on_error=1:" @@ -499,7 +497,7 @@ static void set_up_environment(void) { if (get_afl_env("AFL_PRELOAD")) { - if (qemu_mode) { + if (fsrv->qemu_mode) { u8 *qemu_preload = getenv("QEMU_SET_ENV"); u8 *afl_preload = getenv("AFL_PRELOAD"); @@ -798,10 +796,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'Q': - if (qemu_mode) FATAL("Multiple -Q options not supported"); + if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported"); if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU; - qemu_mode = 1; + fsrv->qemu_mode = 1; break; case 'U': @@ -815,7 +813,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'W': /* Wine+QEMU mode */ if (use_wine) FATAL("Multiple -W options not supported"); - qemu_mode = 1; + fsrv->qemu_mode = 1; use_wine = 1; if (!mem_limit_given) fsrv->mem_limit = 0; @@ -860,7 +858,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); setup_signal_handlers(); - set_up_environment(); + set_up_environment(fsrv); find_binary(fsrv, argv[optind]); @@ -885,7 +883,7 @@ int main(int argc, char **argv_orig, char **envp) { for (i = optind; i < argc; i++) if (strcmp(argv[i], "@@") == 0) arg_offset = i; - if (qemu_mode) { + if (fsrv->qemu_mode) { if (use_wine) use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind, @@ -951,7 +949,7 @@ int main(int argc, char **argv_orig, char **envp) { } - afl_fsrv_start(fsrv, use_argv, &stop_soon); + afl_fsrv_start(fsrv, use_argv, &stop_soon, get_afl_env("AFL_DEBUG_CHILD_OUTPUT")? 1 :0); while (done == 0 && (dir_ent = readdir(dir_in))) { diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 53e8705d..8ad33814 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -80,8 +80,6 @@ u8 crash_mode, /* Crash-centric mode? */ static volatile u8 stop_soon; /* Ctrl-C pressed? */ -static u8 qemu_mode; - /* * forkserver section */ @@ -746,7 +744,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { if (get_afl_env("AFL_PRELOAD")) { - if (qemu_mode) { + if (fsrv->qemu_mode) { u8 *qemu_preload = getenv("QEMU_SET_ENV"); u8 *afl_preload = getenv("AFL_PRELOAD"); @@ -1029,10 +1027,10 @@ int main(int argc, char **argv_orig, char **envp) { case 'Q': - if (qemu_mode) FATAL("Multiple -Q options not supported"); + if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported"); if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU; - qemu_mode = 1; + fsrv->qemu_mode = 1; break; case 'U': @@ -1046,7 +1044,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'W': /* Wine+QEMU mode */ if (use_wine) FATAL("Multiple -W options not supported"); - qemu_mode = 1; + fsrv->qemu_mode = 1; use_wine = 1; if (!mem_limit_given) fsrv->mem_limit = 0; @@ -1107,7 +1105,7 @@ int main(int argc, char **argv_orig, char **envp) { find_binary(fsrv, argv[optind]); detect_file_args(argv + optind, fsrv->out_file, &fsrv->use_stdin); - if (qemu_mode) { + if (fsrv->qemu_mode) { if (use_wine) use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind, @@ -1133,7 +1131,7 @@ int main(int argc, char **argv_orig, char **envp) { read_initial_file(); - afl_fsrv_start(fsrv, use_argv, &stop_soon); + afl_fsrv_start(fsrv, use_argv, &stop_soon, get_afl_env("AFL_DEBUG_CHILD_OUTPUT")? 1 :0); ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : ""); -- cgit 1.4.1 From ee4e1936d0d1ca18147d1916e9365578627584e2 Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 12 Apr 2020 13:20:10 +0100 Subject: build on arm64 fix. tested on Android. (#313) --- include/afl-fuzz.h | 1 + include/forkserver.h | 5 +++-- src/afl-analyze.c | 4 ++-- src/afl-common.c | 25 +++++++++++++------------ src/afl-forkserver.c | 1 + src/afl-fuzz-bitmap.c | 10 +++++----- src/afl-fuzz-init.c | 12 ++++++------ src/afl-fuzz-one.c | 4 ++-- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-stats.c | 26 +++++++++++++------------- src/afl-fuzz.c | 12 ++++++------ src/afl-showmap.c | 2 +- src/afl-tmin.c | 4 ++-- 13 files changed, 56 insertions(+), 52 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 1440b645..58fe7c41 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -61,6 +61,7 @@ #include #include #include +#include #include #include diff --git a/include/forkserver.h b/include/forkserver.h index 444f92df..77fcc126 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -29,6 +29,7 @@ #define __AFL_FORKSERVER_H #include +#include typedef struct afl_forkserver { @@ -97,9 +98,9 @@ void afl_fsrv_killall(); #endif #ifdef RLIMIT_AS -#define MSG_ULIMIT_USAGE " ( ulimit -Sv $[%llu << 10];" +#define MSG_ULIMIT_USAGE " ( ulimit -Sv $[%" PRIu64 " << 10];" #else -#define MSG_ULIMIT_USAGE " ( ulimit -Sd $[%llu << 10];" +#define MSG_ULIMIT_USAGE " ( ulimit -Sd $[%" PRIu64 " << 10];" #endif /* ^RLIMIT_AS */ #endif diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 66dbefab..951e2f76 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -909,7 +909,7 @@ int main(int argc, char **argv, char **envp) { } - if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%" PRIu64 "%c", &mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); @@ -1013,7 +1013,7 @@ int main(int argc, char **argv, char **envp) { read_initial_file(); - ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", + ACTF("Performing dry run (mem limit = %" PRIu64 " MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); run_target(use_argv, in_data, in_len, 1); diff --git a/src/afl-common.c b/src/afl-common.c index 7eba6ae4..d8af353a 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "debug.h" #include "alloc-inl.h" @@ -454,13 +455,13 @@ u8 *stringify_int(u8 *buf, size_t len, u64 val) { } while (0) /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); + CHK_FORMAT(1, 10000, "%" PRIu64, u64); /* 10.0k - 99.9k */ CHK_FORMAT(1000, 99.95, "%0.01fk", double); /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); + CHK_FORMAT(1000, 1000, "%" PRIu64 "k", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); @@ -469,7 +470,7 @@ u8 *stringify_int(u8 *buf, size_t len, u64 val) { CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); + CHK_FORMAT(1000 * 1000, 1000, "%" PRIu64 "M", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); @@ -521,13 +522,13 @@ u8 *stringify_float(u8 *buf, size_t len, double val) { u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); + CHK_FORMAT(1, 10000, "%" PRIu64 " B", u64); /* 10.0k - 99.9k */ CHK_FORMAT(1024, 99.95, "%0.01f kB", double); /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); + CHK_FORMAT(1024, 1000, "%" PRIu64 " kB", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); @@ -536,7 +537,7 @@ u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); + CHK_FORMAT(1024 * 1024, 1000, "%" PRIu64 " MB", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); @@ -614,13 +615,13 @@ u8 *u_stringify_int(u8 *buf, u64 val) { } while (0) /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu", u64); + CHK_FORMAT(1, 10000, "%" PRIu64, u64); /* 10.0k - 99.9k */ CHK_FORMAT(1000, 99.95, "%0.01fk", double); /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%lluk", u64); + CHK_FORMAT(1000, 1000, "%" PRIu64 "k", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); @@ -629,7 +630,7 @@ u8 *u_stringify_int(u8 *buf, u64 val) { CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); + CHK_FORMAT(1000 * 1000, 1000, "%" PRIu64 "M", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); @@ -680,13 +681,13 @@ u8 *u_stringify_float(u8 *buf, double val) { u8 *u_stringify_mem_size(u8 *buf, u64 val) { /* 0-9999 */ - CHK_FORMAT(1, 10000, "%llu B", u64); + CHK_FORMAT(1, 10000, "%" PRIu64 " B", u64); /* 10.0k - 99.9k */ CHK_FORMAT(1024, 99.95, "%0.01f kB", double); /* 100k - 999k */ - CHK_FORMAT(1024, 1000, "%llu kB", u64); + CHK_FORMAT(1024, 1000, "%" PRIu64 " kB", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); @@ -695,7 +696,7 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val) { CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); + CHK_FORMAT(1024 * 1024, 1000, "%" PRIu64 " MB", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index a7067791..8b504584 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index b6a494db..293102a8 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -441,7 +441,7 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) { sprintf(ret, "src:%06u", afl->current_entry); - sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time); + sprintf(ret + strlen(ret), ",time:%" PRIu64, get_cur_time() - afl->start_time); if (afl->splicing_with >= 0) sprintf(ret + strlen(ret), "+%06d", afl->splicing_with); @@ -659,12 +659,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/hangs/id:%06" PRIu64 ",%s", afl->out_dir, afl->unique_hangs, describe_op(afl, 0)); #else - snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/hangs/id_%06" PRIu64, afl->out_dir, afl->unique_hangs); #endif /* ^!SIMPLE_FILES */ @@ -703,12 +703,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/crashes/id:%06" PRIu64 ",sig:%02u,%s", afl->out_dir, afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); #else - snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/crashes/id_%06" PRIu64 "_%02u", afl->out_dir, afl->unique_crashes, afl->kill_signal); #endif /* ^!SIMPLE_FILES */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 54cc81ef..85b98173 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -494,7 +494,7 @@ void perform_dry_run(afl_state_t *afl) { if (afl->stop_soon) return; if (res == afl->crash_mode || res == FAULT_NOBITS) - SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, + SAYF(cGRA " len = %u, map size = %u, exec speed = %" PRIu64 " us\n" cRST, q->len, q->bitmap_size, q->exec_us); switch (res) { @@ -1051,8 +1051,8 @@ static void handle_existing_out_dir(afl_state_t *afl) { u64 start_time2, last_update; if (fscanf(f, - "start_time : %llu\n" - "last_update : %llu\n", + "start_time : %" PRIu64 "\n" + "last_update : %" PRIu64 "\n", &start_time2, &last_update) != 2) FATAL("Malformed data in '%s'", fn); @@ -1602,7 +1602,7 @@ void check_cpu_governor(afl_state_t *afl) { if (f) { - if (fscanf(f, "%llu", &min) != 1) min = 0; + if (fscanf(f, "%" PRIu64, &min) != 1) min = 0; fclose(f); } @@ -1611,7 +1611,7 @@ void check_cpu_governor(afl_state_t *afl) { if (f) { - if (fscanf(f, "%llu", &max) != 1) max = 0; + if (fscanf(f, "%" PRIu64, &max) != 1) max = 0; fclose(f); } @@ -1620,7 +1620,7 @@ void check_cpu_governor(afl_state_t *afl) { SAYF("\n" cLRD "[-] " cRST "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" - " between %llu and %llu MHz. Unfortunately, the scaling algorithm in " + " between %" PRIu64 " and %" PRIu64 " MHz. Unfortunately, the scaling algorithm in " "the\n" " kernel is imperfect and can miss the short-lived processes spawned " "by\n" diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 80567160..01ce37fb 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -405,7 +405,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(afl->not_on_tty)) { - ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", + ACTF("Fuzzing test case #%u (%u total, %" PRIu64 " uniq crashes found)...", afl->current_entry, afl->queued_paths, afl->unique_crashes); fflush(stdout); @@ -2432,7 +2432,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (afl->not_on_tty) { - ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", + ACTF("Fuzzing test case #%u (%u total, %" PRIu64 " uniq crashes found)...", afl->current_entry, afl->queued_paths, afl->unique_crashes); fflush(stdout); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 4c98d788..f8440f46 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -89,7 +89,7 @@ u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { "Unable to communicate with fork server. Some possible reasons:\n\n" " - You've run out of memory. Use -m to increase the the memory " "limit\n" - " to something higher than %lld.\n" + " to something higher than %" PRIu64 ".\n" " - The binary or one of the libraries it uses manages to " "create\n" " threads before the forkserver initializes.\n" diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 2e680dbb..0df950dd 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -70,13 +70,13 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, fprintf( f, - "start_time : %llu\n" - "last_update : %llu\n" - "run_time : %llu\n" + "start_time : %" PRIu64 "\n" + "last_update : %lld\n" + "run_time : %lld\n" "fuzzer_pid : %d\n" - "cycles_done : %llu\n" - "cycles_wo_finds : %llu\n" - "execs_done : %llu\n" + "cycles_done : %" PRIu64 "\n" + "cycles_wo_finds : %" PRIu64 "\n" + "execs_done : %" PRIu64 "\n" "execs_per_sec : %0.02f\n" // "real_execs_per_sec: %0.02f\n" // damn the name is too long "paths_total : %u\n" @@ -90,12 +90,12 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "variable_paths : %u\n" "stability : %0.02f%%\n" "bitmap_cvg : %0.02f%%\n" - "unique_crashes : %llu\n" - "unique_hangs : %llu\n" - "last_path : %llu\n" - "last_crash : %llu\n" - "last_hang : %llu\n" - "execs_since_crash : %llu\n" + "unique_crashes : %" PRIu64 "\n" + "unique_hangs : %" PRIu64 "\n" + "last_path : %" PRIu64 "\n" + "last_crash : %" PRIu64 "\n" + "last_hang : %" PRIu64 "\n" + "execs_since_crash : %" PRIu64 "\n" "exec_timeout : %u\n" "slowest_exec_ms : %u\n" "peak_rss_mb : %lu\n" @@ -171,7 +171,7 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { execs_per_sec */ fprintf(afl->fsrv.plot_file, - "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f\n", + "%" PRIu64 ", %" PRIu64 ", %u, %u, %u, %u, %0.02f%%, %" PRIu64 ", %" PRIu64 ", %u, %0.02f\n", get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 73a38215..9464dacc 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -427,7 +427,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%" PRIu64 "%c", &afl->fsrv.mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); @@ -537,7 +537,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'V': { afl->most_time_key = 1; - if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') + if (sscanf(optarg, "%" PRIu64, &afl->most_time) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -V"); } break; @@ -545,7 +545,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'E': { afl->most_execs_key = 1; - if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') + if (sscanf(optarg, "%" PRIu64, &afl->most_execs) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -E"); } break; @@ -556,7 +556,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->limit_time_sig = 1; afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT; - if (sscanf(optarg, "%llu", &afl->limit_time_puppet) < 1 || + if (sscanf(optarg, "%" PRIu64, &afl->limit_time_puppet) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -L"); @@ -566,7 +566,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("limit_time overflow"); afl->limit_time_puppet = limit_time_puppet2; - SAYF("limit_time_puppet %llu\n", afl->limit_time_puppet); + SAYF("limit_time_puppet %" PRIu64 "\n", afl->limit_time_puppet); afl->swarm_now = 0; if (afl->limit_time_puppet == 0) afl->key_puppet = 1; @@ -1079,7 +1079,7 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->not_on_tty)) { - ACTF("Entering queue cycle %llu.", afl->queue_cycle); + ACTF("Entering queue cycle %" PRIu64 ".", afl->queue_cycle); fflush(stdout); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index c84fa36c..6c2b2000 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -720,7 +720,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%" PRIu64 "%c", &fsrv->mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 3be6b2c0..fd081fcf 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -989,7 +989,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%" PRIu64 "%c", &fsrv->mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); @@ -1134,7 +1134,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_start(fsrv, use_argv, &stop_soon, get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0); - ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", + ACTF("Performing dry run (mem limit = %" PRIu64 " MB, timeout = %u ms%s)...", fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : ""); run_target(fsrv, use_argv, in_data, in_len, 1); -- cgit 1.4.1 From 79195454993b6cfff6b03354dbf1e045e77f83cb Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Sun, 12 Apr 2020 15:55:52 +0100 Subject: Better solution for ARM64 build fix (#315) --- include/afl-fuzz.h | 1 - include/forkserver.h | 5 ++--- include/types.h | 2 +- src/afl-analyze.c | 4 ++-- src/afl-common.c | 25 ++++++++++++------------- src/afl-forkserver.c | 1 - src/afl-fuzz-bitmap.c | 10 +++++----- src/afl-fuzz-init.c | 12 ++++++------ src/afl-fuzz-one.c | 4 ++-- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-stats.c | 26 +++++++++++++------------- src/afl-fuzz.c | 12 ++++++------ src/afl-showmap.c | 2 +- src/afl-tmin.c | 4 ++-- 14 files changed, 53 insertions(+), 57 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 58fe7c41..1440b645 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -61,7 +61,6 @@ #include #include #include -#include #include #include diff --git a/include/forkserver.h b/include/forkserver.h index 77fcc126..444f92df 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -29,7 +29,6 @@ #define __AFL_FORKSERVER_H #include -#include typedef struct afl_forkserver { @@ -98,9 +97,9 @@ void afl_fsrv_killall(); #endif #ifdef RLIMIT_AS -#define MSG_ULIMIT_USAGE " ( ulimit -Sv $[%" PRIu64 " << 10];" +#define MSG_ULIMIT_USAGE " ( ulimit -Sv $[%llu << 10];" #else -#define MSG_ULIMIT_USAGE " ( ulimit -Sd $[%" PRIu64 " << 10];" +#define MSG_ULIMIT_USAGE " ( ulimit -Sd $[%llu << 10];" #endif /* ^RLIMIT_AS */ #endif diff --git a/include/types.h b/include/types.h index da95cb39..f2a12953 100644 --- a/include/types.h +++ b/include/types.h @@ -46,7 +46,7 @@ typedef uint32_t u32; */ -#ifdef __x86_64__ +#if defined(__x86_64__) || defined(__aarch64__) typedef unsigned long long u64; #else typedef uint64_t u64; diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 951e2f76..66dbefab 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -909,7 +909,7 @@ int main(int argc, char **argv, char **envp) { } - if (sscanf(optarg, "%" PRIu64 "%c", &mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); @@ -1013,7 +1013,7 @@ int main(int argc, char **argv, char **envp) { read_initial_file(); - ACTF("Performing dry run (mem limit = %" PRIu64 " MB, timeout = %u ms%s)...", + ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); run_target(use_argv, in_data, in_len, 1); diff --git a/src/afl-common.c b/src/afl-common.c index d8af353a..7eba6ae4 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -26,7 +26,6 @@ #include #include #include -#include #include "debug.h" #include "alloc-inl.h" @@ -455,13 +454,13 @@ u8 *stringify_int(u8 *buf, size_t len, u64 val) { } while (0) /* 0-9999 */ - CHK_FORMAT(1, 10000, "%" PRIu64, u64); + CHK_FORMAT(1, 10000, "%llu", u64); /* 10.0k - 99.9k */ CHK_FORMAT(1000, 99.95, "%0.01fk", double); /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%" PRIu64 "k", u64); + CHK_FORMAT(1000, 1000, "%lluk", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); @@ -470,7 +469,7 @@ u8 *stringify_int(u8 *buf, size_t len, u64 val) { CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%" PRIu64 "M", u64); + CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); @@ -522,13 +521,13 @@ u8 *stringify_float(u8 *buf, size_t len, double val) { u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { /* 0-9999 */ - CHK_FORMAT(1, 10000, "%" PRIu64 " B", u64); + 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, "%" PRIu64 " kB", u64); + CHK_FORMAT(1024, 1000, "%llu kB", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); @@ -537,7 +536,7 @@ u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) { CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%" PRIu64 " MB", u64); + CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); @@ -615,13 +614,13 @@ u8 *u_stringify_int(u8 *buf, u64 val) { } while (0) /* 0-9999 */ - CHK_FORMAT(1, 10000, "%" PRIu64, u64); + CHK_FORMAT(1, 10000, "%llu", u64); /* 10.0k - 99.9k */ CHK_FORMAT(1000, 99.95, "%0.01fk", double); /* 100k - 999k */ - CHK_FORMAT(1000, 1000, "%" PRIu64 "k", u64); + CHK_FORMAT(1000, 1000, "%lluk", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double); @@ -630,7 +629,7 @@ u8 *u_stringify_int(u8 *buf, u64 val) { CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double); /* 100M - 999M */ - CHK_FORMAT(1000 * 1000, 1000, "%" PRIu64 "M", u64); + CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double); @@ -681,13 +680,13 @@ u8 *u_stringify_float(u8 *buf, double val) { u8 *u_stringify_mem_size(u8 *buf, u64 val) { /* 0-9999 */ - CHK_FORMAT(1, 10000, "%" PRIu64 " B", u64); + 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, "%" PRIu64 " kB", u64); + CHK_FORMAT(1024, 1000, "%llu kB", u64); /* 1.00M - 9.99M */ CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double); @@ -696,7 +695,7 @@ u8 *u_stringify_mem_size(u8 *buf, u64 val) { CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double); /* 100M - 999M */ - CHK_FORMAT(1024 * 1024, 1000, "%" PRIu64 " MB", u64); + CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64); /* 1.00G - 9.99G */ CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double); diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 8b504584..a7067791 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -38,7 +38,6 @@ #include #include #include -#include #include #include #include diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 293102a8..b6a494db 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -441,7 +441,7 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) { sprintf(ret, "src:%06u", afl->current_entry); - sprintf(ret + strlen(ret), ",time:%" PRIu64, get_cur_time() - afl->start_time); + sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time); if (afl->splicing_with >= 0) sprintf(ret + strlen(ret), "+%06d", afl->splicing_with); @@ -659,12 +659,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/hangs/id:%06" PRIu64 ",%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir, afl->unique_hangs, describe_op(afl, 0)); #else - snprintf(fn, PATH_MAX, "%s/hangs/id_%06" PRIu64, afl->out_dir, + snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs); #endif /* ^!SIMPLE_FILES */ @@ -703,12 +703,12 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES - snprintf(fn, PATH_MAX, "%s/crashes/id:%06" PRIu64 ",sig:%02u,%s", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); #else - snprintf(fn, PATH_MAX, "%s/crashes/id_%06" PRIu64 "_%02u", afl->out_dir, + snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, afl->unique_crashes, afl->kill_signal); #endif /* ^!SIMPLE_FILES */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 85b98173..54cc81ef 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -494,7 +494,7 @@ void perform_dry_run(afl_state_t *afl) { if (afl->stop_soon) return; if (res == afl->crash_mode || res == FAULT_NOBITS) - SAYF(cGRA " len = %u, map size = %u, exec speed = %" PRIu64 " us\n" cRST, + SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, q->len, q->bitmap_size, q->exec_us); switch (res) { @@ -1051,8 +1051,8 @@ static void handle_existing_out_dir(afl_state_t *afl) { u64 start_time2, last_update; if (fscanf(f, - "start_time : %" PRIu64 "\n" - "last_update : %" PRIu64 "\n", + "start_time : %llu\n" + "last_update : %llu\n", &start_time2, &last_update) != 2) FATAL("Malformed data in '%s'", fn); @@ -1602,7 +1602,7 @@ void check_cpu_governor(afl_state_t *afl) { if (f) { - if (fscanf(f, "%" PRIu64, &min) != 1) min = 0; + if (fscanf(f, "%llu", &min) != 1) min = 0; fclose(f); } @@ -1611,7 +1611,7 @@ void check_cpu_governor(afl_state_t *afl) { if (f) { - if (fscanf(f, "%" PRIu64, &max) != 1) max = 0; + if (fscanf(f, "%llu", &max) != 1) max = 0; fclose(f); } @@ -1620,7 +1620,7 @@ void check_cpu_governor(afl_state_t *afl) { SAYF("\n" cLRD "[-] " cRST "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" - " between %" PRIu64 " and %" PRIu64 " MHz. Unfortunately, the scaling algorithm in " + " between %llu and %llu MHz. Unfortunately, the scaling algorithm in " "the\n" " kernel is imperfect and can miss the short-lived processes spawned " "by\n" diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 01ce37fb..80567160 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -405,7 +405,7 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(afl->not_on_tty)) { - ACTF("Fuzzing test case #%u (%u total, %" PRIu64 " uniq crashes found)...", + ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", afl->current_entry, afl->queued_paths, afl->unique_crashes); fflush(stdout); @@ -2432,7 +2432,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (afl->not_on_tty) { - ACTF("Fuzzing test case #%u (%u total, %" PRIu64 " uniq crashes found)...", + ACTF("Fuzzing test case #%u (%u total, %llu uniq crashes found)...", afl->current_entry, afl->queued_paths, afl->unique_crashes); fflush(stdout); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index f8440f46..4c98d788 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -89,7 +89,7 @@ u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { "Unable to communicate with fork server. Some possible reasons:\n\n" " - You've run out of memory. Use -m to increase the the memory " "limit\n" - " to something higher than %" PRIu64 ".\n" + " to something higher than %lld.\n" " - The binary or one of the libraries it uses manages to " "create\n" " threads before the forkserver initializes.\n" diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 0df950dd..2e680dbb 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -70,13 +70,13 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, fprintf( f, - "start_time : %" PRIu64 "\n" - "last_update : %lld\n" - "run_time : %lld\n" + "start_time : %llu\n" + "last_update : %llu\n" + "run_time : %llu\n" "fuzzer_pid : %d\n" - "cycles_done : %" PRIu64 "\n" - "cycles_wo_finds : %" PRIu64 "\n" - "execs_done : %" PRIu64 "\n" + "cycles_done : %llu\n" + "cycles_wo_finds : %llu\n" + "execs_done : %llu\n" "execs_per_sec : %0.02f\n" // "real_execs_per_sec: %0.02f\n" // damn the name is too long "paths_total : %u\n" @@ -90,12 +90,12 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "variable_paths : %u\n" "stability : %0.02f%%\n" "bitmap_cvg : %0.02f%%\n" - "unique_crashes : %" PRIu64 "\n" - "unique_hangs : %" PRIu64 "\n" - "last_path : %" PRIu64 "\n" - "last_crash : %" PRIu64 "\n" - "last_hang : %" PRIu64 "\n" - "execs_since_crash : %" PRIu64 "\n" + "unique_crashes : %llu\n" + "unique_hangs : %llu\n" + "last_path : %llu\n" + "last_crash : %llu\n" + "last_hang : %llu\n" + "execs_since_crash : %llu\n" "exec_timeout : %u\n" "slowest_exec_ms : %u\n" "peak_rss_mb : %lu\n" @@ -171,7 +171,7 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { execs_per_sec */ fprintf(afl->fsrv.plot_file, - "%" PRIu64 ", %" PRIu64 ", %u, %u, %u, %u, %0.02f%%, %" PRIu64 ", %" PRIu64 ", %u, %0.02f\n", + "%llu, %llu, %u, %u, %u, %u, %0.02f%%, %llu, %llu, %u, %0.02f\n", get_cur_time() / 1000, afl->queue_cycle - 1, afl->current_entry, afl->queued_paths, afl->pending_not_fuzzed, afl->pending_favored, bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->max_depth, diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9464dacc..73a38215 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -427,7 +427,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (sscanf(optarg, "%" PRIu64 "%c", &afl->fsrv.mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); @@ -537,7 +537,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'V': { afl->most_time_key = 1; - if (sscanf(optarg, "%" PRIu64, &afl->most_time) < 1 || optarg[0] == '-') + if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -V"); } break; @@ -545,7 +545,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'E': { afl->most_execs_key = 1; - if (sscanf(optarg, "%" PRIu64, &afl->most_execs) < 1 || optarg[0] == '-') + if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -E"); } break; @@ -556,7 +556,7 @@ int main(int argc, char **argv_orig, char **envp) { afl->limit_time_sig = 1; afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT; - if (sscanf(optarg, "%" PRIu64, &afl->limit_time_puppet) < 1 || + if (sscanf(optarg, "%llu", &afl->limit_time_puppet) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -L"); @@ -566,7 +566,7 @@ int main(int argc, char **argv_orig, char **envp) { FATAL("limit_time overflow"); afl->limit_time_puppet = limit_time_puppet2; - SAYF("limit_time_puppet %" PRIu64 "\n", afl->limit_time_puppet); + SAYF("limit_time_puppet %llu\n", afl->limit_time_puppet); afl->swarm_now = 0; if (afl->limit_time_puppet == 0) afl->key_puppet = 1; @@ -1079,7 +1079,7 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->not_on_tty)) { - ACTF("Entering queue cycle %" PRIu64 ".", afl->queue_cycle); + ACTF("Entering queue cycle %llu.", afl->queue_cycle); fflush(stdout); } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 6c2b2000..c84fa36c 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -720,7 +720,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (sscanf(optarg, "%" PRIu64 "%c", &fsrv->mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index fd081fcf..3be6b2c0 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -989,7 +989,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (sscanf(optarg, "%" PRIu64 "%c", &fsrv->mem_limit, &suffix) < 1 || + if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || optarg[0] == '-') FATAL("Bad syntax used for -m"); @@ -1134,7 +1134,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_start(fsrv, use_argv, &stop_soon, get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0); - ACTF("Performing dry run (mem limit = %" PRIu64 " MB, timeout = %u ms%s)...", + ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : ""); run_target(fsrv, use_argv, in_data, in_len, 1); -- cgit 1.4.1 From 326ab632c378878c96f44586a6e1f3dfa3db2276 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 13 Apr 2020 16:57:19 +0200 Subject: fixed uaf and warnings --- src/afl-analyze.c | 8 ++++++++ src/afl-common.c | 11 +++++++---- src/afl-forkserver.c | 1 - src/afl-fuzz-bitmap.c | 8 ++++---- src/afl-fuzz-extras.c | 2 ++ src/afl-fuzz-init.c | 2 ++ src/afl-fuzz-one.c | 3 --- src/afl-fuzz-queue.c | 2 ++ src/afl-fuzz-redqueen.c | 8 +++++++- src/afl-fuzz-stats.c | 1 - src/afl-sharedmem.c | 10 +--------- src/afl-showmap.c | 2 +- 12 files changed, 34 insertions(+), 24 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 510ec94a..2c98982f 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -902,6 +902,12 @@ int main(int argc, char **argv, char **envp) { if (mem_limit_given) FATAL("Multiple -m options not supported"); mem_limit_given = 1; + if (!optarg) { + + FATAL("Bad syntax used for -m"); + + } + if (!strcmp(optarg, "none")) { mem_limit = 0; @@ -938,6 +944,8 @@ int main(int argc, char **argv, char **envp) { if (timeout_given) FATAL("Multiple -t options not supported"); timeout_given = 1; + if (!optarg) FATAL("Wrong usage of -t"); + exec_tmout = atoi(optarg); if (exec_tmout < 10 || optarg[0] == '-') diff --git a/src/afl-common.c b/src/afl-common.c index 7eba6ae4..1ac1a2f3 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -292,11 +292,10 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { *rsl = 0; cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - if (!access(cp, X_OK)) { + if (cp && !access(cp, X_OK)) { - if (cp != NULL) ck_free(cp); + ck_free(cp); cp = alloc_printf("%s/afl-wine-trace", own_copy); @@ -309,10 +308,14 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } - } else + ck_free(own_copy); + + } else { ck_free(own_copy); + } + u8 *ncp = BIN_PATH "/afl-qemu-trace"; if (!access(ncp, X_OK)) { diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index b282a119..b054a64d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -455,7 +455,6 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - len = status; offset = 0; while (offset < status && (u8)dict[offset] + offset < status) { diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index b6a494db..9603f2f5 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -535,7 +535,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(len == 0)) return 0; u8 *queue_fn = ""; - u8 hnb; + u8 hnb = '\0'; s32 fd; u8 keeping = 0, res; @@ -718,9 +718,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { // if the user wants to be informed on new crashes - do that #if !TARGET_OS_IPHONE - if (system(afl->infoexec) == -1) - hnb += 0; // we dont care if system errors, but we dont want a - // compiler warning either + // we dont care if system errors, but we dont want a + // compiler warning either + (void)(system(afl->infoexec)+1); #else WARNF("command execution unsupported"); #endif diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index 55146dd9..c366cc5b 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -130,6 +130,8 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr); + if (!wptr) PFATAL("no mem for data"); + while (*lptr) { char *hexdigits = "0123456789abcdef"; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 54cc81ef..10417da6 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2178,6 +2178,8 @@ void save_cmdline(afl_state_t *afl, u32 argc, char **argv) { u32 l = strlen(argv[i]); + if (!argv[i] || !buf) FATAL("null deref detected"); + memcpy(buf, argv[i], l); buf += l; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 95d622f2..475c710b 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3593,7 +3593,6 @@ pacemaker_fuzzing: } s32 temp_len_puppet; - cur_ms_lv = get_cur_time(); // for (; afl->swarm_now < swarm_num; ++afl->swarm_now) { @@ -4167,8 +4166,6 @@ pacemaker_fuzzing: afl->orig_hit_cnt_puppet))) { afl->key_puppet = 0; - cur_ms_lv = get_cur_time(); - new_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->orig_hit_cnt_puppet = 0; afl->last_limit_time_start = 0; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 346c2639..5eb110d0 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -438,6 +438,8 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { } + if (unlikely(!n_paths)) FATAL("Queue state corrupt"); + fuzz_mu = fuzz_total / n_paths; if (fuzz <= fuzz_mu) { diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 517f8d7c..b9b41c74 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -115,7 +115,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { afl->stage_short = "colorization"; afl->stage_max = 1000; - struct range *rng; + struct range *rng = NULL; afl->stage_cur = 0; while ((rng = pop_biggest_range(&ranges)) != NULL && afl->stage_cur < afl->stage_max) { @@ -141,6 +141,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { empty_range: ck_free(rng); + rng = NULL; ++afl->stage_cur; } @@ -157,6 +158,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { rng = ranges; ranges = ranges->next; ck_free(rng); + rng = NULL; } @@ -186,6 +188,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { } + return 0; checksum_fail: @@ -196,9 +199,12 @@ checksum_fail: rng = ranges; ranges = ranges->next; ck_free(rng); + rng = NULL; } + // TODO: clang notices a _potential_ leak of mem pointed to by rng + return 1; } diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 2e680dbb..d42df2db 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -56,7 +56,6 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, bitmap_cvg = afl->last_bitmap_cvg; stability = afl->last_stability; - eps = afl->last_eps; } else { diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index 9db84e77..eea1cc95 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -67,6 +67,7 @@ list_t shm_list = {.element_prealloc_count = 0}; void afl_shm_deinit(sharedmem_t *shm) { + // TODO: clang reports a potential UAF in this function/makro(?) list_remove(&shm_list, shm); #ifdef USEMMAP @@ -93,14 +94,6 @@ void afl_shm_deinit(sharedmem_t *shm) { } -/* At exit, remove all leftover maps */ - -void afl_shm_atexit(void) { - - LIST_FOREACH(&shm_list, sharedmem_t, { afl_shm_deinit(el); }); - -} - /* Configure shared memory. Returns a pointer to shm->map for ease of use. */ @@ -207,7 +200,6 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { #endif list_append(&shm_list, shm); - atexit(afl_shm_atexit); return shm->map; diff --git a/src/afl-showmap.c b/src/afl-showmap.c index c84fa36c..63c8caa8 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -983,7 +983,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!quiet_mode) OKF("Processed %u input files.", total_execs); closedir(dir_in); - closedir(dir_out); + if (dir_out) closedir(dir_out); } else { -- cgit 1.4.1 From 6dc36f1e6e7d2d781cc6b14f2898b3f7021e1d06 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 14 Apr 2020 19:27:25 +0200 Subject: unified forkservered run_target, fixes #308 --- include/afl-fuzz.h | 16 +----- include/forkserver.h | 21 ++++++-- src/afl-analyze.c | 2 +- src/afl-forkserver.c | 132 +++++++++++++++++++++++++++++++++++++++++++++--- src/afl-fuzz-bitmap.c | 16 +++--- src/afl-fuzz-cmplog.c | 2 +- src/afl-fuzz-init.c | 14 ++--- src/afl-fuzz-mutators.c | 2 +- src/afl-fuzz-one.c | 12 ++--- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-redqueen.c | 4 +- src/afl-fuzz-run.c | 128 +++------------------------------------------- src/afl-fuzz-stats.c | 18 +++---- src/afl-fuzz.c | 2 +- src/afl-sharedmem.c | 1 - src/afl-showmap.c | 95 ++++------------------------------ src/afl-tmin.c | 109 ++++++++------------------------------- 17 files changed, 222 insertions(+), 354 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 3df99a58..abaa71b5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -195,18 +195,6 @@ enum { }; -/* Execution status fault codes */ - -enum { - - /* 00 */ FAULT_NONE, - /* 01 */ FAULT_TMOUT, - /* 02 */ FAULT_CRASH, - /* 03 */ FAULT_ERROR, - /* 04 */ FAULT_NOINST, - /* 05 */ FAULT_NOBITS - -}; #define operator_num 16 #define swarm_num 5 @@ -433,7 +421,6 @@ typedef struct afl_state { use_splicing, /* Recombine input files? */ dumb_mode, /* Run in non-instrumented mode? */ score_changed, /* Scoring for favorites changed? */ - kill_signal, /* Signal that killed the child */ resuming_fuzz, /* Resuming an older fuzzing job? */ timeout_given, /* Specific timeout given? */ not_on_tty, /* stdout is not a tty */ @@ -488,7 +475,6 @@ typedef struct afl_state { total_tmouts, /* Total number of timeouts */ unique_tmouts, /* Timeouts with unique signatures */ unique_hangs, /* Hangs with unique signatures */ - total_execs, /* Total execve() calls */ last_crash_execs, /* Exec counter at last crash */ queue_cycle, /* Queue round counter */ cycles_wo_finds, /* Cycles without any new paths */ @@ -888,7 +874,7 @@ void show_init_stats(afl_state_t *); /* Run */ -u8 run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); +fsrv_run_result_t run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); void write_to_testcase(afl_state_t *, void *, u32); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); void sync_fuzzers(afl_state_t *); diff --git a/include/forkserver.h b/include/forkserver.h index 6fbaf612..7559e785 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -29,6 +29,7 @@ #define __AFL_FORKSERVER_H #include +#include typedef struct afl_forkserver { @@ -55,16 +56,18 @@ typedef struct afl_forkserver { u32 snapshot; /* is snapshot feature used */ u64 mem_limit; /* Memory cap for child (MB) */ + u64 total_execs; /* How often run_target was called */ + u8 *out_file, /* File to fuzz, if any */ *target_path; /* Path of the target */ FILE *plot_file; /* Gnuplot output file */ - u8 child_timed_out; /* Traced process timed out? */ + u8 last_run_timed_out; /* Traced process timed out? */ - u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ + u8 last_kill_signal; /* Signal that killed the child */ - u32 prev_timed_out; /* if prev forkserver run timed out */ + u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ u8 qemu_mode; /* if running in qemu mode or not */ @@ -79,10 +82,22 @@ typedef struct afl_forkserver { } afl_forkserver_t; +typedef enum fsrv_run_result { + + /* 00 */ FSRV_RUN_OK = 0, + /* 01 */ FSRV_RUN_TMOUT, + /* 02 */ FSRV_RUN_CRASH, + /* 03 */ FSRV_RUN_ERROR, + /* 04 */ FSRV_RUN_NOINST, + /* 05 */ FSRV_RUN_NOBITS, + +} fsrv_run_result_t; + void afl_fsrv_init(afl_forkserver_t *fsrv); void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from); void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output); +fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, volatile u8 *stop_soon_p); void afl_fsrv_killall(void); void afl_fsrv_deinit(afl_forkserver_t *fsrv); diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 952786b0..8625cfda 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -80,7 +80,7 @@ static u8 edges_only, /* Ignore hit counts? */ use_stdin = 1; /* Use stdin for program input? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ - child_timed_out; /* Child timed out? */ + child_timed_out; /* Child timed out? */ static u8 *target_path; static u8 qemu_mode; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index f647ff5d..a7be8e8b 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -76,7 +76,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->child_pid = -1; fsrv->map_size = MAP_SIZE; fsrv->use_fauxsrv = 0; - fsrv->prev_timed_out = 0; + fsrv->last_run_timed_out = 0; fsrv->init_child_func = fsrv_exec_child; @@ -102,7 +102,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->out_dir_fd = -1; fsrv_to->child_pid = -1; fsrv_to->use_fauxsrv = 0; - fsrv_to->prev_timed_out = 0; + fsrv_to->last_run_timed_out = 0; fsrv_to->init_child_func = fsrv_exec_child; @@ -217,7 +217,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); - fsrv->child_timed_out = 0; + fsrv->last_run_timed_out = 0; fsrv->fsrv_pid = fork(); if (fsrv->fsrv_pid < 0) PFATAL("fork() failed"); @@ -361,7 +361,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } else if (time > fsrv->exec_tmout * FORK_WAIT_MULT) { - fsrv->child_timed_out = 1; + fsrv->last_run_timed_out = 1; kill(fsrv->fsrv_pid, SIGKILL); } else { @@ -476,7 +476,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if (fsrv->child_timed_out) + if (fsrv->last_run_timed_out) FATAL("Timeout while initializing fork server (adjusting -t may help)"); if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed"); @@ -640,6 +640,127 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) { } +/* Execute target application, monitoring for timeouts. Return status + information. The called program will update afl->fsrv->trace_bits. */ + +fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, volatile u8 *stop_soon_p) { + + s32 res; + u32 exec_ms; + + int status = 0; + + u32 timeout = fsrv->exec_tmout; + + /* After this memset, fsrv->trace_bits[] are effectively volatile, so we + must prevent any earlier operations from venturing into that + territory. */ + + memset(fsrv->trace_bits, 0, fsrv->map_size); + + MEM_BARRIER(); + + /* we have the fork server (or faux server) up and running + First, tell it if the previous run timed out. */ + + if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) { + + if (*stop_soon_p) return 0; + RPFATAL(res, "Unable to request new process from fork server (OOM?)"); + + } + + fsrv->last_run_timed_out = 0; + + if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { + + if (stop_soon_p) return 0; + RPFATAL(res, "Unable to request new process from fork server (OOM?)"); + + } + + if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); + + exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p); + + if (exec_ms > timeout) { + + /* If there was no response from forkserver after timeout seconds, + we kill the child. The forkserver should inform us afterwards */ + + kill(fsrv->child_pid, SIGKILL); + fsrv->last_run_timed_out = 1; + if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0; + + } + + if (!exec_ms) { + + if (*stop_soon_p) return 0; + SAYF("\n" cLRD "[-] " cRST + "Unable to communicate with fork server. Some possible reasons:\n\n" + " - You've run out of memory. Use -m to increase the the memory " + "limit\n" + " to something higher than %lld.\n" + " - The binary or one of the libraries it uses manages to " + "create\n" + " threads before the forkserver initializes.\n" + " - The binary, at least in some circumstances, exits in a way " + "that\n" + " also kills the parent process - raise() could be the " + "culprit.\n" + " - If using persistent mode with QEMU, " + "AFL_QEMU_PERSISTENT_ADDR " + "is\n" + " probably not valid (hint: add the base address in case of " + "PIE)" + "\n\n" + "If all else fails you can disable the fork server via " + "AFL_NO_FORKSRV=1.\n", + fsrv->mem_limit); + RPFATAL(res, "Unable to communicate with fork server"); + + } + + if (!WIFSTOPPED(status)) fsrv->child_pid = 0; + + fsrv->total_execs++; + + /* Any subsequent operations on fsrv->trace_bits must not be moved by the + compiler below this point. Past this location, fsrv->trace_bits[] + behave very normally and do not have to be treated as volatile. */ + + MEM_BARRIER(); + + /* Report outcome to caller. */ + + if (WIFSIGNALED(status) && !*stop_soon_p) { + + fsrv->last_kill_signal = WTERMSIG(status); + + if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) + return FSRV_RUN_TMOUT; + + return FSRV_RUN_CRASH; + + } + + /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and + must use a special exit code. */ + + if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { + + fsrv->last_kill_signal = 0; + return FSRV_RUN_CRASH; + + } + + if ((*(u32 *)fsrv->trace_bits) == EXEC_FAIL_SIG) return FSRV_RUN_NOINST; + + return FSRV_RUN_OK; + +} + void afl_fsrv_killall() { LIST_FOREACH(&fsrv_list, afl_forkserver_t, { @@ -656,4 +777,3 @@ void afl_fsrv_deinit(afl_forkserver_t *fsrv) { list_remove(&fsrv_list, fsrv); } - diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index a0a720fa..66b1e60d 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -598,7 +598,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0); - if (unlikely(res == FAULT_ERROR)) + if (unlikely(res == FSRV_RUN_ERROR)) FATAL("Unable to execute target application"); fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); @@ -612,7 +612,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { switch (fault) { - case FAULT_TMOUT: + case FSRV_RUN_TMOUT: /* Timeouts are not very interesting, but we're still obliged to keep a handful of samples. We use the presence of new bits in the @@ -651,9 +651,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { timeout actually uncovers a crash. Make sure we don't discard it if so. */ - if (!afl->stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash; + if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) goto keep_as_crash; - if (afl->stop_soon || new_fault != FAULT_TMOUT) return keeping; + if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) return keeping; } @@ -675,7 +675,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { break; - case FAULT_CRASH: + case FSRV_RUN_CRASH: keep_as_crash: @@ -704,7 +704,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #ifndef SIMPLE_FILES snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir, - afl->unique_crashes, afl->kill_signal, describe_op(afl, 0)); + afl->unique_crashes, afl->fsrv.last_kill_signal, describe_op(afl, 0)); #else @@ -730,11 +730,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { } afl->last_crash_time = get_cur_time(); - afl->last_crash_execs = afl->total_execs; + afl->last_crash_execs = afl->fsrv.total_execs; break; - case FAULT_ERROR: FATAL("Unable to execute target application"); + case FSRV_RUN_ERROR: FATAL("Unable to execute target application"); default: return keeping; diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index e2747097..ab93d838 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -66,7 +66,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { if (afl->stop_soon) return 1; - if (fault == FAULT_TMOUT) { + if (fault == FSRV_RUN_TMOUT) { if (afl->subseq_tmouts++ > TMOUT_LIMIT) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 10417da6..55f7ce53 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -493,13 +493,13 @@ void perform_dry_run(afl_state_t *afl) { if (afl->stop_soon) return; - if (res == afl->crash_mode || res == FAULT_NOBITS) + if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, q->len, q->bitmap_size, q->exec_us); switch (res) { - case FAULT_NONE: + case FSRV_RUN_OK: if (q == afl->queue) check_map_coverage(afl); @@ -507,7 +507,7 @@ void perform_dry_run(afl_state_t *afl) { break; - case FAULT_TMOUT: + case FSRV_RUN_TMOUT: if (afl->timeout_given) { @@ -556,7 +556,7 @@ void perform_dry_run(afl_state_t *afl) { } - case FAULT_CRASH: + case FSRV_RUN_CRASH: if (afl->crash_mode) break; @@ -650,13 +650,13 @@ void perform_dry_run(afl_state_t *afl) { FATAL("Test case '%s' results in a crash", fn); - case FAULT_ERROR: + case FSRV_RUN_ERROR: FATAL("Unable to execute target application ('%s')", afl->argv[0]); - case FAULT_NOINST: FATAL("No instrumentation detected"); + case FSRV_RUN_NOINST: FATAL("No instrumentation detected"); - case FAULT_NOBITS: + case FSRV_RUN_NOBITS: ++afl->useless_at_start; diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index efb1c117..7bf23e84 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -242,7 +242,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; - if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; } + if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 961a29d6..cc97654a 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -442,14 +442,14 @@ u8 fuzz_one_original(afl_state_t *afl) { if (unlikely(afl->queue_cur->cal_failed)) { - u8 res = FAULT_TMOUT; + u8 res = FSRV_RUN_TMOUT; if (afl->queue_cur->cal_failed < CAL_CHANCES) { res = calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0); - if (unlikely(res == FAULT_ERROR)) + if (unlikely(res == FSRV_RUN_ERROR)) FATAL("Unable to execute target application"); } @@ -471,7 +471,7 @@ u8 fuzz_one_original(afl_state_t *afl) { u8 res = trim_case(afl, afl->queue_cur, in_buf); - if (unlikely(res == FAULT_ERROR)) + if (unlikely(res == FSRV_RUN_ERROR)) FATAL("Unable to execute target application"); if (unlikely(afl->stop_soon)) { @@ -2469,14 +2469,14 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (afl->queue_cur->cal_failed) { - u8 res = FAULT_TMOUT; + u8 res = FSRV_RUN_TMOUT; if (afl->queue_cur->cal_failed < CAL_CHANCES) { res = calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0); - if (res == FAULT_ERROR) FATAL("Unable to execute target application"); + if (res == FSRV_RUN_ERROR) FATAL("Unable to execute target application"); } @@ -2497,7 +2497,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u8 res = trim_case(afl, afl->queue_cur, in_buf); - if (res == FAULT_ERROR) FATAL("Unable to execute target application"); + if (res == FSRV_RUN_ERROR) FATAL("Unable to execute target application"); if (afl->stop_soon) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 5eb110d0..d05eee08 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -492,7 +492,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { // the more often fuzz result paths are equal to this queue entry, // reduce its value perf_score *= - (1 - (double)((double)q->n_fuzz / (double)afl->total_execs)); + (1 - (double)((double)q->n_fuzz / (double)afl->fsrv.total_execs)); break; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 6a01ec89..8cea01e8 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -622,7 +622,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1; u64 orig_hit_cnt, new_hit_cnt; - u64 orig_execs = afl->total_execs; + u64 orig_execs = afl->fsrv.total_execs; orig_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_name = "input-to-state"; @@ -670,7 +670,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, exit_its: new_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt; - afl->stage_cycles[STAGE_ITS] += afl->total_execs - orig_execs; + afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs; memcpy(orig_buf, buf, len); diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 514ba9ef..b20c5436 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -32,95 +32,9 @@ /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { +fsrv_run_result_t run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { - s32 res; - u32 exec_ms; - - int status = 0; - u32 tb4; - - fsrv->child_timed_out = 0; - - /* After this memset, fsrv->trace_bits[] are effectively volatile, so we - must prevent any earlier operations from venturing into that - territory. */ - - memset(fsrv->trace_bits, 0, fsrv->map_size); - - MEM_BARRIER(); - - /* we have the fork server (or faux server) up and running, so simply - tell it to have at it, and then read back PID. */ - - if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) { - - if (afl->stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { - - if (afl->stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - - exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, &afl->stop_soon); - - if (exec_ms > timeout) { - - /* If there was no response from forkserver after timeout seconds, - we kill the child. The forkserver should inform us afterwards */ - - kill(fsrv->child_pid, SIGKILL); - fsrv->child_timed_out = 1; - if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0; - - } - - if (!exec_ms) { - - if (afl->stop_soon) return 0; - SAYF("\n" cLRD "[-] " cRST - "Unable to communicate with fork server. Some possible reasons:\n\n" - " - You've run out of memory. Use -m to increase the the memory " - "limit\n" - " to something higher than %lld.\n" - " - The binary or one of the libraries it uses manages to " - "create\n" - " threads before the forkserver initializes.\n" - " - The binary, at least in some circumstances, exits in a way " - "that\n" - " also kills the parent process - raise() could be the " - "culprit.\n" - " - If using persistent mode with QEMU, " - "AFL_QEMU_PERSISTENT_ADDR " - "is\n" - " probably not valid (hint: add the base address in case of " - "PIE)" - "\n\n" - "If all else fails you can disable the fork server via " - "AFL_NO_FORKSRV=1.\n", - fsrv->mem_limit); - RPFATAL(res, "Unable to communicate with fork server"); - - } - - if (!WIFSTOPPED(status)) fsrv->child_pid = 0; - - ++afl->total_execs; - - /* Any subsequent operations on fsrv->trace_bits must not be moved by the - compiler below this point. Past this location, fsrv->trace_bits[] - behave very normally and do not have to be treated as volatile. */ - - MEM_BARRIER(); - - tb4 = *(u32 *)fsrv->trace_bits; + fsrv_run_result_t res = afl_fsrv_run_target(&afl->fsrv, &afl->stop_soon); #ifdef WORD_SIZE_64 classify_counts(afl, (u64 *)fsrv->trace_bits); @@ -128,35 +42,7 @@ u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { classify_counts(afl, (u32 *)fsrv->trace_bits); #endif /* ^WORD_SIZE_64 */ - fsrv->prev_timed_out = fsrv->child_timed_out; - - /* Report outcome to caller. */ - - if (WIFSIGNALED(status) && !afl->stop_soon) { - - afl->kill_signal = WTERMSIG(status); - - if (fsrv->child_timed_out && afl->kill_signal == SIGKILL) - return FAULT_TMOUT; - - return FAULT_CRASH; - - } - - /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and - must use a special exit code. */ - - if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) { - - afl->kill_signal = 0; - return FAULT_CRASH; - - } - - if ((afl->dumb_mode == 1 || afl->no_forkserver) && tb4 == EXEC_FAIL_SIG) - return FAULT_ERROR; - - return FAULT_NONE; + return res; } @@ -348,7 +234,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (!afl->dumb_mode && !afl->stage_cur && !count_bytes(afl, afl->fsrv.trace_bits)) { - fault = FAULT_NOINST; + fault = FSRV_RUN_NOINST; goto abort_calibration; } @@ -408,7 +294,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, parent. This is a non-critical problem, but something to warn the user about. */ - if (!afl->dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS; + if (!afl->dumb_mode && first_run && !fault && !new_bits) fault = FSRV_RUN_NOBITS; abort_calibration: @@ -645,7 +531,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; - if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming; + if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming; /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ @@ -753,7 +639,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { if (afl->stop_soon) return 1; - if (fault == FAULT_TMOUT) { + if (fault == FSRV_RUN_TMOUT) { if (afl->subseq_tmouts++ > TMOUT_LIMIT) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index d48dd5e3..52148dc2 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -108,14 +108,14 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, afl->start_time / 1000, cur_time / 1000, (cur_time - afl->start_time) / 1000, getpid(), afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds, - afl->total_execs, - afl->total_execs / ((double)(get_cur_time() - afl->start_time) / 1000), + afl->fsrv.total_execs, + afl->fsrv.total_execs / ((double)(get_cur_time() - afl->start_time) / 1000), afl->queued_paths, afl->queued_favored, afl->queued_discovered, afl->queued_imported, afl->max_depth, afl->current_entry, afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable, stability, bitmap_cvg, afl->unique_crashes, afl->unique_hangs, afl->last_path_time / 1000, afl->last_crash_time / 1000, - afl->last_hang_time / 1000, afl->total_execs - afl->last_crash_execs, + afl->last_hang_time / 1000, afl->fsrv.total_execs - afl->last_crash_execs, afl->fsrv.exec_tmout, afl->slowest_exec_ms, #ifdef __APPLE__ (unsigned long int)(rus.ru_maxrss >> 20), @@ -227,7 +227,7 @@ void show_stats(afl_state_t *afl) { if (afl->most_execs_key == 1) { - if (afl->most_execs <= afl->total_execs) { + if (afl->most_execs <= afl->fsrv.total_execs) { afl->most_execs_key = 2; afl->stop_soon = 2; @@ -251,11 +251,11 @@ void show_stats(afl_state_t *afl) { if (!afl->stats_last_execs) { afl->stats_avg_exec = - ((double)afl->total_execs) * 1000 / (cur_ms - afl->start_time); + ((double)afl->fsrv.total_execs) * 1000 / (cur_ms - afl->start_time); } else { - double cur_avg = ((double)(afl->total_execs - afl->stats_last_execs)) * + double cur_avg = ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) * 1000 / (cur_ms - afl->stats_last_ms); /* If there is a dramatic (5x+) jump in speed, reset the indicator @@ -270,7 +270,7 @@ void show_stats(afl_state_t *afl) { } afl->stats_last_ms = cur_ms; - afl->stats_last_execs = afl->total_execs; + afl->stats_last_execs = afl->fsrv.total_execs; /* Tell the callers when to contact us (as measured in execs). */ @@ -543,14 +543,14 @@ void show_stats(afl_state_t *afl) { SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP " new crashes : %s%-22s" bSTG bV "\n", - u_stringify_int(IB(0), afl->total_execs), + u_stringify_int(IB(0), afl->fsrv.total_execs), afl->unique_crashes ? cLRD : cRST, tmp); } else { SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP " total crashes : %s%-22s" bSTG bV "\n", - u_stringify_int(IB(0), afl->total_execs), + u_stringify_int(IB(0), afl->fsrv.total_execs), afl->unique_crashes ? cLRD : cRST, tmp); } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 07067691..9f17b61b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -480,7 +480,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'C': /* crash mode */ if (afl->crash_mode) FATAL("Multiple -C options not supported"); - afl->crash_mode = FAULT_CRASH; + afl->crash_mode = FSRV_RUN_CRASH; break; case 'n': /* dumb mode */ diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index eea1cc95..16d6fe41 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -40,7 +40,6 @@ #include #include -#include #include #include #include diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 3fcc1d2b..5f622c25 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -69,7 +69,7 @@ static u8 *in_data; /* Input data */ static u32 total, highest; /* tuple content information */ static u32 in_len, /* Input data length */ - arg_offset, total_execs; /* Total number of execs */ + arg_offset; /* Total number of execs */ static u8 quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ @@ -193,7 +193,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { if (cmin_mode) { - if (fsrv->child_timed_out) break; + if (fsrv->last_run_timed_out) break; if (!caa && child_crashed != cco) break; fprintf(f, "%u%u\n", fsrv->trace_bits[i], i); @@ -233,75 +233,18 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) { } -/* Execute target application. Returns 0 if the changes are a dud, or - 1 if they should be kept. */ +/* Execute target application. */ -static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, +void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len) { - struct itimerval it; - int status = 0; - - memset(fsrv->trace_bits, 0, MAP_SIZE); - MEM_BARRIER(); - write_to_testcase(fsrv, mem, len); - s32 res; - - /* we have the fork server up and running, so simply - tell it to have at it, and then read back PID. */ - - if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - - /* Configure timeout, wait for child, cancel timeout. */ - - if (fsrv->exec_tmout) { - - it.it_value.tv_sec = (fsrv->exec_tmout / 1000); - it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000; - - } - - setitimer(ITIMER_REAL, &it, NULL); - - if ((res = read(fsrv->fsrv_st_fd, &status, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to communicate with fork server (OOM?)"); - - } - - fsrv->child_pid = 0; - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - - setitimer(ITIMER_REAL, &it, NULL); - - MEM_BARRIER(); - - /* Clean up bitmap, analyze exit condition, etc. */ - - if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) - FATAL("Unable to execute '%s'", argv[0]); + fsrv_run_result_t res = afl_fsrv_run_target(fsrv, &stop_soon); + if (res == FSRV_RUN_NOINST || res == FSRV_RUN_ERROR) FATAL("Error running target"); classify_counts(fsrv->trace_bits, binary_mode ? count_class_binary : count_class_human); - total_execs++; if (stop_soon) { @@ -310,22 +253,6 @@ static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, } - /* Always discard inputs that time out. */ - - if (fsrv->child_timed_out) { return 0; } - - /* Handle crashing inputs depending on current mode. */ - - if (WIFSIGNALED(status) || - (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) || - (WIFEXITED(status) && WEXITSTATUS(status))) { - - return 0; - - } - - return 0; - } /* Read initial file. */ @@ -425,7 +352,7 @@ static void run_target(afl_forkserver_t *fsrv, char **argv) { if (fsrv->exec_tmout) { - fsrv->child_timed_out = 0; + fsrv->last_run_timed_out = 0; it.it_value.tv_sec = (fsrv->exec_tmout / 1000); it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000; @@ -452,12 +379,12 @@ static void run_target(afl_forkserver_t *fsrv, char **argv) { if (!quiet_mode) SAYF(cRST "-- Program output ends --\n"); - if (!fsrv->child_timed_out && !stop_soon && WIFSIGNALED(status)) + if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) child_crashed = 1; if (!quiet_mode) { - if (fsrv->child_timed_out) + if (fsrv->last_run_timed_out) SAYF(cLRD "\n+++ Program timed off +++\n" cRST); else if (stop_soon) SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST); @@ -980,7 +907,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!quiet_mode) OKF("Processed %u input files.", total_execs); + if (!quiet_mode) OKF("Processed %llu input files.", fsrv->total_execs); closedir(dir_in); if (dir_out) closedir(dir_out); @@ -1010,7 +937,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_shm_deinit(&shm); - u32 ret = child_crashed * 2 + fsrv->child_timed_out; + u32 ret = child_crashed * 2 + fsrv->last_run_timed_out; if (fsrv->target_path) ck_free(fsrv->target_path); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 31fad1df..999d5f65 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -67,7 +67,6 @@ static u8 *in_data; /* Input data for trimming */ static u32 in_len, /* Input data length */ orig_cksum, /* Original checksum */ - 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 */ @@ -249,69 +248,11 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) { static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, u8 first_run) { - struct itimerval it; - int status = 0; - - u32 cksum; - - fsrv->child_timed_out = 0; - - memset(fsrv->trace_bits, 0, fsrv->map_size); - MEM_BARRIER(); - write_to_testcase(fsrv, mem, len); - s32 res; - - /* we have the fork server up and running, so simply - tell it to have at it, and then read back PID. */ - - if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to request new process from fork server (OOM?)"); - - } - - if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - - /* Configure timeout, wait for child, cancel timeout. */ - - if (fsrv->exec_tmout) { - - it.it_value.tv_sec = (fsrv->exec_tmout / 1000); - it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000; - - } - - setitimer(ITIMER_REAL, &it, NULL); + fsrv_run_result_t ret = afl_fsrv_run_target(fsrv, &stop_soon); - if ((res = read(fsrv->fsrv_st_fd, &status, 4)) != 4) { - - if (stop_soon) return 0; - RPFATAL(res, "Unable to communicate with fork server (OOM?)"); - - } - - fsrv->child_pid = 0; - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; - - setitimer(ITIMER_REAL, &it, NULL); - - MEM_BARRIER(); - - /* Clean up bitmap, analyze exit condition, etc. */ - - if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) - FATAL("Unable to execute '%s'", argv[0]); + if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child"); if (!hang_mode) { @@ -320,8 +261,6 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, } - total_execs++; - if (stop_soon) { SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST); @@ -334,25 +273,21 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, if (hang_mode) { - if (fsrv->child_timed_out) return 1; - - if (WIFSIGNALED(status) || - (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) || - (WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) { - + switch (ret) + { + case FSRV_RUN_TMOUT: + return 1; + case FSRV_RUN_CRASH: missed_crashes++; - - } else { - + return 0; + default: missed_hangs++; - + return 0; } - return 0; - } - if (fsrv->child_timed_out) { + if (ret == FSRV_RUN_TMOUT) { missed_hangs++; return 0; @@ -361,9 +296,7 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, /* Handle crashing inputs depending on current mode. */ - if (WIFSIGNALED(status) || - (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) || - (WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) { + if (ret == FSRV_RUN_CRASH) { if (first_run) crash_mode = 1; @@ -391,7 +324,9 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, } - cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST); + if (ret == FSRV_RUN_NOINST) FATAL("Binary not instrumented?"); + + u32 cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST); if (first_run) orig_cksum = cksum; @@ -640,11 +575,11 @@ finalize_all: SAYF("\n" cGRA " File size reduced by : " cRST "%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST - "%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA + "%0.02f%%\n" cGRA " Number of execs done : " cRST "%llu\n" cGRA " Fruitless execs : " cRST "termination=%u crash=%u\n\n", 100 - ((double)in_len) * 100 / orig_len, in_len, in_len == 1 ? "" : "s", - ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), total_execs, + ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), fsrv->total_execs, missed_paths, missed_crashes); return; @@ -652,13 +587,13 @@ finalize_all: SAYF("\n" cGRA " File size reduced by : " cRST "%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST - "%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA + "%0.02f%%\n" cGRA " Number of execs done : " cRST "%llu\n" cGRA " Fruitless execs : " cRST "path=%u crash=%u hang=%s%u\n\n", 100 - ((double)in_len) * 100 / orig_len, in_len, in_len == 1 ? "" : "s", - ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), total_execs, + ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), fsrv->total_execs, missed_paths, missed_crashes, missed_hangs ? cLRD : "", missed_hangs); - if (total_execs > 50 && missed_hangs * 10 > total_execs && !hang_mode) + if (fsrv->total_execs > 50 && missed_hangs * 10 > fsrv->total_execs && !hang_mode) WARNF(cLRD "Frequent timeouts - results may be skewed." cRST); } @@ -1139,13 +1074,13 @@ int main(int argc, char **argv_orig, char **envp) { run_target(fsrv, use_argv, in_data, in_len, 1); - if (hang_mode && !fsrv->child_timed_out) + if (hang_mode && !fsrv->last_run_timed_out) FATAL( "Target binary did not time out but hang minimization mode " "(-H) was set (-t %u).", fsrv->exec_tmout); - if (fsrv->child_timed_out && !hang_mode) + if (fsrv->last_run_timed_out && !hang_mode) FATAL( "Target binary times out (adjusting -t may help). Use -H to minimize a " "hang."); -- cgit 1.4.1 From c961925356bf3388066969b9975b424c4cdae890 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 17 Apr 2020 07:10:42 +0200 Subject: fix plot_data output and code-format --- docs/Changelog.md | 5 ++++- src/afl-fuzz-init.c | 2 ++ src/afl-fuzz-python.c | 2 +- src/afl-fuzz-run.c | 2 +- src/afl-fuzz-stats.c | 31 ++++++++++++++++--------------- src/afl-showmap.c | 4 ++-- src/afl-tmin.c | 2 +- 7 files changed, 27 insertions(+), 21 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index e1e558b7..60d83508 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -19,14 +19,17 @@ sending a mail to . - snapshot feature usage now visible in UI - Now setting "-L -1" will enable MOpt in parallel to normal mutation. Additionally this allows to run dictionaries, radamsa and cmplog. + - fix for cmplog/redqueen mode if stdin was used + - fix for writing a better plot_data file + - qemu_mode: fix for persistent mode - compare-transform/AFL_LLVM_LAF_TRANSFORM_COMPARES now transforms also static global and local variable comparisons (cannot find all though) - extended forkserver: map_size and more information is communicated to afl-fuzz (and afl-fuzz acts accordingly) - - more refactoring - if AFL_CC/AFL_CXX is set but empty afl compilers did fail, fixed (this bug is in vanilla afl too) - added NO_PYTHON flag to disable python support when building afl-fuzz + - more refactoring ### Version ++2.63c (release): diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 55f7ce53..7131ceed 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1419,6 +1419,8 @@ void setup_dirs_fds(afl_state_t *afl) { "# unix_time, cycles_done, cur_path, paths_total, " "pending_total, pending_favs, map_size, unique_crashes, " "unique_hangs, max_depth, execs_per_sec\n"); + fflush(afl->fsrv.plot_file); + /* ignore errors */ } diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 33f01797..d4519c6d 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -42,7 +42,7 @@ it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */ &((py_mutator_t *)py_mutator)->name##_size static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, - u8 *add_buf, size_t add_buf_size, size_t max_size) { + u8 *add_buf, size_t add_buf_size, size_t max_size) { size_t mutated_size; PyObject *py_args, *py_value; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 6ad6444a..30ba0e65 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -34,7 +34,7 @@ information. The called program will update afl->fsrv->trace_bits. */ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, - u32 timeout) { + u32 timeout) { fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); // TODO: Don't classify for faults? diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 7cc9b920..c507b7f7 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -145,14 +145,15 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { - if (afl->plot_prev_qp == afl->queued_paths && - afl->plot_prev_pf == afl->pending_favored && - afl->plot_prev_pnf == afl->pending_not_fuzzed && - afl->plot_prev_ce == afl->current_entry && - afl->plot_prev_qc == afl->queue_cycle && - afl->plot_prev_uc == afl->unique_crashes && - afl->plot_prev_uh == afl->unique_hangs && - afl->plot_prev_md == afl->max_depth) + if (unlikely(afl->plot_prev_qp == afl->queued_paths && + afl->plot_prev_pf == afl->pending_favored && + afl->plot_prev_pnf == afl->pending_not_fuzzed && + afl->plot_prev_ce == afl->current_entry && + afl->plot_prev_qc == afl->queue_cycle && + afl->plot_prev_uc == afl->unique_crashes && + afl->plot_prev_uh == afl->unique_hangs && + afl->plot_prev_md == afl->max_depth) || + unlikely(!afl->queue_cycle)) return; afl->plot_prev_qp = afl->queued_paths; @@ -388,9 +389,9 @@ void show_stats(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->dumb_mode) { @@ -472,9 +473,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -504,9 +505,9 @@ void show_stats(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); @@ -580,7 +581,7 @@ void show_stats(afl_state_t *afl) { /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 61c1754f..f43beb1b 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -218,8 +218,8 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { /* Execute target application. */ -static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, - u32 len) { +static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv, + u8 *mem, u32 len) { afl_fsrv_write_to_testcase(fsrv, mem, len); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 431ff0c4..0a462e9a 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -215,7 +215,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { 1 if they should be kept. */ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, - u8 first_run) { + u8 first_run) { afl_fsrv_write_to_testcase(fsrv, mem, len); -- cgit 1.4.1 From 5b70d23211ddeddfb4d1dfce29a50234d08e9502 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 17 Apr 2020 09:10:49 +0200 Subject: added AFL_MAP_SIZE (wip) --- docs/Changelog.md | 1 + include/afl-fuzz.h | 2 ++ include/config.h | 3 +-- include/forkserver.h | 2 +- src/afl-analyze.c | 22 ++++++++++++++++------ src/afl-common.c | 2 +- src/afl-forkserver.c | 21 +++++++++++++-------- src/afl-fuzz-bitmap.c | 16 +--------------- src/afl-fuzz-init.c | 19 ------------------- src/afl-fuzz-queue.c | 9 +++++---- src/afl-fuzz-state.c | 24 +++++++++++++++++++++++- src/afl-fuzz.c | 12 +++++++----- src/afl-gcc.c | 8 ++++++++ src/afl-showmap.c | 24 ++++++++++++++++++------ src/afl-tmin.c | 27 +++++++++++++++++++-------- 15 files changed, 116 insertions(+), 76 deletions(-) (limited to 'src/afl-fuzz-init.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 60d83508..3ad80b7b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,6 +26,7 @@ sending a mail to . static global and local variable comparisons (cannot find all though) - extended forkserver: map_size and more information is communicated to afl-fuzz (and afl-fuzz acts accordingly) + - new environment variable: AFL_MAP_SIZE to specify the size of the shared map - if AFL_CC/AFL_CXX is set but empty afl compilers did fail, fixed (this bug is in vanilla afl too) - added NO_PYTHON flag to disable python support when building afl-fuzz diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 363776cb..88cacc4f 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -325,6 +325,8 @@ typedef struct afl_env_vars { *afl_python_module, *afl_path, *afl_hang_tmout, *afl_skip_crashes, *afl_preload; + uint32_t map_size; + } afl_env_vars_t; struct afl_pass_stat { diff --git a/include/config.h b/include/config.h index f0274fd3..fae97a42 100644 --- a/include/config.h +++ b/include/config.h @@ -407,8 +407,7 @@ #define FS_OPT_SNAPSHOT 0x20000000 #define FS_OPT_AUTODICT 0x10000000 #define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) -#define FS_OPT_SET_MAPSIZE(x) \ - (x <= 1 || x > MAP_SIZE || x > 0x1000000 ? 0 : ((x - 1) << 1)) +#define FS_OPT_SET_MAPSIZE(x) (x <= 1 || x > 0x1000000 ? 0 : ((x - 1) << 1)) #endif /* ! _HAVE_CONFIG_H */ diff --git a/include/forkserver.h b/include/forkserver.h index ac89b681..d76dfc7a 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -61,7 +61,7 @@ typedef struct afl_forkserver { u64 total_execs; /* How often run_target was called */ u8 *out_file, /* File to fuzz, if any */ - *target_path; /* Path of the target */ + *target_path; /* Path of the target */ FILE *plot_file; /* Gnuplot output file */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 6f946ed5..3d86efb1 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -84,6 +84,7 @@ static volatile u8 stop_soon, /* Ctrl-C pressed? */ static u8 *target_path; static u8 qemu_mode; +static u32 map_size = MAP_SIZE; /* Constants used for describing byte behavior. */ @@ -115,7 +116,7 @@ static u8 count_class_lookup[256] = { static void classify_counts(u8 *mem) { - u32 i = MAP_SIZE; + u32 i = map_size; if (edges_only) { @@ -144,7 +145,7 @@ static void classify_counts(u8 *mem) { static inline u8 anything_set(void) { u32 *ptr = (u32 *)trace_bits; - u32 i = (MAP_SIZE >> 2); + u32 i = (map_size >> 2); while (i--) if (*(ptr++)) return 1; @@ -217,7 +218,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { s32 prog_in_fd; u32 cksum; - memset(trace_bits, 0, MAP_SIZE); + memset(trace_bits, 0, map_size); MEM_BARRIER(); prog_in_fd = write_to_file(prog_in, mem, len); @@ -311,7 +312,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { } - cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST); + cksum = hash32(trace_bits, map_size, HASH_CONST); /* We don't actually care if the target is crashing or not, except that when it does, the checksum should be different. */ @@ -811,7 +812,7 @@ int main(int argc, char **argv, char **envp) { s32 opt; u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; - char **use_argv; + char **use_argv, *ptr; doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; @@ -931,12 +932,21 @@ int main(int argc, char **argv, char **envp) { if (optind == argc || !in_file) usage(argv[0]); + if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { + + map_size = atoi(ptr); + if (map_size < 8 || map_size > (1 << 29)) + FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size); + if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3); + + } + use_hex_offsets = !!get_afl_env("AFL_ANALYZE_HEX"); check_environment_vars(envp); sharedmem_t shm = {0}; - trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); + trace_bits = afl_shm_init(&shm, map_size, 0); atexit(at_exit_handler); setup_signal_handlers(); diff --git a/src/afl-common.c b/src/afl-common.c index c9f09d38..3210ee97 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -72,7 +72,7 @@ char *afl_environment_variables[] = { "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_X86", // not really an env but we dont want to warn on it - "AFL_PATH", "AFL_PERFORMANCE_FILE", + "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally "AFL_POST_LIBRARY", "AFL_PRELOAD", "AFL_PYTHON_MODULE", "AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE", diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 006764d9..9b915a7a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -407,21 +407,26 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { - fsrv->map_size = FS_OPT_GET_MAPSIZE(status); - if (unlikely(fsrv->map_size % 8)) { + u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); + + if (!fsrv->map_size) fsrv->map_size = MAP_SIZE; + + if (unlikely(tmp_map_size % 8)) { // should not happen - WARNF("Target reported non-aligned map size of %ud", fsrv->map_size); - fsrv->map_size = (((fsrv->map_size + 8) >> 3) << 3); + WARNF("Target reported non-aligned map size of %ud", tmp_map_size); + tmp_map_size = (((tmp_map_size + 8) >> 3) << 3); } - if (!be_quiet) ACTF("Target map size: %u", fsrv->map_size); - if (fsrv->map_size > MAP_SIZE) + if (!be_quiet) ACTF("Target map size: %u", tmp_map_size); + if (tmp_map_size > fsrv->map_size) FATAL( "Target's coverage map size of %u is larger than the one this " - "afl++ is compiled with (%u) (change MAP_SIZE and recompile)\n", - fsrv->map_size, MAP_SIZE); + "afl++ is set with (%u) (change MAP_SIZE_POW2 in config.h and " + "recompile or set AFL_MAP_SIZE)\n", + tmp_map_size, fsrv->map_size); + fsrv->map_size = tmp_map_size; } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index be8f504e..0823deed 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -43,7 +43,7 @@ void write_bitmap(afl_state_t *afl) { if (fd < 0) PFATAL("Unable to open '%s'", fname); - ck_write(fd, afl->virgin_bits, MAP_SIZE, fname); + ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname); close(fd); @@ -145,8 +145,6 @@ u32 count_bits(afl_state_t *afl, u8 *mem) { u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; - if (i == 0) i = 1; - while (i--) { u32 v = *(ptr++); @@ -181,8 +179,6 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) { u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; - if (i == 0) i = 1; - while (i--) { u32 v = *(ptr++); @@ -208,8 +204,6 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) { u32 i = (afl->fsrv.map_size >> 2); u32 ret = 0; - if (i == 0) i = 1; - while (i--) { u32 v = *(ptr++); @@ -246,8 +240,6 @@ void simplify_trace(afl_state_t *afl, u64 *mem) { u32 i = (afl->fsrv.map_size >> 3); - if (i == 0) i = 1; - while (i--) { /* Optimize for sparse bitmaps. */ @@ -281,8 +273,6 @@ void simplify_trace(afl_state_t *afl, u32 *mem) { u32 i = (afl->fsrv.map_size >> 2); - if (i == 0) i = 1; - while (i--) { /* Optimize for sparse bitmaps. */ @@ -347,8 +337,6 @@ void classify_counts(afl_forkserver_t *fsrv) { u32 i = (fsrv->map_size >> 3); - if (i == 0) i = 1; - while (i--) { /* Optimize for sparse bitmaps. */ @@ -378,8 +366,6 @@ void classify_counts(afl_forkserver_t *fsrv) { u32 i = (fsrv->map_size >> 2); - if (i == 0) i = 1; - while (i--) { /* Optimize for sparse bitmaps. */ diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7131ceed..3da348d2 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -442,23 +442,6 @@ void read_testcases(afl_state_t *afl) { } -/* Examine map coverage. Called once, for first test case. */ - -static void check_map_coverage(afl_state_t *afl) { - - u32 i; - - if (count_bytes(afl, afl->fsrv.trace_bits) < 100) return; - - for (i = (1 << (MAP_SIZE_POW2 - 1)); i < MAP_SIZE; ++i) - if (afl->fsrv.trace_bits[i]) return; - - if (afl->fsrv.map_size != MAP_SIZE) return; - - WARNF("Recompile binary with newer version of afl to improve coverage!"); - -} - /* Perform dry run of all test cases to confirm that the app is working as expected. This is done only for the initial inputs, and only once. */ @@ -501,8 +484,6 @@ void perform_dry_run(afl_state_t *afl) { case FSRV_RUN_OK: - if (q == afl->queue) check_map_coverage(afl); - if (afl->crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); break; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index d05eee08..373f12d8 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -249,7 +249,6 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { if (!q->trace_mini) { u32 len = (afl->fsrv.map_size >> 3); - if (len == 0) len = 1; q->trace_mini = ck_alloc(len); minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits); @@ -272,12 +271,12 @@ void cull_queue(afl_state_t *afl) { struct queue_entry *q; u32 len = (afl->fsrv.map_size >> 3); u32 i; - u8 temp_v[MAP_SIZE >> 3]; - - if (len == 0) len = 1; + u8 * temp_v; if (afl->dumb_mode || !afl->score_changed) return; + temp_v = ck_alloc(afl->fsrv.map_size >> 3); + afl->score_changed = 0; memset(temp_v, 255, len); @@ -325,6 +324,8 @@ void cull_queue(afl_state_t *afl) { } + ck_free(temp_v); + } /* Calculate case desirability score to adjust the length of havoc fuzzing. diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 7664c521..7d068258 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -99,7 +99,11 @@ void afl_state_init(afl_state_t *afl) { afl->fsrv.use_stdin = 1; - afl->fsrv.map_size = MAP_SIZE; + if (afl->afl_env.map_size > 8 && afl->afl_env.map_size <= (1 << 29)) + afl->fsrv.map_size = afl->afl_env.map_size; + else + afl->fsrv.map_size = MAP_SIZE; + afl->fsrv.function_opt = (u8 *)afl; afl->fsrv.function_ptr = &maybe_add_auto; @@ -324,6 +328,24 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_path = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_MAP_SIZE", + + afl_environment_variable_len) || + !strncmp(env, "AFL_MAPSIZE", + afl_environment_variable_len)) { + + afl->afl_env.map_size = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); + + if (afl->afl_env.map_size < 8 || afl->afl_env.map_size > (1 << 29)) + FATAL( + "the specified AFL_MAP_SIZE size is illegal and must be " + "between 2^3 and 2^30: %u\n", + afl->afl_env.map_size); + + if (afl->afl_env.map_size % 8) + afl->afl_env.map_size = (((afl->afl_env.map_size >> 3) + 1) << 3); + } else if (!strncmp(env, "AFL_PRELOAD", afl_environment_variable_len)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 925dbb1a..3cf57f86 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -249,6 +249,7 @@ int main(int argc, char **argv_orig, char **envp) { if (get_afl_env("AFL_DEBUG")) afl->debug = 1; read_afl_environment(afl, envp); + if (afl->afl_env.map_size) afl->fsrv.map_size = afl->afl_env.map_size; exit_1 = !!afl->afl_env.afl_bench_just_one; SAYF(cCYA "afl-fuzz" VERSION cRST @@ -476,7 +477,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->in_bitmap) FATAL("Multiple -B options not supported"); afl->in_bitmap = optarg; - read_bitmap(afl->in_bitmap, afl->virgin_bits, MAP_SIZE); + read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); break; case 'C': /* crash mode */ @@ -910,13 +911,14 @@ int main(int argc, char **argv_orig, char **envp) { check_crash_handling(); check_cpu_governor(afl); - afl->fsrv.trace_bits = afl_shm_init(&afl->shm, MAP_SIZE, afl->dumb_mode); + afl->fsrv.trace_bits = + afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->dumb_mode); setup_post(afl); - if (!afl->in_bitmap) memset(afl->virgin_bits, 255, MAP_SIZE); - memset(afl->virgin_tmout, 255, MAP_SIZE); - memset(afl->virgin_crash, 255, MAP_SIZE); + if (!afl->in_bitmap) memset(afl->virgin_bits, 255, afl->fsrv.map_size); + memset(afl->virgin_tmout, 255, afl->fsrv.map_size); + memset(afl->virgin_crash, 255, afl->fsrv.map_size); init_count_class16(); diff --git a/src/afl-gcc.c b/src/afl-gcc.c index 32cd36cb..86a88014 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -411,6 +411,14 @@ int main(int argc, char **argv) { } + u8 *ptr; + if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { + + u32 map_size = atoi(ptr); + if (map_size != MAP_SIZE) FATAL("AFL_MAP_SIZE is not supported by afl-gcc"); + + } + find_as(argv[0]); edit_params(argc, argv); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 21e18061..c1561b4c 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -72,6 +72,8 @@ static u32 total, highest; /* tuple content information */ static u32 in_len, /* Input data length */ arg_offset; /* Total number of execs */ +static u32 map_size = MAP_SIZE; + static u8 quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ raw_instr_output, /* Do not apply AFL filters */ @@ -112,7 +114,7 @@ static void classify_counts(afl_forkserver_t *fsrv) { u8 * mem = fsrv->trace_bits; const u8 *map = binary_mode ? count_class_binary : count_class_human; - u32 i = MAP_SIZE; + u32 i = map_size; if (edges_only) { @@ -175,10 +177,10 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { if (binary_mode) { - for (i = 0; i < MAP_SIZE; i++) + for (i = 0; i < map_size; i++) if (fsrv->trace_bits[i]) ret++; - ck_write(fd, fsrv->trace_bits, MAP_SIZE, outfile); + ck_write(fd, fsrv->trace_bits, map_size, outfile); close(fd); } else { @@ -187,7 +189,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { if (!f) PFATAL("fdopen() failed"); - for (i = 0; i < MAP_SIZE; i++) { + for (i = 0; i < map_size; i++) { if (!fsrv->trace_bits[i]) continue; ret++; @@ -535,7 +537,7 @@ int main(int argc, char **argv_orig, char **envp) { s32 opt, i; u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; u32 tcnt = 0; - char **use_argv; + char **use_argv, *ptr; char **argv = argv_cpy_dup(argc, argv_orig); @@ -543,6 +545,16 @@ int main(int argc, char **argv_orig, char **envp) { afl_forkserver_t *fsrv = &fsrv_var; afl_fsrv_init(fsrv); + if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { + + map_size = atoi(ptr); + if (map_size < 8 || map_size > (1 << 29)) + FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size); + if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3); + fsrv->map_size = map_size; + + } + doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; if (getenv("AFL_QUIET") != NULL) be_quiet = 1; @@ -715,7 +727,7 @@ int main(int argc, char **argv_orig, char **envp) { check_environment_vars(envp); sharedmem_t shm = {0}; - fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); + fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); setup_signal_handlers(); set_up_environment(fsrv); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 0a462e9a..e366d260 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -70,7 +70,8 @@ static u32 in_len, /* Input data length */ orig_cksum, /* Original checksum */ missed_hangs, /* Misses due to hangs */ missed_crashes, /* Misses due to crashes */ - missed_paths; /* Misses due to exec path diffs */ + missed_paths, /* Misses due to exec path diffs */ + map_size = MAP_SIZE; static u8 crash_mode, /* Crash-centric mode? */ hang_mode, /* Minimize as long as it hangs */ @@ -105,7 +106,7 @@ static const u8 count_class_lookup[256] = { static void apply_mask(u32 *mem, u32 *mask) { - u32 i = (MAP_SIZE >> 2); + u32 i = (map_size >> 2); if (!mask) return; @@ -122,7 +123,7 @@ static void apply_mask(u32 *mem, u32 *mask) { static void classify_counts(afl_forkserver_t *fsrv) { u8 *mem = fsrv->trace_bits; - u32 i = MAP_SIZE; + u32 i = map_size; if (edges_only) { @@ -151,7 +152,7 @@ static void classify_counts(afl_forkserver_t *fsrv) { static inline u8 anything_set(afl_forkserver_t *fsrv) { u32 *ptr = (u32 *)fsrv->trace_bits; - u32 i = (MAP_SIZE >> 2); + u32 i = (map_size >> 2); while (i--) if (*(ptr++)) return 1; @@ -755,7 +756,7 @@ int main(int argc, char **argv_orig, char **envp) { s32 opt; u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0; - char **use_argv; + char **use_argv, *ptr; char **argv = argv_cpy_dup(argc, argv_orig); @@ -763,6 +764,16 @@ int main(int argc, char **argv_orig, char **envp) { afl_forkserver_t *fsrv = &fsrv_var; afl_fsrv_init(fsrv); + if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { + + map_size = atoi(ptr); + if (map_size < 8 || map_size > (1 << 29)) + FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size); + if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3); + fsrv->map_size = map_size; + + } + doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); @@ -910,8 +921,8 @@ int main(int argc, char **argv_orig, char **envp) { to be useful. */ if (mask_bitmap) FATAL("Multiple -B options not supported"); - mask_bitmap = ck_alloc(MAP_SIZE); - read_bitmap(optarg, mask_bitmap, MAP_SIZE); + mask_bitmap = ck_alloc(map_size); + read_bitmap(optarg, mask_bitmap, map_size); break; case 'h': @@ -928,7 +939,7 @@ int main(int argc, char **argv_orig, char **envp) { check_environment_vars(envp); sharedmem_t shm = {0}; - fsrv->trace_bits = afl_shm_init(&shm, MAP_SIZE, 0); + fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); atexit(at_exit_handler); setup_signal_handlers(); -- cgit 1.4.1