From 495127480a44a830c317306c5aa25feee94a3abe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ulf=20Karg=C3=A9n?= <ulf.kargen@liu.se> Date: Mon, 20 Nov 2023 04:58:56 +0100 Subject: [PATCH] simplify sync delay implementation --- include/afl-fuzz.h | 9 ++++---- include/config.h | 5 ----- include/envs.h | 2 +- src/afl-fuzz-init.c | 52 -------------------------------------------- src/afl-fuzz-one.c | 4 ---- src/afl-fuzz-queue.c | 17 --------------- src/afl-fuzz-run.c | 50 +++++++++++++++++++++--------------------- src/afl-fuzz-state.c | 16 +++++++++++--- src/afl-fuzz.c | 10 +++++++-- 9 files changed, 51 insertions(+), 114 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index f48754b6..f87e21df 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -184,8 +184,7 @@ struct queue_entry { handicap, /* Number of queue cycles behind */ depth, /* Path depth */ exec_cksum, /* Checksum of the execution trace */ - stats_mutated, /* stats: # of mutations performed */ - first_fuzz; /* Time of first fuzzing */ + stats_mutated; /* stats: # of mutations performed */ u8 *trace_mini; /* Trace bytes, if kept */ u32 tc_ref; /* Trace bytes ref count */ @@ -400,7 +399,7 @@ typedef struct afl_env_vars { afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new, afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems, afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts, - afl_no_startup_calibration, afl_no_warn_instability, afl_delay_sync; + afl_no_startup_calibration, afl_no_warn_instability; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, @@ -596,7 +595,8 @@ typedef struct afl_state { last_hang_time, /* Time for most recent hang (ms) */ longest_find_time, /* Longest time taken for a find */ exit_on_time, /* Delay to exit if no new paths */ - sync_time; /* Sync time (ms) */ + sync_time, /* Sync time (ms) */ + sync_delay; /* Sync delay (ms) */ u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ subseq_tmouts; /* Number of timeouts in a row */ @@ -1089,7 +1089,6 @@ void deinit_py(void *); /* Queue */ void mark_as_det_done(afl_state_t *, struct queue_entry *); -void mark_as_fuzzed(afl_state_t *, struct queue_entry *); void mark_as_variable(afl_state_t *, struct queue_entry *); void mark_as_redundant(afl_state_t *, struct queue_entry *, u8); void add_to_queue(afl_state_t *, u8 *, u32, u8); diff --git a/include/config.h b/include/config.h index 1360ba25..b6249a0f 100644 --- a/include/config.h +++ b/include/config.h @@ -309,11 +309,6 @@ #define SYNC_TIME (30 * 60 * 1000) -/* Approximate number of queue cycles to delay syncing of new discoveries - when AFL_DELAY_SYNC is in effect. */ - -#define SYNC_DELAY_CYCLES 3 - /* Output directory reuse grace period (minutes): */ #define OUTPUT_GRACE 25 diff --git a/include/envs.h b/include/envs.h index 6f5576f4..942aab66 100644 --- a/include/envs.h +++ b/include/envs.h @@ -221,7 +221,7 @@ static char *afl_environment_variables[] = { "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", - "AFL_DELAY_SYNC", + "AFL_SYNC_DELAY", "AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 7531149c..01d1e82e 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -801,24 +801,6 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } - /* Carry over saved time of first fuzzing from resumed run, if present */ - - u8 wf_fn[PATH_MAX]; - s32 wf_fd; - u64 first_fuzz; - snprintf(wf_fn, PATH_MAX, "%s/.state/was_fuzzed/%s", afl->in_dir, - nl[i]->d_name); - wf_fd = open(wf_fn, O_RDONLY); - - if (wf_fd != -1 && - read(wf_fd, &first_fuzz, sizeof(u64)) == sizeof(u64)) { - afl->queue_top->was_fuzzed = 1; - afl->queue_top->first_fuzz = first_fuzz; - afl->pending_not_fuzzed--; - } - - close(wf_fd); - /* if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) { @@ -920,8 +902,6 @@ void perform_dry_run(afl_state_t *afl) { } - u64 runtime = afl->prev_run_time + get_cur_time() - afl->start_time; - switch (res) { case FSRV_RUN_OK: @@ -948,9 +928,6 @@ void perform_dry_run(afl_state_t *afl) { --afl->pending_not_fuzzed; --afl->active_items; - q->first_fuzz = runtime; - mark_as_fuzzed(afl, q); - } break; @@ -1082,9 +1059,6 @@ void perform_dry_run(afl_state_t *afl) { --afl->pending_not_fuzzed; --afl->active_items; - q->first_fuzz = runtime; - mark_as_fuzzed(afl, q); - } q->disabled = 1; @@ -1195,8 +1169,6 @@ void perform_dry_run(afl_state_t *afl) { duplicates = 1; - u64 runtime = afl->prev_run_time + get_cur_time() - afl->start_time; - // we keep the shorter file if (p->len >= q->len) { @@ -1206,9 +1178,6 @@ void perform_dry_run(afl_state_t *afl) { --afl->pending_not_fuzzed; --afl->active_items; - p->first_fuzz = runtime; - mark_as_fuzzed(afl, p); - } p->disabled = 1; @@ -1222,9 +1191,6 @@ void perform_dry_run(afl_state_t *afl) { --afl->pending_not_fuzzed; --afl->active_items; - q->first_fuzz = runtime; - mark_as_fuzzed(afl, q); - } q->disabled = 1; @@ -1393,10 +1359,6 @@ void pivot_inputs(afl_state_t *afl) { if (q->passed_det) { mark_as_det_done(afl, q); } - /* ...and the time of first fuzzing. */ - - if (q->was_fuzzed) { mark_as_fuzzed(afl, q); } - if (afl->custom_mutators_count) { run_afl_custom_queue_new_entry(afl, q, q->fname, NULL); @@ -1594,10 +1556,6 @@ void nuke_resume_dir(afl_state_t *afl) { if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); - fn = alloc_printf("%s/_resume/.state/was_fuzzed", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } - ck_free(fn); - fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir); if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; } ck_free(fn); @@ -1758,10 +1716,6 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); - fn = alloc_printf("%s/queue/.state/was_fuzzed", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } - ck_free(fn); - fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir); if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; } ck_free(fn); @@ -2053,12 +2007,6 @@ void setup_dirs_fds(afl_state_t *afl) { if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); - /* Directory for flagging queue entries that have been fuzzed */ - - tmp = alloc_printf("%s/queue/.state/was_fuzzed/", afl->out_dir); - if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } - ck_free(tmp); - /* Directory with the auto-selected dictionary entries. */ tmp = alloc_printf("%s/queue/.state/auto_extras/", afl->out_dir); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 53f6e447..ee562f96 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -3091,10 +3091,6 @@ abandon_entry: afl->reinit_table = 1; if (afl->queue_cur->favored) { --afl->pending_favored; } - afl->queue_cur->first_fuzz = - afl->prev_run_time + get_cur_time() - afl->start_time; - mark_as_fuzzed(afl, afl->queue_cur); - } ++afl->queue_cur->fuzz_level; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index e5282517..8ad7cd97 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -292,23 +292,6 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { } -void mark_as_fuzzed(afl_state_t *afl, struct queue_entry *q) { - - char fn[PATH_MAX]; - s32 fd; - - snprintf(fn, PATH_MAX, "%s/queue/.state/was_fuzzed/%s", afl->out_dir, - strrchr((char *)q->fname, '/') + 1); - - fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION); - if (fd < 0) { PFATAL("Unable to create '%s'", fn); } - - ck_write(fd, &q->first_fuzz, sizeof(u64), fn); - - close(fd); - -} - /* Mark as variable. Create symlinks if possible to make it easier to examine the files. */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 99519757..04222817 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -648,7 +648,6 @@ void sync_fuzzers(afl_state_t *afl) { struct dirent *sd_ent; u32 sync_cnt = 0, synced = 0, entries = 0; u8 path[PATH_MAX + 1 + NAME_MAX]; - u8 wf_path[PATH_MAX + 1 + NAME_MAX]; sd = opendir(afl->sync_dir); if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } @@ -704,7 +703,6 @@ void sync_fuzzers(afl_state_t *afl) { /* document the attempt to sync to this instance */ sprintf(qd_synced_path, "%s/.synced/%s.last", afl->out_dir, sd_ent->d_name); - id_fd = open(qd_synced_path, O_RDWR | O_CREAT | O_TRUNC, DEFAULT_PERMISSION); if (id_fd >= 0) close(id_fd); @@ -748,12 +746,6 @@ void sync_fuzzers(afl_state_t *afl) { afl->stage_cur = 0; afl->stage_max = 0; - if(afl->afl_env.afl_delay_sync && !afl->last_sync_time) { - - goto close_sync; - - } - /* For every file queued by this fuzzer, parse ID and see if we have looked at it before; exec a test case if not. */ @@ -777,37 +769,46 @@ void sync_fuzzers(afl_state_t *afl) { if (m >= n) { goto close_sync; } // nothing new u8 retry_remaining = 0; - + for (o = m; o < n; o++) { - s32 fd, wf_fd; + s32 fd; struct stat st; - u64 ftime; u8 skip; snprintf(path, sizeof(path), "%s/%s", qd_path, namelist[o]->d_name); - /* Skip syncing of recent discoveries if AFL_DELAY_SYNC is set. */ + /* Skip syncing of recent discoveries if AFL_SYNC_DELAY is set. */ skip = 0; - if (afl->afl_env.afl_delay_sync) { + if (afl->sync_delay) { + + u8 *timep = NULL; + u8 *timep_tmp = namelist[o]->d_name; + u64 discovery_time = 0; + + /* Parse time field in file name. Scan in reverse order to capture + original discovery time in case of a resumed session. */ + + while ( (timep_tmp = strstr(timep_tmp, "time:")) ) { - u64 cycle_time = get_cur_time() - afl->last_sync_time; + timep_tmp += 5; + timep = timep_tmp; - u64 runtime = afl->prev_run_time + get_cur_time() - afl->start_time; + } + + if (timep) { + + sscanf(timep, "%llu", &discovery_time); - snprintf(wf_path, sizeof(wf_path), "%s/.state/was_fuzzed/%s", - qd_path, namelist[o]->d_name); + } - wf_fd = open(wf_path, O_RDONLY); + if (afl->prev_run_time + get_cur_time() - afl->start_time < + afl->sync_delay + discovery_time) { - if (wf_fd < 0 || - read(wf_fd, &ftime, sizeof(u64)) != sizeof(u64) || - ftime + SYNC_DELAY_CYCLES * cycle_time > runtime) { - skip = 1; - + /* All entries beyond this one would need to be retried at the next sync. (Pretty wasteful, would be better to document each synced test case individually, e.g. in the .synced dir.) */ @@ -816,8 +817,7 @@ void sync_fuzzers(afl_state_t *afl) { ck_write(id_fd, &next_min_accept, sizeof(u32), qd_synced_path); } - close(wf_fd); - + } afl->syncing_case = next_min_accept; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index b6bb0fdf..60206b4a 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -567,12 +567,22 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } - } else if (!strncmp(env, "AFL_DELAY_SYNC", + } else if (!strncmp(env, "AFL_SYNC_DELAY", afl_environment_variable_len)) { - afl->afl_env.afl_delay_sync = - get_afl_env(afl_environment_variables[i]) ? 1 : 0; + int delay = atoi((u8 *)get_afl_env(afl_environment_variables[i])); + if (delay > 0) { + + afl->sync_delay = delay * (60 * 1000LL); + + } else { + + WARNF( + "incorrect value for AFL_SYNC_DELAY environment variable, " + "used default value 0 instead."); + + } } else if (!strncmp(env, "AFL_FUZZER_STATS_UPDATE_INTERVAL", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9866642b..b93b04ef 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1339,6 +1339,13 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->sync_delay) { + + OKF("AFL_SYNC_DELAY set. Delaying sync by %llu minutes.", + afl->sync_delay / (60 * 1000LL)); + + } + #ifdef __linux__ if (afl->fsrv.nyx_mode) { @@ -2578,8 +2585,7 @@ int main(int argc, char **argv_orig, char **envp) { } while (skipped_fuzz && afl->queue_cur && !afl->stop_soon); - if (likely(!afl->stop_soon && afl->sync_id && - !afl->afl_env.afl_delay_sync)) { + if (likely(!afl->stop_soon && afl->sync_id)) { if (likely(afl->skip_deterministic)) { -- GitLab