diff options
author | vanhauser-thc <vh@thc.org> | 2022-08-14 12:24:42 +0200 |
---|---|---|
committer | vanhauser-thc <vh@thc.org> | 2022-08-14 12:30:23 +0200 |
commit | 3200e6515b9cc988d0d8dccd27257baccc8df021 (patch) | |
tree | 6a3538d9e3d13a78a5227fca69258c46a9fb5c76 | |
parent | 89d6e306f29d1424012cdbb95d5cb18f6e36932f (diff) | |
download | afl++-3200e6515b9cc988d0d8dccd27257baccc8df021.tar.gz |
add AFL_NO_STARTUP_CALIBRATION feature
-rw-r--r-- | docs/Changelog.md | 9 | ||||
-rw-r--r-- | docs/env_variables.md | 3 | ||||
-rw-r--r-- | docs/fuzzing_in_depth.md | 7 | ||||
-rw-r--r-- | include/afl-fuzz.h | 4 | ||||
-rw-r--r-- | include/envs.h | 1 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 24 | ||||
-rw-r--r-- | src/afl-fuzz-queue.c | 10 | ||||
-rw-r--r-- | src/afl-fuzz-state.c | 7 | ||||
-rw-r--r-- | src/afl-fuzz.c | 13 |
9 files changed, 73 insertions, 5 deletions
diff --git a/docs/Changelog.md b/docs/Changelog.md index ec517104..f5847ade 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,7 +9,14 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to <afl-users+subscribe@googlegroups.com>. ### Version ++4.03a (dev) - - ... your PR? :) + - afl-fuzz: + - added AFL_NO_STARTUP_CALIBRATION to start fuzzing at once instead + of calibrating all initial seeds first. Good for large queues + and long execution times, especially in CIs. + - qemu_mode: + - added AFL_QEMU_TRACK_UNSTABLE to log the addresses of unstable + edges (together with AFL_DEBUG=1 afl-fuzz). thanks to + worksbutnottested! ### Version ++4.02c (release) diff --git a/docs/env_variables.md b/docs/env_variables.md index 00948fc1..bb54357b 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -462,6 +462,9 @@ checks or alter some of the more exotic semantics of the tool: some basic stats. This behavior is also automatically triggered when the output from afl-fuzz is redirected to a file or to a pipe. + - Setting `AFL_NO_STARTUP_CALIBRATION` will skip the initial calibration + of all starting seeds, and start fuzzing at once. + - In QEMU mode (-Q) and FRIDA mode (-O), `AFL_PATH` will be searched for afl-qemu-trace and afl-frida-trace.so. diff --git a/docs/fuzzing_in_depth.md b/docs/fuzzing_in_depth.md index 37889137..92c9910b 100644 --- a/docs/fuzzing_in_depth.md +++ b/docs/fuzzing_in_depth.md @@ -626,6 +626,9 @@ from other fuzzers in the campaign first. If you have a large corpus, a corpus from a previous run or are fuzzing in a CI, then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`. +If the queue in the CI is huge and/or the execution time is slow then you can +also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration +phase and start fuzzing at once. You can also use different fuzzers. If you are using AFL spinoffs or AFL conforming fuzzers, then just use the same -o directory and give it a unique @@ -902,6 +905,10 @@ complex file formats. Some notes on continuous integration (CI) fuzzing - this fuzzing is different to normal fuzzing campaigns as these are much shorter runnings. +If the queue in the CI is huge and/or the execution time is slow then you can +also add `AFL_NO_STARTUP_CALIBRATION=1` to skip the initial queue calibration +phase and start fuzzing at once. + 1. Always: * LTO has a much longer compile time which is diametrical to short fuzzing - hence use afl-clang-fast instead. diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 061076ed..822096e8 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -386,7 +386,8 @@ typedef struct afl_env_vars { afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast, 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_pizza_mode, afl_no_crash_readme; + afl_keep_timeouts, afl_pizza_mode, afl_no_crash_readme, + afl_no_startup_calibration; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload, @@ -1122,6 +1123,7 @@ void bind_to_free_cpu(afl_state_t *); void setup_post(afl_state_t *); void read_testcases(afl_state_t *, u8 *); void perform_dry_run(afl_state_t *); +void no_dry_run(afl_state_t *); void pivot_inputs(afl_state_t *); u32 find_start_position(afl_state_t *); void find_timeout(afl_state_t *); diff --git a/include/envs.h b/include/envs.h index 02bd2ece..2204a100 100644 --- a/include/envs.h +++ b/include/envs.h @@ -165,6 +165,7 @@ static char *afl_environment_variables[] = { "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", + "AFL_NO_STARTUP_CALIBRATION", "AFL_UNTRACER_FILE", "AFL_LLVM_USE_TRACE_PC", "AFL_MAP_SIZE", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 4ffcfd2b..32e2b7b8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -850,6 +850,30 @@ void read_testcases(afl_state_t *afl, u8 *directory) { } +/* In case no initial calibration is to be performed (e.g. huge queue and slow +execution time), then setting AFL_NO_STARTUP_CALIBRATION will help getting +initial data. For this to succeed, non-calibrated corpus entries have to look +especially juicy so they are more likely to be selected then a calibrated good +looking one. */ + +void no_dry_run(afl_state_t *afl) { + + struct queue_entry *q; + u32 idx; + + for (idx = 0; idx < afl->queued_items; idx++) { + + q = afl->queue_buf[idx]; + if (unlikely(!q || q->disabled)) { continue; } + + q->exec_us = 1; + q->bitmap_size = MAP_SIZE; + q->tc_ref = MAP_SIZE; + + } + +} + /* 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. */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 02d697ab..d8dbdfbe 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -795,8 +795,14 @@ void cull_queue(afl_state_t *afl) { u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { - u32 avg_exec_us = afl->total_cal_us / afl->total_cal_cycles; - u32 avg_bitmap_size = afl->total_bitmap_size / afl->total_bitmap_entries; + u32 cal_cycles = afl->total_cal_cycles; + u32 bitmap_entries = afl->total_bitmap_entries; + + if (unlikely(!cal_cycles)) { cal_cycles = 1; } + if (unlikely(!bitmap_entries)) { bitmap_entries = 1; } + + u32 avg_exec_us = afl->total_cal_us / cal_cycles; + u32 avg_bitmap_size = afl->total_bitmap_size / bitmap_entries; u32 perf_score = 100; /* Adjust score based on execution speed of this path, compared to the diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index ddfd4b31..6770839a 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -265,6 +265,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_cmplog_only_new = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION", + + afl_environment_variable_len)) { + + afl->afl_env.afl_no_startup_calibration = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_NO_UI", afl_environment_variable_len)) { afl->afl_env.afl_no_ui = diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2e151abb..e3851473 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -273,6 +273,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n" "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n" "AFL_NO_SNAPSHOT: do not use the snapshot feature (if the snapshot lkm is loaded)\n" + "AFL_NO_STARTUP_CALIBRATION: no initial seed calibration, start fuzzing at once\n" "AFL_NO_UI: switch status screen off\n" DYN_COLOR @@ -2150,7 +2151,17 @@ int main(int argc, char **argv_orig, char **envp) { memset(afl->virgin_tmout, 255, map_size); memset(afl->virgin_crash, 255, map_size); - perform_dry_run(afl); + if (likely(!afl->afl_env.afl_no_startup_calibration)) { + + perform_dry_run(afl); + + } else { + + ACTF("skipping initial seed calibration due option override"); + usleep(1000); + no_dry_run(afl); + + } if (afl->q_testcase_max_cache_entries) { |