mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-15 11:28:08 +00:00
Better handling of exit codes used by sanitzers
This commit is contained in:
@ -247,6 +247,12 @@ CFISAN. You might need to experiment which sanitizers you can combine in a
|
||||
target (which means more instances can be run without a sanitized target, which
|
||||
is more effective).
|
||||
|
||||
Note that some sanitizers (MSAN and LSAN) exit with a particular exit code
|
||||
instead of aborting. afl-fuzz treats these exit codes as a crash when these
|
||||
sanitizers are enabled. If the target uses these exit codes there could be false
|
||||
positives among the saved crashes. LSAN uses exit code 23 and MSAN uses exit
|
||||
code 86.
|
||||
|
||||
### d) Modifying the target
|
||||
|
||||
If the target has features that make fuzzing more difficult, e.g., checksums,
|
||||
|
@ -137,6 +137,8 @@ typedef struct afl_forkserver {
|
||||
|
||||
u8 last_kill_signal; /* Signal that killed the child */
|
||||
|
||||
u8 last_exit_code; /* Child exit code if counted as a crash */
|
||||
|
||||
bool use_shmem_fuzz; /* use shared mem for test cases */
|
||||
|
||||
bool support_shmem_fuzz; /* set by afl-fuzz */
|
||||
@ -155,7 +157,7 @@ typedef struct afl_forkserver {
|
||||
|
||||
bool no_unlink; /* do not unlink cur_input */
|
||||
|
||||
bool uses_asan; /* Target uses ASAN? */
|
||||
u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */
|
||||
|
||||
bool debug; /* debug mode? */
|
||||
|
||||
|
@ -258,7 +258,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
|
||||
fsrv->last_run_timed_out = false;
|
||||
fsrv->debug = false;
|
||||
fsrv->uses_crash_exitcode = false;
|
||||
fsrv->uses_asan = false;
|
||||
fsrv->uses_asan = 0;
|
||||
|
||||
#ifdef __AFL_CODE_COVERAGE
|
||||
fsrv->persistent_trace_bits = NULL;
|
||||
@ -2087,17 +2087,19 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
|
||||
|
||||
/* Did we crash?
|
||||
In a normal case, (abort) WIFSIGNALED(child_status) will be set.
|
||||
MSAN in uses_asan mode uses a special exit code as it doesn't support
|
||||
MSAN & LSAN in uses_asan mode use special exit codes as they doesn't support
|
||||
abort_on_error. On top, a user may specify a custom AFL_CRASH_EXITCODE.
|
||||
Handle all three cases here. */
|
||||
Handle all four cases here. */
|
||||
|
||||
if (unlikely(
|
||||
/* A normal crash/abort */
|
||||
(WIFSIGNALED(fsrv->child_status)) ||
|
||||
/* special handling for msan and lsan */
|
||||
(fsrv->uses_asan &&
|
||||
(WEXITSTATUS(fsrv->child_status) == MSAN_ERROR ||
|
||||
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) ||
|
||||
/* special handling for msan */
|
||||
((fsrv->uses_asan & 4) &&
|
||||
WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
|
||||
/* special handling for lsan */
|
||||
((fsrv->uses_asan & 2) &&
|
||||
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR) ||
|
||||
/* the custom crash_exitcode was returned by the target */
|
||||
(fsrv->uses_crash_exitcode &&
|
||||
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
|
||||
@ -2106,6 +2108,10 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
|
||||
fsrv->last_kill_signal =
|
||||
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
|
||||
|
||||
/* For a special exit code, set last_exit_code to non-zero */
|
||||
fsrv->last_exit_code =
|
||||
WIFSIGNALED(fsrv->child_status) ? 0 : WEXITSTATUS(fsrv->child_status);
|
||||
|
||||
#ifdef AFL_PERSISTENT_RECORD
|
||||
if (unlikely(fsrv->persistent_record)) {
|
||||
|
||||
|
@ -1042,6 +1042,47 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
|
||||
if (afl->crash_mode) { break; }
|
||||
|
||||
const u8 *msg_exit_code = "";
|
||||
|
||||
if (afl->fsrv.uses_asan && !afl->fsrv.last_kill_signal) {
|
||||
|
||||
if ((afl->fsrv.uses_asan & 4) &&
|
||||
afl->fsrv.last_exit_code == MSAN_ERROR) {
|
||||
|
||||
msg_exit_code =
|
||||
" - The test case terminated with the exit code that is "
|
||||
"used by MSAN to\n"
|
||||
" indicate an error. This is counted as a crash by "
|
||||
"afl-fuzz because you\n"
|
||||
" have compiled the target with MSAN enabled. This could "
|
||||
"be a false\n"
|
||||
" positive if the program returns this exit code under "
|
||||
"normal operation.\n"
|
||||
" In that case, either disable MSAN or change the test "
|
||||
"case or program\n"
|
||||
" to avoid generating this exit code.\n\n";
|
||||
|
||||
} else if ((afl->fsrv.uses_asan & 2) &&
|
||||
|
||||
afl->fsrv.last_exit_code == LSAN_ERROR) {
|
||||
|
||||
msg_exit_code =
|
||||
" - The test case terminated with the exit code that is "
|
||||
"used by LSAN to\n"
|
||||
" indicate an error. This is counted as a crash by "
|
||||
"afl-fuzz because you\n"
|
||||
" have compiled the target with LSAN enabled. This could "
|
||||
"be a false\n"
|
||||
" positive if the program returns this exit code under "
|
||||
"normal operation.\n"
|
||||
" In that case, either disable LSAN or change the test "
|
||||
"case or program\n"
|
||||
" to avoid generating this exit code.\n\n";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (afl->fsrv.mem_limit) {
|
||||
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
@ -1056,6 +1097,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
" so, please remove it. The fuzzer should be seeded with "
|
||||
"interesting\n"
|
||||
" inputs - but not ones that cause an outright crash.\n\n"
|
||||
"%s"
|
||||
|
||||
" - The current memory limit (%s) is too low for this "
|
||||
"program, causing\n"
|
||||
@ -1085,6 +1127,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
"other options\n"
|
||||
" fail, poke the Awesome Fuzzing Discord for "
|
||||
"troubleshooting tips.\n",
|
||||
msg_exit_code,
|
||||
stringify_mem_size(val_buf, sizeof(val_buf),
|
||||
afl->fsrv.mem_limit << 20),
|
||||
afl->fsrv.mem_limit - 1);
|
||||
@ -1101,6 +1144,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
" so, please remove it. The fuzzer should be seeded with "
|
||||
"interesting\n"
|
||||
" inputs - but not ones that cause an outright crash.\n\n"
|
||||
"%s"
|
||||
|
||||
" - In QEMU persistent mode the selected address(es) for the "
|
||||
"loop are not\n"
|
||||
@ -1113,7 +1157,8 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
" - Least likely, there is a horrible bug in the fuzzer. If "
|
||||
"other options\n"
|
||||
" fail, poke the Awesome Fuzzing Discord for "
|
||||
"troubleshooting tips.\n");
|
||||
"troubleshooting tips.\n",
|
||||
msg_exit_code);
|
||||
|
||||
}
|
||||
|
||||
@ -3118,11 +3163,23 @@ void check_binary(afl_state_t *afl, u8 *fname) {
|
||||
|
||||
}
|
||||
|
||||
if (afl_memmem(f_data, f_len, "__asan_init", 11) ||
|
||||
afl_memmem(f_data, f_len, "__msan_init", 11) ||
|
||||
afl_memmem(f_data, f_len, "__lsan_init", 11)) {
|
||||
afl->fsrv.uses_asan = 0;
|
||||
|
||||
afl->fsrv.uses_asan = 1;
|
||||
if (afl_memmem(f_data, f_len, "__asan_init", 11)) {
|
||||
|
||||
afl->fsrv.uses_asan |= 1;
|
||||
|
||||
}
|
||||
|
||||
if (afl_memmem(f_data, f_len, "__lsan_init", 11)) {
|
||||
|
||||
afl->fsrv.uses_asan |= 2;
|
||||
|
||||
}
|
||||
|
||||
if (afl_memmem(f_data, f_len, "__msan_init", 11)) {
|
||||
|
||||
afl->fsrv.uses_asan |= 4;
|
||||
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user