diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-cc.c | 91 | ||||
-rw-r--r-- | src/afl-common.c | 16 | ||||
-rw-r--r-- | src/afl-forkserver.c | 21 | ||||
-rw-r--r-- | src/afl-fuzz-bitmap.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-cmplog.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 19 | ||||
-rw-r--r-- | src/afl-fuzz-mutators.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 35 | ||||
-rw-r--r-- | src/afl-fuzz-state.c | 16 | ||||
-rw-r--r-- | src/afl-fuzz.c | 41 |
10 files changed, 169 insertions, 76 deletions
diff --git a/src/afl-cc.c b/src/afl-cc.c index 9197c74b..ed57ca1e 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -315,7 +315,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0, preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0, - have_c = 0, partial_linking = 0; + have_c = 0, partial_linking = 0, wasm_linking = 0; cc_params = ck_alloc((argc + 128) * sizeof(u8 *)); @@ -671,22 +671,6 @@ static void edit_params(u32 argc, char **argv, char **envp) { // cc_params[cc_par_cnt++] = "-Qunused-arguments"; - // in case LLVM is installed not via a package manager or "make install" - // e.g. compiled download or compiled from github then its ./lib directory - // might not be in the search path. Add it if so. - u8 *libdir = strdup(LLVM_LIBDIR); - if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) && - strncmp(libdir, "/lib", 4)) { - - cc_params[cc_par_cnt++] = "-rpath"; - cc_params[cc_par_cnt++] = libdir; - - } else { - - free(libdir); - - } - if (lto_mode && argc > 1) { u32 idx; @@ -766,14 +750,21 @@ static void edit_params(u32 argc, char **argv, char **envp) { u8 *afllib = find_object("libAFLDriver.a", argv[0]); - if (!be_quiet) + if (!be_quiet) { + OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a"); + } + if (!afllib) { - WARNF( - "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " - "the flags - this will fail!"); + if (!be_quiet) { + + WARNF( + "Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in " + "the flags - this will fail!"); + + } } else { @@ -806,6 +797,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { if (!strcmp(cur, "-E")) preprocessor_only = 1; if (!strcmp(cur, "-shared")) shared_linking = 1; if (!strcmp(cur, "-dynamiclib")) shared_linking = 1; + if (!strcmp(cur, "--target=wasm32-wasi")) wasm_linking = 1; if (!strcmp(cur, "-Wl,-r")) partial_linking = 1; if (!strcmp(cur, "-Wl,-i")) partial_linking = 1; if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1; @@ -820,6 +812,22 @@ static void edit_params(u32 argc, char **argv, char **envp) { } + // in case LLVM is installed not via a package manager or "make install" + // e.g. compiled download or compiled from github then its ./lib directory + // might not be in the search path. Add it if so. + u8 *libdir = strdup(LLVM_LIBDIR); + if (plusplus_mode && !wasm_linking && strlen(libdir) && + strncmp(libdir, "/usr", 4) && strncmp(libdir, "/lib", 4)) { + + cc_params[cc_par_cnt++] = "-rpath"; + cc_params[cc_par_cnt++] = libdir; + + } else { + + free(libdir); + + } + if (getenv("AFL_HARDEN")) { cc_params[cc_par_cnt++] = "-fstack-protector-all"; @@ -923,7 +931,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } -#if defined(USEMMAP) && !defined(__HAIKU__) +#if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ if (!have_c) cc_params[cc_par_cnt++] = "-lrt"; #endif @@ -1056,7 +1064,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { switch (bit_mode) { case 0: - if (!shared_linking && !partial_linking) + if (!shared_linking && !partial_linking && !wasm_linking) cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt.o", obj_path); if (lto_mode) @@ -1065,7 +1073,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { break; case 32: - if (!shared_linking && !partial_linking) { + if (!shared_linking && !partial_linking && !wasm_linking) { cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt-32.o", obj_path); @@ -1086,7 +1094,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { break; case 64: - if (!shared_linking && !partial_linking) { + if (!shared_linking && !partial_linking && !wasm_linking) { cc_params[cc_par_cnt++] = alloc_printf("%s/afl-compiler-rt-64.o", obj_path); @@ -1109,7 +1117,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #if !defined(__APPLE__) && !defined(__sun) - if (!shared_linking && !partial_linking) + if (!shared_linking && !partial_linking && !wasm_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif @@ -1128,7 +1136,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - #if defined(USEMMAP) && !defined(__HAIKU__) + #if defined(USEMMAP) && !defined(__HAIKU__) && !__APPLE__ cc_params[cc_par_cnt++] = "-lrt"; #endif @@ -1248,10 +1256,14 @@ int main(int argc, char **argv, char **envp) { if (compiler_mode) { - WARNF( - "\"AFL_CC_COMPILER\" is set but a specific compiler was already " - "selected by command line parameter or symlink, ignoring the " - "environment variable!"); + if (!be_quiet) { + + WARNF( + "\"AFL_CC_COMPILER\" is set but a specific compiler was already " + "selected by command line parameter or symlink, ignoring the " + "environment variable!"); + + } } else { @@ -1304,11 +1316,14 @@ int main(int argc, char **argv, char **envp) { } - if (compiler_mode) + if (compiler_mode && !be_quiet) { + WARNF( "--afl-... compiler mode supersedes the AFL_CC_COMPILER and " "symlink compiler selection!"); + } + ptr = argv[i]; ptr += 5; while (*ptr == '-') @@ -1390,7 +1405,7 @@ int main(int argc, char **argv, char **envp) { } - if (have_instr_env && getenv("AFL_DONT_OPTIMIZE")) { + if (have_instr_env && getenv("AFL_DONT_OPTIMIZE") && !be_quiet) { WARNF( "AFL_LLVM_ALLOWLIST/DENYLIST and AFL_DONT_OPTIMIZE cannot be combined " @@ -1970,10 +1985,13 @@ int main(int argc, char **argv, char **envp) { } else { - if (!be_quiet) + if (!be_quiet) { + WARNF("afl-clang-lto called with mode %s, using that mode instead", instrument_mode_string[instrument_mode]); + } + } } @@ -1985,11 +2003,14 @@ int main(int argc, char **argv, char **envp) { if (have_instr_env) { instrument_mode = INSTRUMENT_AFL; - if (!be_quiet) + if (!be_quiet) { + WARNF( "Switching to classic instrumentation because " "AFL_LLVM_ALLOWLIST/DENYLIST does not work with PCGUARD < 10.0.1."); + } + } else #endif diff --git a/src/afl-common.c b/src/afl-common.c index 7ba3bb74..7c074acc 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -71,11 +71,9 @@ u32 check_binary_signatures(u8 *fn) { } else if (getenv("AFL_PERSISTENT")) { - if (!be_quiet) { - - WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); - - } + if (!be_quiet) { OKF(cPIN "Persistent mode enforced."); } + setenv(PERSIST_ENV_VAR, "1", 1); + ret = 1; } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) { @@ -98,11 +96,9 @@ u32 check_binary_signatures(u8 *fn) { } else if (getenv("AFL_DEFER_FORKSRV")) { - if (!be_quiet) { - - WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); - - } + if (!be_quiet) { OKF(cPIN "Deferred forkserver enforced."); } + setenv(DEFER_ENV_VAR, "1", 1); + ret += 2; } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index ce554170..8997781d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -59,7 +59,11 @@ static list_t fsrv_list = {.element_prealloc_count = 0}; static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { - if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); } + if (fsrv->qemu_mode || fsrv->cs_mode) { + + setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); + + } execv(fsrv->target_path, argv); @@ -281,13 +285,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { sigaction(SIGPIPE, &sa, NULL); signal(SIGCHLD, old_sigchld_handler); + // FORKSRV_FD is for communication with AFL, we don't need it in the - // child. + // child close(FORKSRV_FD); close(FORKSRV_FD + 1); - // TODO: exec... - + // finally: exec... execv(fsrv->target_path, argv); /* Use a distinctive bitmap signature to tell the parent about execv() @@ -567,6 +571,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + if (!be_quiet) { ACTF("Using AFL++ faux forkserver..."); } fsrv->init_child_func = afl_fauxsrv_execv; } @@ -1265,7 +1270,8 @@ u32 afl_fsrv_get_mapsize(afl_forkserver_t *fsrv, char **argv, /* Delete the current testcase and write the buf to the testcase file */ -void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { +void __attribute__((hot)) +afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { #ifdef __linux__ if (unlikely(fsrv->nyx_mode)) { @@ -1383,8 +1389,9 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { /* 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, u32 timeout, - volatile u8 *stop_soon_p) { +fsrv_run_result_t __attribute__((hot)) +afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, + volatile u8 *stop_soon_p) { s32 res; u32 exec_ms; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 8d044959..b963caf8 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -633,7 +633,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (afl->fsrv.exec_tmout < afl->hang_tmout) { u8 new_fault; - write_to_testcase(afl, mem, len); + len = write_to_testcase(afl, mem, len, 0); new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout); classify_counts(&afl->fsrv); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index ce8f1a83..1a8052a0 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -49,7 +49,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; - write_to_testcase(afl, out_buf, len); + len = write_to_testcase(afl, out_buf, len, 0); fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 5449460e..05a654c8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -617,11 +617,10 @@ void read_foreign_testcases(afl_state_t *afl, int first) { } - write_to_testcase(afl, mem, st.st_size); + u32 len = write_to_testcase(afl, mem, st.st_size, 1); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); afl->syncing_party = foreign_name; - afl->queued_imported += - save_if_interesting(afl, mem, st.st_size, fault); + afl->queued_imported += save_if_interesting(afl, mem, len, fault); afl->syncing_party = 0; munmap(mem, st.st_size); close(fd); @@ -2818,19 +2817,23 @@ void check_binary(afl_state_t *afl, u8 *fname) { OKF(cPIN "Persistent mode binary detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; - + afl->fsrv.persistent_mode = 1; afl->shmem_testcase_mode = 1; } else if (getenv("AFL_PERSISTENT")) { - WARNF("AFL_PERSISTENT is no longer supported and may misbehave!"); + OKF(cPIN "Persistent mode enforced."); + setenv(PERSIST_ENV_VAR, "1", 1); + afl->persistent_mode = 1; + afl->fsrv.persistent_mode = 1; + afl->shmem_testcase_mode = 1; } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) { OKF("FRIDA Persistent mode configuration options detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; - + afl->fsrv.persistent_mode = 1; afl->shmem_testcase_mode = 1; } @@ -2844,7 +2847,9 @@ void check_binary(afl_state_t *afl, u8 *fname) { } else if (getenv("AFL_DEFER_FORKSRV")) { - WARNF("AFL_DEFER_FORKSRV is no longer supported and may misbehave!"); + OKF(cPIN "Deferred forkserver enforced."); + setenv(DEFER_ENV_VAR, "1", 1); + afl->deferred_mode = 1; } diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 51a43dbd..e78e2dc4 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -428,7 +428,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf, if (likely(retlen)) { - write_to_testcase(afl, retbuf, retlen); + retlen = write_to_testcase(afl, retbuf, retlen, 0); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index eaa82b19..5da0e583 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -73,8 +73,8 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is rewound and truncated. */ -void __attribute__((hot)) -write_to_testcase(afl_state_t *afl, void *mem, u32 len) { +u32 __attribute__((hot)) +write_to_testcase(afl_state_t *afl, void *mem, u32 len, u32 fix) { #ifdef _AFL_DOCUMENT_MUTATIONS s32 doc_fd; @@ -120,16 +120,39 @@ write_to_testcase(afl_state_t *afl, void *mem, u32 len) { }); + if (unlikely(new_size < afl->min_length && !fix)) { + + new_size = afl->min_length; + + } else if (unlikely(new_size > afl->max_length)) { + + new_size = afl->max_length; + + } + /* everything as planned. use the potentially new data. */ afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size); + len = new_size; } else { + if (unlikely(len < afl->min_length && !fix)) { + + len = afl->min_length; + + } else if (unlikely(len > afl->max_length)) { + + len = afl->max_length; + + } + /* boring uncustom. */ afl_fsrv_write_to_testcase(&afl->fsrv, mem, len); } + return len; + } /* The same, but with an adjustable gap. Used for trimming. */ @@ -346,7 +369,7 @@ 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); + (void)write_to_testcase(afl, use_mem, q->len, 1); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); @@ -389,7 +412,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, u64 cksum; - write_to_testcase(afl, use_mem, q->len); + (void)write_to_testcase(afl, use_mem, q->len, 1); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); @@ -700,7 +723,7 @@ void sync_fuzzers(afl_state_t *afl) { /* See what happens. We rely on save_if_interesting() to catch major errors and save the test case. */ - write_to_testcase(afl, mem, st.st_size); + (void)write_to_testcase(afl, mem, st.st_size, 1); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); @@ -943,7 +966,7 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; - write_to_testcase(afl, out_buf, len); + len = write_to_testcase(afl, out_buf, len, 0); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 69ffa8cf..129e4c8b 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -102,6 +102,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_avg_exec = 0; afl->skip_deterministic = 1; afl->cmplog_lvl = 2; + afl->min_length = 1; + afl->max_length = MAX_FILE; #ifndef NO_SPLICING afl->use_splicing = 1; #endif @@ -480,6 +482,20 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_target_env = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_INPUT_LEN_MIN", + + afl_environment_variable_len)) { + + afl->min_length = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); + + } else if (!strncmp(env, "AFL_INPUT_LEN_MAX", + + afl_environment_variable_len)) { + + afl->max_length = + atoi((u8 *)get_afl_env(afl_environment_variables[i])); + } } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9ef2669a..c73ab38b 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -155,6 +155,9 @@ static void usage(u8 *argv0, int more_help) { "\n" "Mutator settings:\n" + " -g minlength - set min length of generated fuzz input (default: 1)\n" + " -G maxlength - set max length of generated fuzz input (default: " + "%lu)\n" " -D - enable deterministic fuzzing (once per queue entry)\n" " -L minutes - use MOpt(imize) mode and set the time limit for " "entering the\n" @@ -198,13 +201,13 @@ static void usage(u8 *argv0, int more_help) { " -I command - execute this command/script when a new crash is " "found\n" //" -B bitmap.txt - mutate a specific test case, use the - //out/default/fuzz_bitmap file\n" + // out/default/fuzz_bitmap file\n" " -C - crash exploration mode (the peruvian rabbit thing)\n" " -b cpu_id - bind the fuzzing process to the specified CPU core " "(0-...)\n" " -e ext - file extension for the fuzz test input file (if " "needed)\n\n", - argv0, EXEC_TIMEOUT, MEM_LIMIT, FOREIGN_SYNCS_MAX); + argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX); if (more_help > 1) { @@ -253,6 +256,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n" "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected during a run\n" "AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n" + "AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n" "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" " the target was compiled for\n" @@ -290,8 +294,10 @@ static void usage(u8 *argv0, int more_help) { " 'signalfx' and 'influxdb'\n" "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n" "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n" - //"AFL_PERSISTENT: not supported anymore -> no effect, just a warning\n" - //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n" + "AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n" + " afl-clang-lto/afl-gcc-fast target\n" + "AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n" + "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so\n" "\n" ); @@ -527,13 +533,22 @@ int main(int argc, char **argv_orig, char **envp) { afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing - while ((opt = getopt( - argc, argv, - "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOXYo:p:RQs:S:t:T:UV:Wx:Z")) > - 0) { + while ( + (opt = getopt( + argc, argv, + "+Ab:B:c:CdDe:E:hi:I:f:F:g:G:l:L:m:M:nNOo:p:RQs:S:t:T:UV:WXx:YZ")) > + 0) { switch (opt) { + case 'g': + afl->min_length = atoi(optarg); + break; + + case 'G': + afl->max_length = atoi(optarg); + break; + case 'Z': afl->old_seed_selection = 1; break; @@ -1622,6 +1637,16 @@ int main(int argc, char **argv_orig, char **envp) { } + OKF("Generating fuzz data with a a length of min=%u max=%u", afl->min_length, + afl->max_length); + u32 min_alloc = MAX(64U, afl->min_length); + afl_realloc(AFL_BUF_PARAM(in_scratch), min_alloc); + afl_realloc(AFL_BUF_PARAM(in), min_alloc); + afl_realloc(AFL_BUF_PARAM(out_scratch), min_alloc); + afl_realloc(AFL_BUF_PARAM(out), min_alloc); + afl_realloc(AFL_BUF_PARAM(eff), min_alloc); + afl_realloc(AFL_BUF_PARAM(ex), min_alloc); + afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver; #ifdef __linux__ |