diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-analyze.c | 15 | ||||
-rw-r--r-- | src/afl-cc.c | 6 | ||||
-rw-r--r-- | src/afl-common.c | 64 | ||||
-rw-r--r-- | src/afl-forkserver.c | 29 | ||||
-rw-r--r-- | src/afl-fuzz-bitmap.c | 5 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 41 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 30 | ||||
-rw-r--r-- | src/afl-fuzz-stats.c | 54 | ||||
-rw-r--r-- | src/afl-fuzz.c | 23 | ||||
-rw-r--r-- | src/afl-showmap.c | 37 | ||||
-rw-r--r-- | src/afl-tmin.c | 15 |
11 files changed, 232 insertions, 87 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c index e19df3ce..09b01541 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -120,6 +120,17 @@ static u8 count_class_lookup[256] = { #undef TIMES8 #undef TIMES4 +static void kill_child() { + + if (fsrv.child_pid > 0) { + + kill(fsrv.child_pid, fsrv.kill_signal); + fsrv.child_pid = -1; + + } + +} + static void classify_counts(u8 *mem) { u32 i = map_size; @@ -184,7 +195,7 @@ static void read_initial_file(void) { if (st.st_size >= TMIN_MAX_FILE) { - FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024); + FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024); } @@ -1053,6 +1064,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv.target_path = find_binary(argv[optind]); fsrv.trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, fsrv.out_file, &use_stdin); + signal(SIGALRM, kill_child); if (qemu_mode) { @@ -1093,6 +1105,7 @@ int main(int argc, char **argv_orig, char **envp) { parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL); read_initial_file(); + (void)check_binary_signatures(fsrv.target_path); ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); diff --git a/src/afl-cc.c b/src/afl-cc.c index e49addc4..77407a98 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1007,7 +1007,11 @@ static void edit_params(u32 argc, char **argv, char **envp) { } // prevent unnecessary build errors - cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + if (compiler_mode != GCC_PLUGIN && compiler_mode != GCC) { + + cc_params[cc_par_cnt++] = "-Wno-unused-command-line-argument"; + + } if (preprocessor_only || have_c) { diff --git a/src/afl-common.c b/src/afl-common.c index 9ca2b3e8..db19f0a7 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -25,8 +25,12 @@ #include <stdlib.h> #include <stdio.h> +#define _GNU_SOURCE +#define __USE_GNU +#include <string.h> #include <strings.h> #include <math.h> +#include <sys/mman.h> #include "debug.h" #include "alloc-inl.h" @@ -51,6 +55,66 @@ u8 last_intr = 0; #define AFL_PATH "/usr/local/lib/afl/" #endif +u32 check_binary_signatures(u8 *fn) { + + int ret = 0, fd = open(fn, O_RDONLY); + if (fd < 0) { PFATAL("Unable to open '%s'", fn); } + struct stat st; + if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); } + u32 f_len = st.st_size; + u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); + if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); } + close(fd); + + if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { + + if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); } + setenv(PERSIST_ENV_VAR, "1", 1); + ret = 1; + + } else if (getenv("AFL_PERSISTENT")) { + + if (!be_quiet) { + + WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); + + } + + } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) { + + if (!be_quiet) { + + OKF("FRIDA Persistent mode configuration options detected."); + + } + + setenv(PERSIST_ENV_VAR, "1", 1); + ret = 1; + + } + + if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) { + + if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); } + setenv(DEFER_ENV_VAR, "1", 1); + ret += 2; + + } else if (getenv("AFL_DEFER_FORKSRV")) { + + if (!be_quiet) { + + WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); + + } + + } + + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } + + return ret; + +} + void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) { u32 i = 0; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index c8c94c08..80b295e0 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -603,19 +603,31 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* Wait for the fork server to come up, but don't wait too long. */ rlen = 0; - if (fsrv->exec_tmout) { + if (fsrv->init_tmout) { u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout, stop_soon_p); if (!time_ms) { - kill(fsrv->fsrv_pid, fsrv->kill_signal); + s32 tmp_pid = fsrv->fsrv_pid; + if (tmp_pid > 0) { + + kill(tmp_pid, fsrv->kill_signal); + fsrv->fsrv_pid = -1; + + } } else if (time_ms > fsrv->init_tmout) { fsrv->last_run_timed_out = 1; - kill(fsrv->fsrv_pid, fsrv->kill_signal); + s32 tmp_pid = fsrv->fsrv_pid; + if (tmp_pid > 0) { + + kill(tmp_pid, fsrv->kill_signal); + fsrv->fsrv_pid = -1; + + } } else { @@ -1248,7 +1260,14 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 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, fsrv->kill_signal); + s32 tmp_pid = fsrv->child_pid; + if (tmp_pid > 0) { + + kill(tmp_pid, fsrv->kill_signal); + fsrv->child_pid = -1; + + } + fsrv->last_run_timed_out = 1; if (read(fsrv->fsrv_st_fd, &fsrv->child_status, 4) < 4) { exec_ms = 0; } @@ -1282,7 +1301,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = 0; } + if (!WIFSTOPPED(fsrv->child_status)) { fsrv->child_pid = -1; } fsrv->total_execs++; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0ae4d607..316067e4 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -317,8 +317,9 @@ u8 *describe_op(afl_state_t *afl, u8 new_bits, size_t max_description_len) { } - sprintf(ret + strlen(ret), ",time:%llu", - get_cur_time() + afl->prev_run_time - afl->start_time); + sprintf(ret + strlen(ret), ",time:%llu,execs:%llu", + get_cur_time() + afl->prev_run_time - afl->start_time, + afl->fsrv.total_execs); if (afl->current_custom_fuzz && afl->current_custom_fuzz->afl_custom_describe) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 9bb25785..1170715f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1325,8 +1325,8 @@ void pivot_inputs(afl_state_t *afl) { } - nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", afl->out_dir, id, - use_name); + nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s", + afl->out_dir, id, afl->fsrv.total_execs, use_name); #else @@ -2815,43 +2815,6 @@ void check_binary(afl_state_t *afl, u8 *fname) { } -/* Trim and possibly create a banner for the run. */ - -void fix_up_banner(afl_state_t *afl, u8 *name) { - - if (!afl->use_banner) { - - if (afl->sync_id) { - - afl->use_banner = afl->sync_id; - - } else { - - u8 *trim = strrchr(name, '/'); - if (!trim) { - - afl->use_banner = name; - - } else { - - afl->use_banner = trim + 1; - - } - - } - - } - - if (strlen(afl->use_banner) > 32) { - - u8 *tmp = ck_alloc(36); - sprintf(tmp, "%.32s...", afl->use_banner); - afl->use_banner = tmp; - - } - -} - /* Check if we're on TTY. */ void check_if_tty(afl_state_t *afl) { diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 4173f4e1..da6ba7d9 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -291,8 +291,6 @@ static void write_with_gap(afl_state_t *afl, u8 *mem, u32 len, u32 skip_at, u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u32 handicap, u8 from_queue) { - if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; } - u8 fault = 0, new_bits = 0, var_detected = 0, hnb = 0, first_run = (q->exec_cksum == 0); u64 start_us, stop_us, diff_us; @@ -300,6 +298,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u32 use_tmout = afl->fsrv.exec_tmout; u8 *old_sn = afl->stage_name; + if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; } + /* Be a bit more generous about timeouts when resuming sessions, or when trying to calibrate already-added finds. This helps avoid trouble due to intermittent latency. */ @@ -343,6 +343,32 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } + /* we need a dummy run if this is LTO + cmplog */ + if (unlikely(afl->shm.cmplog_mode)) { + + write_to_testcase(afl, use_mem, q->len); + + fault = fuzz_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. */ + + if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } + + if (!afl->non_instrumented_mode && !afl->stage_cur && + !count_bytes(afl, afl->fsrv.trace_bits)) { + + fault = FSRV_RUN_NOINST; + goto abort_calibration; + + } + +#ifdef INTROSPECTION + if (unlikely(!q->bitsmap_size)) q->bitsmap_size = afl->bitsmap_size; +#endif + + } + if (q->exec_cksum) { memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index eb1fe2d9..0c06232b 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -441,9 +441,10 @@ void show_stats(afl_state_t *afl) { u64 cur_ms; u32 t_bytes, t_bits; - u32 banner_len, banner_pad; - u8 tmp[256]; - u8 time_tmp[64]; + static u8 banner[128]; + u32 banner_len, banner_pad; + u8 tmp[256]; + u8 time_tmp[64]; u8 val_buf[8][STRINGIFY_VAL_SIZE_MAX]; #define IB(i) (val_buf[(i)]) @@ -560,8 +561,9 @@ void show_stats(afl_state_t *afl) { /* Roughly every minute, update fuzzer stats and save auto tokens. */ - if (unlikely(afl->force_ui_update || - cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000)) { + if (unlikely(!afl->non_instrumented_mode && + (afl->force_ui_update || + cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) { afl->stats_last_stats_ms = cur_ms; write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio, @@ -655,26 +657,34 @@ void show_stats(afl_state_t *afl) { } /* Let's start by drawing a centered banner. */ + if (unlikely(!banner[0])) { - banner_len = (afl->crash_mode ? 24 : 22) + strlen(VERSION) + - strlen(afl->use_banner) + strlen(afl->power_name) + 3 + 5; - banner_pad = (79 - banner_len) / 2; - memset(tmp, ' ', banner_pad); + char *si = ""; + if (afl->sync_id) { si = afl->sync_id; } + memset(banner, 0, sizeof(banner)); + banner_len = (afl->crash_mode ? 20 : 18) + strlen(VERSION) + strlen(si) + + strlen(afl->power_name) + 4 + 6; -#ifdef HAVE_AFFINITY - sprintf( - tmp + banner_pad, - "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]" cBLU " {%d}", - afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", - afl->use_banner, afl->power_name, afl->cpu_aff); -#else - sprintf( - tmp + banner_pad, "%s " cLCY VERSION cLGN " (%s) " cPIN "[%s]", - afl->crash_mode ? cPIN "peruvian were-rabbit" : cYEL "american fuzzy lop", - afl->use_banner, afl->power_name); -#endif /* HAVE_AFFINITY */ + if (strlen(afl->use_banner) + banner_len > 75) { + + afl->use_banner += (strlen(afl->use_banner) + banner_len) - 76; + memset(afl->use_banner, '.', 3); + + } + + banner_len += strlen(afl->use_banner); + banner_pad = (79 - banner_len) / 2; + memset(banner, ' ', banner_pad); + + sprintf(banner + banner_pad, + "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]", + afl->crash_mode ? cPIN "peruvian were-rabbit" + : cYEL "american fuzzy lop", + si, afl->use_banner, afl->power_name); + + } - SAYF("\n%s\n", tmp); + SAYF("\n%s\n", banner); /* "Handy" shortcuts for drawing boxes... */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8ffc0e77..34f3377b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1189,7 +1189,17 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->sync_id) { fix_up_sync(afl); } + if (afl->sync_id) { + + if (strlen(afl->sync_id) > 24) { + + FATAL("sync_id max length is 24 characters"); + + } + + fix_up_sync(afl); + + } if (!strcmp(afl->in_dir, afl->out_dir)) { @@ -1218,6 +1228,8 @@ int main(int argc, char **argv_orig, char **envp) { if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); } + if (!afl->use_banner) { afl->use_banner = argv[optind]; } + if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { WARNF(cLRD @@ -1348,7 +1360,7 @@ int main(int argc, char **argv_orig, char **envp) { } else if (afl->q_testcase_max_cache_size < 2 * MAX_FILE) { - FATAL("AFL_TESTCACHE_SIZE must be set to %u or more, or 0 to disable", + FATAL("AFL_TESTCACHE_SIZE must be set to %ld or more, or 0 to disable", (2 * MAX_FILE) % 1048576 == 0 ? (2 * MAX_FILE) / 1048576 : 1 + ((2 * MAX_FILE) / 1048576)); @@ -1486,9 +1498,6 @@ int main(int argc, char **argv_orig, char **envp) { } save_cmdline(afl, argc, argv); - - fix_up_banner(afl, argv[optind]); - check_if_tty(afl); if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } @@ -1697,7 +1706,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode || afl->unicorn_mode) { - map_size = afl->fsrv.map_size = MAP_SIZE; + map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE; afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size); afl->virgin_crash = ck_realloc(afl->virgin_crash, map_size); @@ -1918,7 +1927,7 @@ int main(int argc, char **argv_orig, char **envp) { } - write_stats_file(afl, 0, 0, 0, 0); + if (!afl->non_instrumented_mode) { write_stats_file(afl, 0, 0, 0, 0); } maybe_update_plot_file(afl, 0, 0, 0); save_auto(afl); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 9122cd25..3826e385 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -77,7 +77,7 @@ static u32 tcnt, highest; /* tuple content information */ static u32 in_len; /* Input data length */ -static u32 map_size = MAP_SIZE; +static u32 map_size = MAP_SIZE, timed_out = 0; static bool quiet_mode, /* Hide non-essential messages? */ edges_only, /* Ignore hit counts? */ @@ -146,6 +146,18 @@ static const u8 count_class_binary[256] = { #undef TIMES8 #undef TIMES4 +static void kill_child() { + + timed_out = 1; + if (fsrv->child_pid > 0) { + + kill(fsrv->child_pid, fsrv->kill_signal); + fsrv->child_pid = -1; + + } + +} + static void classify_counts(afl_forkserver_t *fsrv) { u8 * mem = fsrv->trace_bits; @@ -242,9 +254,14 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { if (cmin_mode && (fsrv->last_run_timed_out || (!caa && child_crashed != cco))) { - // create empty file to prevent error messages in afl-cmin - fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - close(fd); + if (strcmp(outfile, "-")) { + + // create empty file to prevent error messages in afl-cmin + fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); + close(fd); + + } + return ret; } @@ -357,9 +374,10 @@ static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem, if (!quiet_mode) { - if (fsrv->last_run_timed_out) { + if (timed_out || fsrv->last_run_timed_out) { SAYF(cLRD "\n+++ Program timed off +++\n" cRST); + timed_out = 0; } else if (stop_soon) { @@ -413,7 +431,7 @@ static u32 read_file(u8 *in_file) { if (!be_quiet && !quiet_mode) { - WARNF("Input file '%s' is too large, only reading %u bytes.", in_file, + WARNF("Input file '%s' is too large, only reading %ld bytes.", in_file, MAX_FILE); } @@ -521,6 +539,8 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { } + signal(SIGALRM, kill_child); + setitimer(ITIMER_REAL, &it, NULL); if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); } @@ -563,9 +583,10 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { if (!quiet_mode) { - if (fsrv->last_run_timed_out) { + if (timed_out || fsrv->last_run_timed_out) { SAYF(cLRD "\n+++ Program timed off +++\n" cRST); + timed_out = 0; } else if (stop_soon) { @@ -1189,6 +1210,8 @@ int main(int argc, char **argv_orig, char **envp) { } + if (in_dir) { (void)check_binary_signatures(fsrv->target_path); } + shm_fuzz = ck_alloc(sizeof(sharedmem_t)); /* initialize cmplog_mode */ diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 792770e0..ce2a0b8f 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -120,6 +120,17 @@ static const u8 count_class_lookup[256] = { #undef TIMES8 #undef TIMES4 +static void kill_child() { + + if (fsrv->child_pid > 0) { + + kill(fsrv->child_pid, fsrv->kill_signal); + fsrv->child_pid = -1; + + } + +} + static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv, sharedmem_t * shm_fuzz) { @@ -221,7 +232,7 @@ static void read_initial_file(void) { if (st.st_size >= TMIN_MAX_FILE) { - FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024); + FATAL("Input file is too large (%ld MB max)", TMIN_MAX_FILE / 1024 / 1024); } @@ -1125,6 +1136,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->target_path = find_binary(argv[optind]); fsrv->trace_bits = afl_shm_init(&shm, map_size, 0); detect_file_args(argv + optind, out_file, &fsrv->use_stdin); + signal(SIGALRM, kill_child); if (fsrv->qemu_mode) { @@ -1209,6 +1221,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz = map + sizeof(u32); read_initial_file(); + (void)check_binary_signatures(fsrv->target_path); if (!fsrv->qemu_mode && !unicorn_mode) { |