From f80f62f14bb5222344925a7ec51c81aa2f95d86e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Wed, 18 Nov 2020 03:02:13 +0100 Subject: renamed env var to AFL_DEBUG_CHILD --- include/envs.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'include/envs.h') diff --git a/include/envs.h b/include/envs.h index b753d5f8..8255cf4f 100644 --- a/include/envs.h +++ b/include/envs.h @@ -6,6 +6,7 @@ static char *afl_environment_deprecated[] = { "AFL_LLVM_WHITELIST", "AFL_GCC_WHITELIST", + "AFL_DEBUG_CHILD_OUTPUT", "AFL_DEFER_FORKSRV", "AFL_POST_LIBRARY", "AFL_PERSISTENT", @@ -36,7 +37,7 @@ static char *afl_environment_variables[] = { "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG", - "AFL_DEBUG_CHILD_OUTPUT", + "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DISABLE_TRIM", "AFL_DONT_OPTIMIZE", -- cgit 1.4.1 From 8584f9d2b5de9687c518c672e471f4f8cd9166fa Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 1 Dec 2020 13:13:11 +0100 Subject: added AFL_NO_AUTODICT --- docs/Changelog.md | 1 + docs/env_variables.md | 3 + include/envs.h | 1 + instrumentation/README.lto.md | 33 +++++++---- src/afl-forkserver.c | 125 ++++++++++++++++++++++-------------------- src/afl-fuzz.c | 1 + 6 files changed, 95 insertions(+), 69 deletions(-) (limited to 'include/envs.h') diff --git a/docs/Changelog.md b/docs/Changelog.md index 3c20f8bd..7fa7ff53 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -34,6 +34,7 @@ sending a mail to . - crashing seeds are now not prohibiting a run anymore but are skipped. They are used for splicing though. - update MOpt for expanded havoc modes + - setting the env var AFL_NO_AUTODICT will not load an LTO autodictionary - added NO_SPLICING compile option and makefile define - added INTROSPECTION make target that writes all mutations to out/NAME/introspection.txt diff --git a/docs/env_variables.md b/docs/env_variables.md index 04ba032a..f7b4c994 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -294,6 +294,9 @@ checks or alter some of the more exotic semantics of the tool: on Linux systems. This slows things down, but lets you run more instances of afl-fuzz than would be prudent (if you really want to). + - Setting `AFL_NO_AUTODICT` will not load an LTO generated auto dictionary + that is compiled into the target. + - `AFL_SKIP_CRASHES` causes AFL++ to tolerate crashing files in the input queue. This can help with rare situations where a program crashes only intermittently, but it's not really recommended under normal operating diff --git a/include/envs.h b/include/envs.h index 8255cf4f..3aa05cb5 100644 --- a/include/envs.h +++ b/include/envs.h @@ -100,6 +100,7 @@ static char *afl_environment_variables[] = { "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", + "AFL_NO_AUTODICT", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md index abdbd2ac..62e98902 100644 --- a/instrumentation/README.lto.md +++ b/instrumentation/README.lto.md @@ -60,7 +60,12 @@ AUTODICTIONARY: 11 strings found ## Getting llvm 11+ -### Installing llvm from the llvm repository (version 11) +### Installing llvm version 11 + +llvm 11 should be available in all current Linux repository. +If you use an outdated Linux distribution read the next section. + +### Installing llvm from the llvm repository (version 12) Installing the llvm snapshot builds is easy and mostly painless: @@ -73,11 +78,11 @@ then add the pgp key of llvm and install the packages: ``` wget -O - https://apt.llvm.org/llvm-snapshot.gpg.key | apt-key add - apt-get update && apt-get upgrade -y -apt-get install -y clang-11 clang-tools-11 libc++1-11 libc++-11-dev \ - libc++abi1-11 libc++abi-11-dev libclang1-11 libclang-11-dev \ - libclang-common-11-dev libclang-cpp11 libclang-cpp11-dev liblld-11 \ - liblld-11-dev liblldb-11 liblldb-11-dev libllvm11 libomp-11-dev \ - libomp5-11 lld-11 lldb-11 llvm-11 llvm-11-dev llvm-11-runtime llvm-11-tools +apt-get install -y clang-12 clang-tools-12 libc++1-12 libc++-12-dev \ + libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \ + libclang-common-12-dev libclang-cpp11 libclang-cpp11-dev liblld-12 \ + liblld-12-dev liblldb-12 liblldb-12-dev libllvm11 libomp-12-dev \ + libomp5-12 lld-12 lldb-12 llvm-12 llvm-12-dev llvm-12-runtime llvm-12-tools ``` ### Building llvm yourself (version 12) @@ -120,16 +125,22 @@ While compiling, a dictionary based on string comparisons is automatically generated and put into the target binary. This dictionary is transfered to afl-fuzz on start. This improves coverage statistically by 5-10% :) +Note that if for any reason you do not want to use the autodictionary feature +then just set the environment variable `AFL_NO_AUTODICT` when starting afl-fuzz. + ## Fixed memory map -To speed up fuzzing, it is possible to set a fixed shared memory map. +To speed up fuzzing a little bit more, it is possible to set a fixed shared +memory map. Recommended is the value 0x10000. + In most cases this will work without any problems. However if a target uses early constructors, ifuncs or a deferred forkserver this can crash the target. -On unusual operating systems/processors/kernels or weird libraries this might -fail so to change the fixed address at compile time set -AFL_LLVM_MAP_ADDR with a better value (a value of 0 or empty sets the map address -to be dynamic - the original afl way, which is slower). + +Also on unusual operating systems/processors/kernels or weird libraries the +recommended 0x10000 address might not work, so then change the fixed address. + +To enable this feature set AFL_LLVM_MAP_ADDR with the address. ## Document edge IDs diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 3814a77e..01ef1d9e 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -348,9 +348,10 @@ static void report_error_and_exit(int error) { void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output) { - int st_pipe[2], ctl_pipe[2]; - s32 status; - s32 rlen; + int st_pipe[2], ctl_pipe[2]; + s32 status; + s32 rlen; + char *ignore_autodict = getenv("AFL_NO_AUTODICT"); if (!be_quiet) { ACTF("Spinning up the fork server..."); } @@ -607,7 +608,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, fsrv->use_shmem_fuzz = 1; if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); } - if ((status & FS_OPT_AUTODICT) == 0) { + if ((status & FS_OPT_AUTODICT) == 0 || ignore_autodict) { u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) { @@ -660,101 +661,109 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_AUTODICT) == FS_OPT_AUTODICT) { - if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) { + if (ignore_autodict) { - // this is not afl-fuzz - or it is cmplog - we deny and return - if (fsrv->use_shmem_fuzz) { + if (!be_quiet) { WARNF("Ignoring offered AUTODICT feature."); } - status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + } else { - } else { + if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) { - status = (FS_OPT_ENABLED); + // this is not afl-fuzz - or it is cmplog - we deny and return + if (fsrv->use_shmem_fuzz) { - } + status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); - if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + } else { - FATAL("Writing to forkserver failed."); + status = (FS_OPT_ENABLED); - } + } - return; + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { - } + FATAL("Writing to forkserver failed."); - if (!be_quiet) { ACTF("Using AUTODICT feature."); } + } - if (fsrv->use_shmem_fuzz) { + return; - status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); + } - } else { + if (!be_quiet) { ACTF("Using AUTODICT feature."); } - status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); + if (fsrv->use_shmem_fuzz) { - } + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); - if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + } else { - FATAL("Writing to forkserver failed."); + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); - } + } - if (read(fsrv->fsrv_st_fd, &status, 4) != 4) { + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { - FATAL("Reading from forkserver failed."); + FATAL("Writing to forkserver failed."); - } + } - if (status < 2 || (u32)status > 0xffffff) { + if (read(fsrv->fsrv_st_fd, &status, 4) != 4) { - FATAL("Dictionary has an illegal size: %d", status); + FATAL("Reading from forkserver failed."); - } + } - u32 offset = 0, count = 0; - u32 len = status; - u8 *dict = ck_alloc(len); - if (dict == NULL) { + if (status < 2 || (u32)status > 0xffffff) { - FATAL("Could not allocate %u bytes of autodictionary memory", len); + FATAL("Dictionary has an illegal size: %d", status); - } + } - while (len != 0) { + u32 offset = 0, count = 0; + u32 len = status; + u8 *dict = ck_alloc(len); + if (dict == NULL) { - rlen = read(fsrv->fsrv_st_fd, dict + offset, len); - if (rlen > 0) { + FATAL("Could not allocate %u bytes of autodictionary memory", len); - len -= rlen; - offset += rlen; + } - } else { + while (len != 0) { - FATAL( - "Reading autodictionary fail at position %u with %u bytes " - "left.", - offset, len); + rlen = read(fsrv->fsrv_st_fd, dict + offset, len); + if (rlen > 0) { + + len -= rlen; + offset += rlen; + + } else { + + FATAL( + "Reading autodictionary fail at position %u with %u bytes " + "left.", + offset, len); + + } } - } + offset = 0; + while (offset < (u32)status && + (u8)dict[offset] + offset < (u32)status) { + + fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, + (u8)dict[offset]); + offset += (1 + dict[offset]); + count++; - offset = 0; - while (offset < (u32)status && - (u8)dict[offset] + offset < (u32)status) { + } - fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1, - (u8)dict[offset]); - offset += (1 + dict[offset]); - count++; + if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } + ck_free(dict); } - if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } - ck_free(dict); - } } diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b60908da..b91d862d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -187,6 +187,7 @@ static void usage(u8 *argv0, int more_help) { " used. Defaults to 200.\n" "AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n" "AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n" + "AFL_NO_AUTODICT: do not load an offered auto dictionary compiled into a target\n" "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" -- cgit 1.4.1 From a2e2fae840e9946c7994ac6807bed8496d71af56 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Thu, 3 Dec 2020 14:43:06 +0100 Subject: AFL_CRASH_EXITCODE env var added, u8->bool --- .gitignore | 1 + afl-cmin | 5 +++-- docs/Changelog.md | 4 +++- docs/env_variables.md | 7 +++++++ include/afl-fuzz.h | 7 ++++--- include/common.h | 2 +- include/envs.h | 1 + include/forkserver.h | 21 +++++++++++++-------- src/afl-analyze.c | 4 ++-- src/afl-common.c | 4 ++-- src/afl-forkserver.c | 22 +++++++++++++++------- src/afl-fuzz-init.c | 27 +++++++++++++++++++++++++-- src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz.c | 26 ++++++++++++++++++++++++-- src/afl-showmap.c | 19 +++++++++++++++++++ src/afl-tmin.c | 32 +++++++++++++++++++++++++------- 16 files changed, 152 insertions(+), 37 deletions(-) (limited to 'include/envs.h') diff --git a/.gitignore b/.gitignore index 97f99bf6..82a81605 100644 --- a/.gitignore +++ b/.gitignore @@ -8,6 +8,7 @@ *.pyc *.dSYM as +a.out ld in out diff --git a/afl-cmin b/afl-cmin index 91ed8d6d..b3b1ead8 100755 --- a/afl-cmin +++ b/afl-cmin @@ -116,11 +116,12 @@ function usage() { "For additional tips, please consult README.md\n" \ "\n" \ "Environment variables used:\n" \ +"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \ +"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \ +"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \ "AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \ "AFL_PATH: path for the afl-showmap binary\n" \ "AFL_SKIP_BIN_CHECK: skip check for target binary\n" \ -"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" -"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" exit 1 } diff --git a/docs/Changelog.md b/docs/Changelog.md index fd30c7b0..02728f10 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -60,8 +60,10 @@ sending a mail to . - Our afl++ Grammar-Mutator is now better integrated into custom_mutators/ - added INTROSPECTION support for custom modules - python fuzz function was not optional, fixed - - unicornafl synced with upstream (arm64 fix, better rust bindings) + - some python mutator speed improvements + - unicornafl synced with upstream version 1.02 (fixes, better rust bindings) - renamed AFL_DEBUG_CHILD_OUTPUT to AFL_DEBUG_CHILD + - added AFL_CRASH_EXITCODE env variable to treat a child exitcode as crash ### Version ++2.68c (release) diff --git a/docs/env_variables.md b/docs/env_variables.md index ada89257..e203055f 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -428,6 +428,13 @@ checks or alter some of the more exotic semantics of the tool: matches your StatsD server. Available flavors are `dogstatsd`, `librato`, `signalfx` and `influxdb`. + - Setting `AFL_CRASH_EXITCODE` sets the exit code afl treats as crash. + For example, if `AFL_CRASH_EXITCODE='-1'` is set, each input resulting + in an `-1` return code (i.e. `exit(-1)` got called), will be treated + as if a crash had ocurred. + This may be beneficial if you look for higher-level faulty conditions in which your + target still exits gracefully. + - Outdated environment variables that are not supported anymore: `AFL_DEFER_FORKSRV` `AFL_PERSISTENT` diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 933af65d..62d76323 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -144,8 +144,8 @@ struct queue_entry { u8 *fname; /* File name for the test case */ u32 len; /* Input length */ - u8 cal_failed, /* Calibration failed? */ - trim_done, /* Trimmed? */ + u8 cal_failed; /* Calibration failed? */ + bool trim_done, /* Trimmed? */ was_fuzzed, /* historical, but needed for MOpt */ passed_det, /* Deterministic stages passed? */ has_new_cov, /* Triggers new coverage? */ @@ -368,7 +368,8 @@ typedef struct afl_env_vars { u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, - *afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries; + *afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size, + *afl_testcache_entries; } afl_env_vars_t; diff --git a/include/common.h b/include/common.h index c364ade0..6e5039d8 100644 --- a/include/common.h +++ b/include/common.h @@ -38,7 +38,7 @@ #define STRINGIFY_VAL_SIZE_MAX (16) -void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin); +void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin); void check_environment_vars(char **env); char **argv_cpy_dup(int argc, char **argv); diff --git a/include/envs.h b/include/envs.h index 3aa05cb5..43c87148 100644 --- a/include/envs.h +++ b/include/envs.h @@ -32,6 +32,7 @@ static char *afl_environment_variables[] = { "AFL_CODE_START", "AFL_COMPCOV_BINNAME", "AFL_COMPCOV_LEVEL", + "AFL_CRASH_EXITCODE", "AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY", "AFL_CXX", diff --git a/include/forkserver.h b/include/forkserver.h index 300ecffc..5d5c728f 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -37,9 +37,7 @@ typedef struct afl_forkserver { /* a program that includes afl-forkserver needs to define these */ - u8 uses_asan; /* Target uses ASAN? */ u8 *trace_bits; /* SHM with instrumentation bitmap */ - u8 use_stdin; /* use stdin for sending data */ s32 fsrv_pid, /* PID of the fork server */ child_pid, /* PID of the fuzzed program */ @@ -53,8 +51,6 @@ typedef struct afl_forkserver { fsrv_ctl_fd, /* Fork server control pipe (write) */ fsrv_st_fd; /* Fork server status pipe (read) */ - u8 no_unlink; /* do not unlink cur_input */ - u32 exec_tmout; /* Configurable exec timeout (ms) */ u32 init_tmout; /* Configurable init timeout (ms) */ u32 map_size; /* map size used by the target */ @@ -73,13 +69,22 @@ typedef struct afl_forkserver { u8 last_kill_signal; /* Signal that killed the child */ - u8 use_shmem_fuzz; /* use shared mem for test cases */ + bool use_shmem_fuzz; /* use shared mem for test cases */ + + bool support_shmem_fuzz; /* set by afl-fuzz */ + + bool use_fauxsrv; /* Fauxsrv for non-forking targets? */ + + bool qemu_mode; /* if running in qemu mode or not */ + + bool use_stdin; /* use stdin for sending data */ - u8 support_shmem_fuzz; /* set by afl-fuzz */ + bool no_unlink; /* do not unlink cur_input */ - u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */ + bool uses_asan; /* Target uses ASAN? */ - u8 qemu_mode; /* if running in qemu mode or not */ + bool uses_crash_exitcode; /* Custom crash exitcode specified? */ + u8 crash_exitcode; /* The crash exitcode specified */ u32 *shmem_fuzz_len; /* length of the fuzzing test case */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index c8acebb3..2780deff 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -78,9 +78,9 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */ static s32 dev_null_fd = -1; /* FD to /dev/null */ -static u8 edges_only, /* Ignore hit counts? */ +static bool edges_only, /* Ignore hit counts? */ use_hex_offsets, /* Show hex offsets? */ - use_stdin = 1; /* Use stdin for program input? */ + use_stdin = true; /* Use stdin for program input? */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_timed_out; /* Child timed out? */ diff --git a/src/afl-common.c b/src/afl-common.c index 8cf1a444..ed0b0e53 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -46,7 +46,7 @@ u8 be_quiet = 0; u8 *doc_path = ""; u8 last_intr = 0; -void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) { +void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) { u32 i = 0; u8 cwd[PATH_MAX]; @@ -63,7 +63,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) { if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); } - *use_stdin = 0; + *use_stdin = false; if (prog_in[0] != 0) { // not afl-showmap special case diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 01ef1d9e..20117c1d 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -76,8 +76,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { fsrv->dev_urandom_fd = -1; /* Settings */ - fsrv->use_stdin = 1; - fsrv->no_unlink = 0; + fsrv->use_stdin = true; + fsrv->no_unlink = false; fsrv->exec_tmout = EXEC_TIMEOUT; fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT; fsrv->mem_limit = MEM_LIMIT; @@ -86,8 +86,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { /* exec related stuff */ fsrv->child_pid = -1; fsrv->map_size = get_map_size(); - fsrv->use_fauxsrv = 0; - fsrv->last_run_timed_out = 0; + fsrv->use_fauxsrv = false; + fsrv->last_run_timed_out = false; + + fsrv->uses_crash_exitcode = false; + fsrv->uses_asan = false; fsrv->init_child_func = fsrv_exec_child; @@ -109,6 +112,8 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->dev_urandom_fd = from->dev_urandom_fd; fsrv_to->out_fd = from->out_fd; // not sure this is a good idea fsrv_to->no_unlink = from->no_unlink; + fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode; + fsrv_to->crash_exitcode = from->crash_exitcode; // These are forkserver specific. fsrv_to->out_dir_fd = -1; @@ -1136,10 +1141,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - /* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and - must use a special exit code. */ + /* MSAN in uses_asan mode uses a special exit code as it doesn't support + abort_on_error. + On top, a user may specify a custom AFL_CRASH_EXITCODE. Handle both here. */ - if (fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) { + if ((fsrv->uses_asan && WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) || + (fsrv->uses_crash_exitcode && + WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode)) { fsrv->last_kill_signal = 0; return FSRV_RUN_CRASH; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 0360cdb0..6707340b 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -868,7 +868,19 @@ void perform_dry_run(afl_state_t *afl) { if (skip_crashes) { - WARNF("Test case results in a crash (skipping)"); + if (afl->fsrv.uses_crash_exitcode) { + + WARNF( + "Test case results in a crash or AFL_CRASH_EXITCODE %d " + "(skipping)", + (int)(s8)afl->fsrv.crash_exitcode); + + } else { + + WARNF("Test case results in a crash (skipping)"); + + } + q->cal_failed = CAL_CHANCES; ++cal_failures; break; @@ -954,7 +966,18 @@ void perform_dry_run(afl_state_t *afl) { #undef MSG_ULIMIT_USAGE #undef MSG_FORK_ON_APPLE - WARNF("Test case '%s' results in a crash, skipping", fn); + if (afl->fsrv.uses_crash_exitcode) { + + WARNF( + "Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, " + "skipping", + fn, (int)(s8)afl->fsrv.crash_exitcode); + + } else { + + WARNF("Test case '%s' results in a crash, skipping", fn); + + } /* Remove from fuzzing queue but keep for splicing */ diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 489d4e53..73b94466 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -394,6 +394,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_statsd_tags_flavor = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_CRASH_EXITCODE", + + afl_environment_variable_len)) { + + afl->afl_env.afl_crash_exitcode = + (u8 *)get_afl_env(afl_environment_variables[i]); + } } else { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index b91d862d..eb5e9307 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -26,6 +26,7 @@ #include "afl-fuzz.h" #include "cmplog.h" #include +#include #ifndef USEMMAP #include #include @@ -165,6 +166,7 @@ static void usage(u8 *argv0, int more_help) { "AFL_AUTORESUME: resume fuzzing if directory specified by -o already exists\n" "AFL_BENCH_JUST_ONE: run the target just once\n" "AFL_BENCH_UNTIL_CRASH: exit soon when the first crashing input has been found\n" + "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" "AFL_CUSTOM_MUTATOR_LIBRARY: lib with afl_custom_fuzz() to mutate inputs\n" "AFL_CUSTOM_MUTATOR_ONLY: avoid AFL++'s internal mutators\n" "AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n" @@ -702,7 +704,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'N': /* Unicorn mode */ if (afl->no_unlink) { FATAL("Multiple -N options not supported"); } - afl->fsrv.no_unlink = afl->no_unlink = 1; + afl->fsrv.no_unlink = (afl->no_unlink = true); break; @@ -1135,6 +1137,23 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->afl_env.afl_crash_exitcode) { + + long exitcode = strtol(afl->afl_env.afl_crash_exitcode, NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + afl->afl_env.afl_crash_exitcode); + + } + + afl->fsrv.uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + afl->fsrv.crash_exitcode = (u8)exitcode; + + } + if (afl->non_instrumented_mode == 2 && afl->no_forkserver) { FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); @@ -1486,9 +1505,12 @@ int main(int argc, char **argv_orig, char **envp) { cull_queue(afl); - if (!afl->pending_not_fuzzed) + if (!afl->pending_not_fuzzed) { + FATAL("We need at least on valid input seed that does not crash!"); + } + show_init_stats(afl); if (unlikely(afl->old_seed_selection)) seek_to = find_start_position(afl); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index a8e7d3f9..e07e76c8 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -667,6 +667,8 @@ static void usage(u8 *argv0) { "AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing " "inputs\n" "AFL_CMIN_ALLOW_ANY: (cmin_mode) write tuples for crashing inputs also\n" + "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as " + "crash\n" "AFL_DEBUG: enable extra developer output\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the " "size\n" @@ -1090,6 +1092,23 @@ int main(int argc, char **argv_orig, char **envp) { } + if (getenv("AFL_CRASH_EXITCODE")) { + + long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + getenv("AFL_CRASH_EXITCODE")); + + } + + fsrv->uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + fsrv->crash_exitcode = (u8)exitcode; + + } + afl_fsrv_start(fsrv, use_argv, &stop_soon, (get_afl_env("AFL_DEBUG_CHILD") || get_afl_env("AFL_DEBUG_CHILD_OUTPUT")) diff --git a/src/afl-tmin.c b/src/afl-tmin.c index e4fb068d..b9045551 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -51,6 +51,7 @@ #include #include #include +#include #include #include @@ -841,17 +842,17 @@ static void usage(u8 *argv0) { "For additional tips, please consult %s/README.md.\n\n" "Environment variables used:\n" - "TMPDIR: directory to use for temporary input files\n" - "ASAN_OPTIONS: custom settings for ASAN\n" - " (must contain abort_on_error=1 and symbolize=0)\n" - "MSAN_OPTIONS: custom settings for MSAN\n" - " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" + "AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" + "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" "AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n" " the target was compiled for\n" "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n" - "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n" - + "ASAN_OPTIONS: custom settings for ASAN\n" + " (must contain abort_on_error=1 and symbolize=0)\n" + "MSAN_OPTIONS: custom settings for MSAN\n" + " (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n" + "TMPDIR: directory to use for temporary input files\n" , argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path); exit(1); @@ -1122,6 +1123,23 @@ int main(int argc, char **argv_orig, char **envp) { } + if (getenv("AFL_CRASH_EXITCODE")) { + + long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10); + if ((!exitcode && (errno == EINVAL || errno == ERANGE)) || + exitcode < -127 || exitcode > 128) { + + FATAL("Invalid crash exitcode, expected -127 to 128, but got %s", + getenv("AFL_CRASH_EXITCODE")); + + } + + fsrv->uses_crash_exitcode = true; + // WEXITSTATUS is 8 bit unsigned + fsrv->crash_exitcode = (u8)exitcode; + + } + shm_fuzz = ck_alloc(sizeof(sharedmem_t)); /* initialize cmplog_mode */ -- cgit 1.4.1 From d59d1fcd9fa356b98380dd5ab2ca1d82b3b80747 Mon Sep 17 00:00:00 2001 From: Thomas Rooijakkers Date: Fri, 4 Dec 2020 17:11:09 +0100 Subject: Add missing env var used in https://github.com/qemu/qemu/blob/bec7edf41d2d0e8006637a739881abcea1d1305c/accel/tcg/cpu-exec.c#L389 and ./qemu_mode/README.persistent.md --- include/envs.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/envs.h') diff --git a/include/envs.h b/include/envs.h index 43c87148..c0f41ca5 100644 --- a/include/envs.h +++ b/include/envs.h @@ -126,6 +126,7 @@ static char *afl_environment_variables[] = { "AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK", + "AFL_QEMU_PERSISTENT_MEM", "AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS", -- cgit 1.4.1