add AFL_NO_STARTUP_CALIBRATION feature

This commit is contained in:
vanhauser-thc
2022-08-14 12:24:42 +02:00
parent 89d6e306f2
commit 3200e6515b
9 changed files with 73 additions and 5 deletions

View File

@ -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)

View File

@ -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.

View File

@ -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.

View File

@ -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 *);

View File

@ -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",

View File

@ -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. */

View File

@ -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

View File

@ -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 =

View File

@ -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,8 +2151,18 @@ int main(int argc, char **argv_orig, char **envp) {
memset(afl->virgin_tmout, 255, map_size);
memset(afl->virgin_crash, 255, map_size);
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) {
afl->q_testcase_cache =