unified forkservered run_target, fixes #308

This commit is contained in:
Dominik Maier
2020-04-14 19:27:25 +02:00
parent f4436f118c
commit 6dc36f1e6e
17 changed files with 222 additions and 354 deletions

View File

@ -195,18 +195,6 @@ enum {
};
/* Execution status fault codes */
enum {
/* 00 */ FAULT_NONE,
/* 01 */ FAULT_TMOUT,
/* 02 */ FAULT_CRASH,
/* 03 */ FAULT_ERROR,
/* 04 */ FAULT_NOINST,
/* 05 */ FAULT_NOBITS
};
#define operator_num 16
#define swarm_num 5
@ -433,7 +421,6 @@ typedef struct afl_state {
use_splicing, /* Recombine input files? */
dumb_mode, /* Run in non-instrumented mode? */
score_changed, /* Scoring for favorites changed? */
kill_signal, /* Signal that killed the child */
resuming_fuzz, /* Resuming an older fuzzing job? */
timeout_given, /* Specific timeout given? */
not_on_tty, /* stdout is not a tty */
@ -488,7 +475,6 @@ typedef struct afl_state {
total_tmouts, /* Total number of timeouts */
unique_tmouts, /* Timeouts with unique signatures */
unique_hangs, /* Hangs with unique signatures */
total_execs, /* Total execve() calls */
last_crash_execs, /* Exec counter at last crash */
queue_cycle, /* Queue round counter */
cycles_wo_finds, /* Cycles without any new paths */
@ -888,7 +874,7 @@ void show_init_stats(afl_state_t *);
/* Run */
u8 run_target(afl_state_t *, afl_forkserver_t *fsrv, u32);
fsrv_run_result_t run_target(afl_state_t *, afl_forkserver_t *fsrv, u32);
void write_to_testcase(afl_state_t *, void *, u32);
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
void sync_fuzzers(afl_state_t *);

View File

@ -29,6 +29,7 @@
#define __AFL_FORKSERVER_H
#include <stdio.h>
#include <stdbool.h>
typedef struct afl_forkserver {
@ -55,17 +56,19 @@ typedef struct afl_forkserver {
u32 snapshot; /* is snapshot feature used */
u64 mem_limit; /* Memory cap for child (MB) */
u64 total_execs; /* How often run_target was called */
u8 *out_file, /* File to fuzz, if any */
*target_path; /* Path of the target */
FILE *plot_file; /* Gnuplot output file */
u8 child_timed_out; /* Traced process timed out? */
u8 last_run_timed_out; /* Traced process timed out? */
u8 last_kill_signal; /* Signal that killed the child */
u8 use_fauxsrv; /* Fauxsrv for non-forking targets? */
u32 prev_timed_out; /* if prev forkserver run timed out */
u8 qemu_mode; /* if running in qemu mode or not */
char *cmplog_binary; /* the name of the cmplog binary */
@ -79,10 +82,22 @@ typedef struct afl_forkserver {
} afl_forkserver_t;
typedef enum fsrv_run_result {
/* 00 */ FSRV_RUN_OK = 0,
/* 01 */ FSRV_RUN_TMOUT,
/* 02 */ FSRV_RUN_CRASH,
/* 03 */ FSRV_RUN_ERROR,
/* 04 */ FSRV_RUN_NOINST,
/* 05 */ FSRV_RUN_NOBITS,
} fsrv_run_result_t;
void afl_fsrv_init(afl_forkserver_t *fsrv);
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
volatile u8 *stop_soon_p, u8 debug_child_output);
fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, volatile u8 *stop_soon_p);
void afl_fsrv_killall(void);
void afl_fsrv_deinit(afl_forkserver_t *fsrv);

View File

@ -76,7 +76,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->child_pid = -1;
fsrv->map_size = MAP_SIZE;
fsrv->use_fauxsrv = 0;
fsrv->prev_timed_out = 0;
fsrv->last_run_timed_out = 0;
fsrv->init_child_func = fsrv_exec_child;
@ -102,7 +102,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->out_dir_fd = -1;
fsrv_to->child_pid = -1;
fsrv_to->use_fauxsrv = 0;
fsrv_to->prev_timed_out = 0;
fsrv_to->last_run_timed_out = 0;
fsrv_to->init_child_func = fsrv_exec_child;
@ -217,7 +217,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed");
fsrv->child_timed_out = 0;
fsrv->last_run_timed_out = 0;
fsrv->fsrv_pid = fork();
if (fsrv->fsrv_pid < 0) PFATAL("fork() failed");
@ -361,7 +361,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} else if (time > fsrv->exec_tmout * FORK_WAIT_MULT) {
fsrv->child_timed_out = 1;
fsrv->last_run_timed_out = 1;
kill(fsrv->fsrv_pid, SIGKILL);
} else {
@ -476,7 +476,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
}
if (fsrv->child_timed_out)
if (fsrv->last_run_timed_out)
FATAL("Timeout while initializing fork server (adjusting -t may help)");
if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed");
@ -640,6 +640,127 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) {
}
/* 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, volatile u8 *stop_soon_p) {
s32 res;
u32 exec_ms;
int status = 0;
u32 timeout = fsrv->exec_tmout;
/* After this memset, fsrv->trace_bits[] are effectively volatile, so we
must prevent any earlier operations from venturing into that
territory. */
memset(fsrv->trace_bits, 0, fsrv->map_size);
MEM_BARRIER();
/* we have the fork server (or faux server) up and running
First, tell it if the previous run timed out. */
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) {
if (*stop_soon_p) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
fsrv->last_run_timed_out = 0;
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
if (stop_soon_p) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p);
if (exec_ms > timeout) {
/* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */
kill(fsrv->child_pid, SIGKILL);
fsrv->last_run_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
}
if (!exec_ms) {
if (*stop_soon_p) return 0;
SAYF("\n" cLRD "[-] " cRST
"Unable to communicate with fork server. Some possible reasons:\n\n"
" - You've run out of memory. Use -m to increase the the memory "
"limit\n"
" to something higher than %lld.\n"
" - The binary or one of the libraries it uses manages to "
"create\n"
" threads before the forkserver initializes.\n"
" - The binary, at least in some circumstances, exits in a way "
"that\n"
" also kills the parent process - raise() could be the "
"culprit.\n"
" - If using persistent mode with QEMU, "
"AFL_QEMU_PERSISTENT_ADDR "
"is\n"
" probably not valid (hint: add the base address in case of "
"PIE)"
"\n\n"
"If all else fails you can disable the fork server via "
"AFL_NO_FORKSRV=1.\n",
fsrv->mem_limit);
RPFATAL(res, "Unable to communicate with fork server");
}
if (!WIFSTOPPED(status)) fsrv->child_pid = 0;
fsrv->total_execs++;
/* Any subsequent operations on fsrv->trace_bits must not be moved by the
compiler below this point. Past this location, fsrv->trace_bits[]
behave very normally and do not have to be treated as volatile. */
MEM_BARRIER();
/* Report outcome to caller. */
if (WIFSIGNALED(status) && !*stop_soon_p) {
fsrv->last_kill_signal = WTERMSIG(status);
if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL)
return FSRV_RUN_TMOUT;
return FSRV_RUN_CRASH;
}
/* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
must use a special exit code. */
if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) {
fsrv->last_kill_signal = 0;
return FSRV_RUN_CRASH;
}
if ((*(u32 *)fsrv->trace_bits) == EXEC_FAIL_SIG) return FSRV_RUN_NOINST;
return FSRV_RUN_OK;
}
void afl_fsrv_killall() {
LIST_FOREACH(&fsrv_list, afl_forkserver_t, {
@ -656,4 +777,3 @@ void afl_fsrv_deinit(afl_forkserver_t *fsrv) {
list_remove(&fsrv_list, fsrv);
}

View File

@ -598,7 +598,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0);
if (unlikely(res == FAULT_ERROR))
if (unlikely(res == FSRV_RUN_ERROR))
FATAL("Unable to execute target application");
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
@ -612,7 +612,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
switch (fault) {
case FAULT_TMOUT:
case FSRV_RUN_TMOUT:
/* Timeouts are not very interesting, but we're still obliged to keep
a handful of samples. We use the presence of new bits in the
@ -651,9 +651,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
timeout actually uncovers a crash. Make sure we don't discard it if
so. */
if (!afl->stop_soon && new_fault == FAULT_CRASH) goto keep_as_crash;
if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) goto keep_as_crash;
if (afl->stop_soon || new_fault != FAULT_TMOUT) return keeping;
if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) return keeping;
}
@ -675,7 +675,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
break;
case FAULT_CRASH:
case FSRV_RUN_CRASH:
keep_as_crash:
@ -704,7 +704,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
#ifndef SIMPLE_FILES
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
afl->unique_crashes, afl->kill_signal, describe_op(afl, 0));
afl->unique_crashes, afl->fsrv.last_kill_signal, describe_op(afl, 0));
#else
@ -730,11 +730,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
afl->last_crash_time = get_cur_time();
afl->last_crash_execs = afl->total_execs;
afl->last_crash_execs = afl->fsrv.total_execs;
break;
case FAULT_ERROR: FATAL("Unable to execute target application");
case FSRV_RUN_ERROR: FATAL("Unable to execute target application");
default: return keeping;

View File

@ -66,7 +66,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
if (afl->stop_soon) return 1;
if (fault == FAULT_TMOUT) {
if (fault == FSRV_RUN_TMOUT) {
if (afl->subseq_tmouts++ > TMOUT_LIMIT) {

View File

@ -493,13 +493,13 @@ void perform_dry_run(afl_state_t *afl) {
if (afl->stop_soon) return;
if (res == afl->crash_mode || res == FAULT_NOBITS)
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS)
SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST,
q->len, q->bitmap_size, q->exec_us);
switch (res) {
case FAULT_NONE:
case FSRV_RUN_OK:
if (q == afl->queue) check_map_coverage(afl);
@ -507,7 +507,7 @@ void perform_dry_run(afl_state_t *afl) {
break;
case FAULT_TMOUT:
case FSRV_RUN_TMOUT:
if (afl->timeout_given) {
@ -556,7 +556,7 @@ void perform_dry_run(afl_state_t *afl) {
}
case FAULT_CRASH:
case FSRV_RUN_CRASH:
if (afl->crash_mode) break;
@ -650,13 +650,13 @@ void perform_dry_run(afl_state_t *afl) {
FATAL("Test case '%s' results in a crash", fn);
case FAULT_ERROR:
case FSRV_RUN_ERROR:
FATAL("Unable to execute target application ('%s')", afl->argv[0]);
case FAULT_NOINST: FATAL("No instrumentation detected");
case FSRV_RUN_NOINST: FATAL("No instrumentation detected");
case FAULT_NOBITS:
case FSRV_RUN_NOBITS:
++afl->useless_at_start;

View File

@ -242,7 +242,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs;
if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; }
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);

View File

@ -442,14 +442,14 @@ u8 fuzz_one_original(afl_state_t *afl) {
if (unlikely(afl->queue_cur->cal_failed)) {
u8 res = FAULT_TMOUT;
u8 res = FSRV_RUN_TMOUT;
if (afl->queue_cur->cal_failed < CAL_CHANCES) {
res =
calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
if (unlikely(res == FAULT_ERROR))
if (unlikely(res == FSRV_RUN_ERROR))
FATAL("Unable to execute target application");
}
@ -471,7 +471,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
u8 res = trim_case(afl, afl->queue_cur, in_buf);
if (unlikely(res == FAULT_ERROR))
if (unlikely(res == FSRV_RUN_ERROR))
FATAL("Unable to execute target application");
if (unlikely(afl->stop_soon)) {
@ -2469,14 +2469,14 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
if (afl->queue_cur->cal_failed) {
u8 res = FAULT_TMOUT;
u8 res = FSRV_RUN_TMOUT;
if (afl->queue_cur->cal_failed < CAL_CHANCES) {
res =
calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
if (res == FAULT_ERROR) FATAL("Unable to execute target application");
if (res == FSRV_RUN_ERROR) FATAL("Unable to execute target application");
}
@ -2497,7 +2497,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
u8 res = trim_case(afl, afl->queue_cur, in_buf);
if (res == FAULT_ERROR) FATAL("Unable to execute target application");
if (res == FSRV_RUN_ERROR) FATAL("Unable to execute target application");
if (afl->stop_soon) {

View File

@ -492,7 +492,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
// the more often fuzz result paths are equal to this queue entry,
// reduce its value
perf_score *=
(1 - (double)((double)q->n_fuzz / (double)afl->total_execs));
(1 - (double)((double)q->n_fuzz / (double)afl->fsrv.total_execs));
break;

View File

@ -622,7 +622,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1;
u64 orig_hit_cnt, new_hit_cnt;
u64 orig_execs = afl->total_execs;
u64 orig_execs = afl->fsrv.total_execs;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
afl->stage_name = "input-to-state";
@ -670,7 +670,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
exit_its:
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ITS] += afl->total_execs - orig_execs;
afl->stage_cycles[STAGE_ITS] += afl->fsrv.total_execs - orig_execs;
memcpy(orig_buf, buf, len);

View File

@ -32,95 +32,9 @@
/* Execute target application, monitoring for timeouts. Return status
information. The called program will update afl->fsrv->trace_bits. */
u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
fsrv_run_result_t run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
s32 res;
u32 exec_ms;
int status = 0;
u32 tb4;
fsrv->child_timed_out = 0;
/* After this memset, fsrv->trace_bits[] are effectively volatile, so we
must prevent any earlier operations from venturing into that
territory. */
memset(fsrv->trace_bits, 0, fsrv->map_size);
MEM_BARRIER();
/* we have the fork server (or faux server) up and running, so simply
tell it to have at it, and then read back PID. */
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
if (afl->stop_soon) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
if (afl->stop_soon) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, &afl->stop_soon);
if (exec_ms > timeout) {
/* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */
kill(fsrv->child_pid, SIGKILL);
fsrv->child_timed_out = 1;
if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
}
if (!exec_ms) {
if (afl->stop_soon) return 0;
SAYF("\n" cLRD "[-] " cRST
"Unable to communicate with fork server. Some possible reasons:\n\n"
" - You've run out of memory. Use -m to increase the the memory "
"limit\n"
" to something higher than %lld.\n"
" - The binary or one of the libraries it uses manages to "
"create\n"
" threads before the forkserver initializes.\n"
" - The binary, at least in some circumstances, exits in a way "
"that\n"
" also kills the parent process - raise() could be the "
"culprit.\n"
" - If using persistent mode with QEMU, "
"AFL_QEMU_PERSISTENT_ADDR "
"is\n"
" probably not valid (hint: add the base address in case of "
"PIE)"
"\n\n"
"If all else fails you can disable the fork server via "
"AFL_NO_FORKSRV=1.\n",
fsrv->mem_limit);
RPFATAL(res, "Unable to communicate with fork server");
}
if (!WIFSTOPPED(status)) fsrv->child_pid = 0;
++afl->total_execs;
/* Any subsequent operations on fsrv->trace_bits must not be moved by the
compiler below this point. Past this location, fsrv->trace_bits[]
behave very normally and do not have to be treated as volatile. */
MEM_BARRIER();
tb4 = *(u32 *)fsrv->trace_bits;
fsrv_run_result_t res = afl_fsrv_run_target(&afl->fsrv, &afl->stop_soon);
#ifdef WORD_SIZE_64
classify_counts(afl, (u64 *)fsrv->trace_bits);
@ -128,35 +42,7 @@ u8 run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
classify_counts(afl, (u32 *)fsrv->trace_bits);
#endif /* ^WORD_SIZE_64 */
fsrv->prev_timed_out = fsrv->child_timed_out;
/* Report outcome to caller. */
if (WIFSIGNALED(status) && !afl->stop_soon) {
afl->kill_signal = WTERMSIG(status);
if (fsrv->child_timed_out && afl->kill_signal == SIGKILL)
return FAULT_TMOUT;
return FAULT_CRASH;
}
/* A somewhat nasty hack for MSAN, which doesn't support abort_on_error and
must use a special exit code. */
if (fsrv->uses_asan && WEXITSTATUS(status) == MSAN_ERROR) {
afl->kill_signal = 0;
return FAULT_CRASH;
}
if ((afl->dumb_mode == 1 || afl->no_forkserver) && tb4 == EXEC_FAIL_SIG)
return FAULT_ERROR;
return FAULT_NONE;
return res;
}
@ -348,7 +234,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
if (!afl->dumb_mode && !afl->stage_cur &&
!count_bytes(afl, afl->fsrv.trace_bits)) {
fault = FAULT_NOINST;
fault = FSRV_RUN_NOINST;
goto abort_calibration;
}
@ -408,7 +294,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
parent. This is a non-critical problem, but something to warn the user
about. */
if (!afl->dumb_mode && first_run && !fault && !new_bits) fault = FAULT_NOBITS;
if (!afl->dumb_mode && first_run && !fault && !new_bits) fault = FSRV_RUN_NOBITS;
abort_calibration:
@ -645,7 +531,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
++afl->trim_execs;
if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming;
if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming;
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
*/
@ -753,7 +639,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
if (afl->stop_soon) return 1;
if (fault == FAULT_TMOUT) {
if (fault == FSRV_RUN_TMOUT) {
if (afl->subseq_tmouts++ > TMOUT_LIMIT) {

View File

@ -108,14 +108,14 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
afl->start_time / 1000, cur_time / 1000,
(cur_time - afl->start_time) / 1000, getpid(),
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
afl->total_execs,
afl->total_execs / ((double)(get_cur_time() - afl->start_time) / 1000),
afl->fsrv.total_execs,
afl->fsrv.total_execs / ((double)(get_cur_time() - afl->start_time) / 1000),
afl->queued_paths, afl->queued_favored, afl->queued_discovered,
afl->queued_imported, afl->max_depth, afl->current_entry,
afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable,
stability, bitmap_cvg, afl->unique_crashes, afl->unique_hangs,
afl->last_path_time / 1000, afl->last_crash_time / 1000,
afl->last_hang_time / 1000, afl->total_execs - afl->last_crash_execs,
afl->last_hang_time / 1000, afl->fsrv.total_execs - afl->last_crash_execs,
afl->fsrv.exec_tmout, afl->slowest_exec_ms,
#ifdef __APPLE__
(unsigned long int)(rus.ru_maxrss >> 20),
@ -227,7 +227,7 @@ void show_stats(afl_state_t *afl) {
if (afl->most_execs_key == 1) {
if (afl->most_execs <= afl->total_execs) {
if (afl->most_execs <= afl->fsrv.total_execs) {
afl->most_execs_key = 2;
afl->stop_soon = 2;
@ -251,11 +251,11 @@ void show_stats(afl_state_t *afl) {
if (!afl->stats_last_execs) {
afl->stats_avg_exec =
((double)afl->total_execs) * 1000 / (cur_ms - afl->start_time);
((double)afl->fsrv.total_execs) * 1000 / (cur_ms - afl->start_time);
} else {
double cur_avg = ((double)(afl->total_execs - afl->stats_last_execs)) *
double cur_avg = ((double)(afl->fsrv.total_execs - afl->stats_last_execs)) *
1000 / (cur_ms - afl->stats_last_ms);
/* If there is a dramatic (5x+) jump in speed, reset the indicator
@ -270,7 +270,7 @@ void show_stats(afl_state_t *afl) {
}
afl->stats_last_ms = cur_ms;
afl->stats_last_execs = afl->total_execs;
afl->stats_last_execs = afl->fsrv.total_execs;
/* Tell the callers when to contact us (as measured in execs). */
@ -543,14 +543,14 @@ void show_stats(afl_state_t *afl) {
SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
" new crashes : %s%-22s" bSTG bV "\n",
u_stringify_int(IB(0), afl->total_execs),
u_stringify_int(IB(0), afl->fsrv.total_execs),
afl->unique_crashes ? cLRD : cRST, tmp);
} else {
SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
" total crashes : %s%-22s" bSTG bV "\n",
u_stringify_int(IB(0), afl->total_execs),
u_stringify_int(IB(0), afl->fsrv.total_execs),
afl->unique_crashes ? cLRD : cRST, tmp);
}

View File

@ -480,7 +480,7 @@ int main(int argc, char **argv_orig, char **envp) {
case 'C': /* crash mode */
if (afl->crash_mode) FATAL("Multiple -C options not supported");
afl->crash_mode = FAULT_CRASH;
afl->crash_mode = FSRV_RUN_CRASH;
break;
case 'n': /* dumb mode */

View File

@ -40,7 +40,6 @@
#include <stdio.h>
#include <unistd.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

View File

@ -69,7 +69,7 @@ static u8 *in_data; /* Input data */
static u32 total, highest; /* tuple content information */
static u32 in_len, /* Input data length */
arg_offset, total_execs; /* Total number of execs */
arg_offset; /* Total number of execs */
static u8 quiet_mode, /* Hide non-essential messages? */
edges_only, /* Ignore hit counts? */
@ -193,7 +193,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
if (cmin_mode) {
if (fsrv->child_timed_out) break;
if (fsrv->last_run_timed_out) break;
if (!caa && child_crashed != cco) break;
fprintf(f, "%u%u\n", fsrv->trace_bits[i], i);
@ -233,75 +233,18 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
}
/* Execute target application. Returns 0 if the changes are a dud, or
1 if they should be kept. */
/* Execute target application. */
static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
u32 len) {
struct itimerval it;
int status = 0;
memset(fsrv->trace_bits, 0, MAP_SIZE);
MEM_BARRIER();
write_to_testcase(fsrv, mem, len);
s32 res;
/* we have the fork server up and running, so simply
tell it to have at it, and then read back PID. */
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
if (stop_soon) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
if (stop_soon) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
/* Configure timeout, wait for child, cancel timeout. */
if (fsrv->exec_tmout) {
it.it_value.tv_sec = (fsrv->exec_tmout / 1000);
it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000;
}
setitimer(ITIMER_REAL, &it, NULL);
if ((res = read(fsrv->fsrv_st_fd, &status, 4)) != 4) {
if (stop_soon) return 0;
RPFATAL(res, "Unable to communicate with fork server (OOM?)");
}
fsrv->child_pid = 0;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &it, NULL);
MEM_BARRIER();
/* Clean up bitmap, analyze exit condition, etc. */
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG)
FATAL("Unable to execute '%s'", argv[0]);
fsrv_run_result_t res = afl_fsrv_run_target(fsrv, &stop_soon);
if (res == FSRV_RUN_NOINST || res == FSRV_RUN_ERROR) FATAL("Error running target");
classify_counts(fsrv->trace_bits,
binary_mode ? count_class_binary : count_class_human);
total_execs++;
if (stop_soon) {
@ -310,22 +253,6 @@ static u8 run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem,
}
/* Always discard inputs that time out. */
if (fsrv->child_timed_out) { return 0; }
/* Handle crashing inputs depending on current mode. */
if (WIFSIGNALED(status) ||
(WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
(WIFEXITED(status) && WEXITSTATUS(status))) {
return 0;
}
return 0;
}
/* Read initial file. */
@ -425,7 +352,7 @@ static void run_target(afl_forkserver_t *fsrv, char **argv) {
if (fsrv->exec_tmout) {
fsrv->child_timed_out = 0;
fsrv->last_run_timed_out = 0;
it.it_value.tv_sec = (fsrv->exec_tmout / 1000);
it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000;
@ -452,12 +379,12 @@ static void run_target(afl_forkserver_t *fsrv, char **argv) {
if (!quiet_mode) SAYF(cRST "-- Program output ends --\n");
if (!fsrv->child_timed_out && !stop_soon && WIFSIGNALED(status))
if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status))
child_crashed = 1;
if (!quiet_mode) {
if (fsrv->child_timed_out)
if (fsrv->last_run_timed_out)
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
else if (stop_soon)
SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
@ -980,7 +907,7 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (!quiet_mode) OKF("Processed %u input files.", total_execs);
if (!quiet_mode) OKF("Processed %llu input files.", fsrv->total_execs);
closedir(dir_in);
if (dir_out) closedir(dir_out);
@ -1010,7 +937,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_deinit(&shm);
u32 ret = child_crashed * 2 + fsrv->child_timed_out;
u32 ret = child_crashed * 2 + fsrv->last_run_timed_out;
if (fsrv->target_path) ck_free(fsrv->target_path);

View File

@ -67,7 +67,6 @@ static u8 *in_data; /* Input data for trimming */
static u32 in_len, /* Input data length */
orig_cksum, /* Original checksum */
total_execs, /* Total number of execs */
missed_hangs, /* Misses due to hangs */
missed_crashes, /* Misses due to crashes */
missed_paths; /* Misses due to exec path diffs */
@ -249,69 +248,11 @@ static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) {
static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
u8 first_run) {
struct itimerval it;
int status = 0;
u32 cksum;
fsrv->child_timed_out = 0;
memset(fsrv->trace_bits, 0, fsrv->map_size);
MEM_BARRIER();
write_to_testcase(fsrv, mem, len);
s32 res;
fsrv_run_result_t ret = afl_fsrv_run_target(fsrv, &stop_soon);
/* we have the fork server up and running, so simply
tell it to have at it, and then read back PID. */
if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->prev_timed_out, 4)) != 4) {
if (stop_soon) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) {
if (stop_soon) return 0;
RPFATAL(res, "Unable to request new process from fork server (OOM?)");
}
if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
/* Configure timeout, wait for child, cancel timeout. */
if (fsrv->exec_tmout) {
it.it_value.tv_sec = (fsrv->exec_tmout / 1000);
it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000;
}
setitimer(ITIMER_REAL, &it, NULL);
if ((res = read(fsrv->fsrv_st_fd, &status, 4)) != 4) {
if (stop_soon) return 0;
RPFATAL(res, "Unable to communicate with fork server (OOM?)");
}
fsrv->child_pid = 0;
it.it_value.tv_sec = 0;
it.it_value.tv_usec = 0;
setitimer(ITIMER_REAL, &it, NULL);
MEM_BARRIER();
/* Clean up bitmap, analyze exit condition, etc. */
if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG)
FATAL("Unable to execute '%s'", argv[0]);
if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child");
if (!hang_mode) {
@ -320,8 +261,6 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
}
total_execs++;
if (stop_soon) {
SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST);
@ -334,25 +273,21 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
if (hang_mode) {
if (fsrv->child_timed_out) return 1;
if (WIFSIGNALED(status) ||
(WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
(WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) {
switch (ret)
{
case FSRV_RUN_TMOUT:
return 1;
case FSRV_RUN_CRASH:
missed_crashes++;
} else {
missed_hangs++;
}
return 0;
default:
missed_hangs++;
return 0;
}
}
if (fsrv->child_timed_out) {
if (ret == FSRV_RUN_TMOUT) {
missed_hangs++;
return 0;
@ -361,9 +296,7 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
/* Handle crashing inputs depending on current mode. */
if (WIFSIGNALED(status) ||
(WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
(WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) {
if (ret == FSRV_RUN_CRASH) {
if (first_run) crash_mode = 1;
@ -391,7 +324,9 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
}
cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST);
if (ret == FSRV_RUN_NOINST) FATAL("Binary not instrumented?");
u32 cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST);
if (first_run) orig_cksum = cksum;
@ -640,11 +575,11 @@ finalize_all:
SAYF("\n" cGRA " File size reduced by : " cRST
"%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST
"%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA
"%0.02f%%\n" cGRA " Number of execs done : " cRST "%llu\n" cGRA
" Fruitless execs : " cRST "termination=%u crash=%u\n\n",
100 - ((double)in_len) * 100 / orig_len, in_len,
in_len == 1 ? "" : "s",
((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), total_execs,
((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), fsrv->total_execs,
missed_paths, missed_crashes);
return;
@ -652,13 +587,13 @@ finalize_all:
SAYF("\n" cGRA " File size reduced by : " cRST
"%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " cRST
"%0.02f%%\n" cGRA " Number of execs done : " cRST "%u\n" cGRA
"%0.02f%%\n" cGRA " Number of execs done : " cRST "%llu\n" cGRA
" Fruitless execs : " cRST "path=%u crash=%u hang=%s%u\n\n",
100 - ((double)in_len) * 100 / orig_len, in_len, in_len == 1 ? "" : "s",
((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), total_execs,
((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1), fsrv->total_execs,
missed_paths, missed_crashes, missed_hangs ? cLRD : "", missed_hangs);
if (total_execs > 50 && missed_hangs * 10 > total_execs && !hang_mode)
if (fsrv->total_execs > 50 && missed_hangs * 10 > fsrv->total_execs && !hang_mode)
WARNF(cLRD "Frequent timeouts - results may be skewed." cRST);
}
@ -1139,13 +1074,13 @@ int main(int argc, char **argv_orig, char **envp) {
run_target(fsrv, use_argv, in_data, in_len, 1);
if (hang_mode && !fsrv->child_timed_out)
if (hang_mode && !fsrv->last_run_timed_out)
FATAL(
"Target binary did not time out but hang minimization mode "
"(-H) was set (-t %u).",
fsrv->exec_tmout);
if (fsrv->child_timed_out && !hang_mode)
if (fsrv->last_run_timed_out && !hang_mode)
FATAL(
"Target binary times out (adjusting -t may help). Use -H to minimize a "
"hang.");