mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
unified forkservered run_target, fixes #308
This commit is contained in:
@ -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 operator_num 16
|
||||||
#define swarm_num 5
|
#define swarm_num 5
|
||||||
@ -433,7 +421,6 @@ typedef struct afl_state {
|
|||||||
use_splicing, /* Recombine input files? */
|
use_splicing, /* Recombine input files? */
|
||||||
dumb_mode, /* Run in non-instrumented mode? */
|
dumb_mode, /* Run in non-instrumented mode? */
|
||||||
score_changed, /* Scoring for favorites changed? */
|
score_changed, /* Scoring for favorites changed? */
|
||||||
kill_signal, /* Signal that killed the child */
|
|
||||||
resuming_fuzz, /* Resuming an older fuzzing job? */
|
resuming_fuzz, /* Resuming an older fuzzing job? */
|
||||||
timeout_given, /* Specific timeout given? */
|
timeout_given, /* Specific timeout given? */
|
||||||
not_on_tty, /* stdout is not a tty */
|
not_on_tty, /* stdout is not a tty */
|
||||||
@ -488,7 +475,6 @@ typedef struct afl_state {
|
|||||||
total_tmouts, /* Total number of timeouts */
|
total_tmouts, /* Total number of timeouts */
|
||||||
unique_tmouts, /* Timeouts with unique signatures */
|
unique_tmouts, /* Timeouts with unique signatures */
|
||||||
unique_hangs, /* Hangs with unique signatures */
|
unique_hangs, /* Hangs with unique signatures */
|
||||||
total_execs, /* Total execve() calls */
|
|
||||||
last_crash_execs, /* Exec counter at last crash */
|
last_crash_execs, /* Exec counter at last crash */
|
||||||
queue_cycle, /* Queue round counter */
|
queue_cycle, /* Queue round counter */
|
||||||
cycles_wo_finds, /* Cycles without any new paths */
|
cycles_wo_finds, /* Cycles without any new paths */
|
||||||
@ -888,7 +874,7 @@ void show_init_stats(afl_state_t *);
|
|||||||
|
|
||||||
/* Run */
|
/* 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);
|
void write_to_testcase(afl_state_t *, void *, u32);
|
||||||
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
|
u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8);
|
||||||
void sync_fuzzers(afl_state_t *);
|
void sync_fuzzers(afl_state_t *);
|
||||||
|
@ -29,6 +29,7 @@
|
|||||||
#define __AFL_FORKSERVER_H
|
#define __AFL_FORKSERVER_H
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
typedef struct afl_forkserver {
|
typedef struct afl_forkserver {
|
||||||
|
|
||||||
@ -55,17 +56,19 @@ typedef struct afl_forkserver {
|
|||||||
u32 snapshot; /* is snapshot feature used */
|
u32 snapshot; /* is snapshot feature used */
|
||||||
u64 mem_limit; /* Memory cap for child (MB) */
|
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 */
|
u8 *out_file, /* File to fuzz, if any */
|
||||||
*target_path; /* Path of the target */
|
*target_path; /* Path of the target */
|
||||||
|
|
||||||
FILE *plot_file; /* Gnuplot output file */
|
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? */
|
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 */
|
u8 qemu_mode; /* if running in qemu mode or not */
|
||||||
|
|
||||||
char *cmplog_binary; /* the name of the cmplog binary */
|
char *cmplog_binary; /* the name of the cmplog binary */
|
||||||
@ -79,10 +82,22 @@ typedef struct afl_forkserver {
|
|||||||
|
|
||||||
} afl_forkserver_t;
|
} 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(afl_forkserver_t *fsrv);
|
||||||
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
|
void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from);
|
||||||
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||||
volatile u8 *stop_soon_p, u8 debug_child_output);
|
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_killall(void);
|
||||||
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
|
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
|
||||||
|
|
||||||
|
@ -80,7 +80,7 @@ static u8 edges_only, /* Ignore hit counts? */
|
|||||||
use_stdin = 1; /* Use stdin for program input? */
|
use_stdin = 1; /* Use stdin for program input? */
|
||||||
|
|
||||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||||
child_timed_out; /* Child timed out? */
|
child_timed_out; /* Child timed out? */
|
||||||
|
|
||||||
static u8 *target_path;
|
static u8 *target_path;
|
||||||
static u8 qemu_mode;
|
static u8 qemu_mode;
|
||||||
|
@ -76,7 +76,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
|
|||||||
fsrv->child_pid = -1;
|
fsrv->child_pid = -1;
|
||||||
fsrv->map_size = MAP_SIZE;
|
fsrv->map_size = MAP_SIZE;
|
||||||
fsrv->use_fauxsrv = 0;
|
fsrv->use_fauxsrv = 0;
|
||||||
fsrv->prev_timed_out = 0;
|
fsrv->last_run_timed_out = 0;
|
||||||
|
|
||||||
fsrv->init_child_func = fsrv_exec_child;
|
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->out_dir_fd = -1;
|
||||||
fsrv_to->child_pid = -1;
|
fsrv_to->child_pid = -1;
|
||||||
fsrv_to->use_fauxsrv = 0;
|
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;
|
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");
|
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();
|
fsrv->fsrv_pid = fork();
|
||||||
|
|
||||||
if (fsrv->fsrv_pid < 0) PFATAL("fork() failed");
|
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) {
|
} 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);
|
kill(fsrv->fsrv_pid, SIGKILL);
|
||||||
|
|
||||||
} else {
|
} 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)");
|
FATAL("Timeout while initializing fork server (adjusting -t may help)");
|
||||||
|
|
||||||
if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed");
|
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() {
|
void afl_fsrv_killall() {
|
||||||
|
|
||||||
LIST_FOREACH(&fsrv_list, afl_forkserver_t, {
|
LIST_FOREACH(&fsrv_list, afl_forkserver_t, {
|
||||||
@ -656,4 +777,3 @@ void afl_fsrv_deinit(afl_forkserver_t *fsrv) {
|
|||||||
list_remove(&fsrv_list, fsrv);
|
list_remove(&fsrv_list, fsrv);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
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");
|
FATAL("Unable to execute target application");
|
||||||
|
|
||||||
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
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) {
|
switch (fault) {
|
||||||
|
|
||||||
case FAULT_TMOUT:
|
case FSRV_RUN_TMOUT:
|
||||||
|
|
||||||
/* Timeouts are not very interesting, but we're still obliged to keep
|
/* 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
|
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
|
timeout actually uncovers a crash. Make sure we don't discard it if
|
||||||
so. */
|
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;
|
break;
|
||||||
|
|
||||||
case FAULT_CRASH:
|
case FSRV_RUN_CRASH:
|
||||||
|
|
||||||
keep_as_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
|
#ifndef SIMPLE_FILES
|
||||||
|
|
||||||
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
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
|
#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_time = get_cur_time();
|
||||||
afl->last_crash_execs = afl->total_execs;
|
afl->last_crash_execs = afl->fsrv.total_execs;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FAULT_ERROR: FATAL("Unable to execute target application");
|
case FSRV_RUN_ERROR: FATAL("Unable to execute target application");
|
||||||
|
|
||||||
default: return keeping;
|
default: return keeping;
|
||||||
|
|
||||||
|
@ -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 (afl->stop_soon) return 1;
|
||||||
|
|
||||||
if (fault == FAULT_TMOUT) {
|
if (fault == FSRV_RUN_TMOUT) {
|
||||||
|
|
||||||
if (afl->subseq_tmouts++ > TMOUT_LIMIT) {
|
if (afl->subseq_tmouts++ > TMOUT_LIMIT) {
|
||||||
|
|
||||||
|
@ -493,13 +493,13 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
|
|
||||||
if (afl->stop_soon) return;
|
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,
|
SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST,
|
||||||
q->len, q->bitmap_size, q->exec_us);
|
q->len, q->bitmap_size, q->exec_us);
|
||||||
|
|
||||||
switch (res) {
|
switch (res) {
|
||||||
|
|
||||||
case FAULT_NONE:
|
case FSRV_RUN_OK:
|
||||||
|
|
||||||
if (q == afl->queue) check_map_coverage(afl);
|
if (q == afl->queue) check_map_coverage(afl);
|
||||||
|
|
||||||
@ -507,7 +507,7 @@ void perform_dry_run(afl_state_t *afl) {
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FAULT_TMOUT:
|
case FSRV_RUN_TMOUT:
|
||||||
|
|
||||||
if (afl->timeout_given) {
|
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;
|
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);
|
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]);
|
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;
|
++afl->useless_at_start;
|
||||||
|
|
||||||
|
@ -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);
|
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||||
++afl->trim_execs;
|
++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);
|
cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||||
|
|
||||||
|
@ -442,14 +442,14 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
|||||||
|
|
||||||
if (unlikely(afl->queue_cur->cal_failed)) {
|
if (unlikely(afl->queue_cur->cal_failed)) {
|
||||||
|
|
||||||
u8 res = FAULT_TMOUT;
|
u8 res = FSRV_RUN_TMOUT;
|
||||||
|
|
||||||
if (afl->queue_cur->cal_failed < CAL_CHANCES) {
|
if (afl->queue_cur->cal_failed < CAL_CHANCES) {
|
||||||
|
|
||||||
res =
|
res =
|
||||||
calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
|
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");
|
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);
|
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");
|
FATAL("Unable to execute target application");
|
||||||
|
|
||||||
if (unlikely(afl->stop_soon)) {
|
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) {
|
if (afl->queue_cur->cal_failed) {
|
||||||
|
|
||||||
u8 res = FAULT_TMOUT;
|
u8 res = FSRV_RUN_TMOUT;
|
||||||
|
|
||||||
if (afl->queue_cur->cal_failed < CAL_CHANCES) {
|
if (afl->queue_cur->cal_failed < CAL_CHANCES) {
|
||||||
|
|
||||||
res =
|
res =
|
||||||
calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0);
|
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);
|
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) {
|
if (afl->stop_soon) {
|
||||||
|
|
||||||
|
@ -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,
|
// the more often fuzz result paths are equal to this queue entry,
|
||||||
// reduce its value
|
// reduce its value
|
||||||
perf_score *=
|
perf_score *=
|
||||||
(1 - (double)((double)q->n_fuzz / (double)afl->total_execs));
|
(1 - (double)((double)q->n_fuzz / (double)afl->fsrv.total_execs));
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -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;
|
if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1;
|
||||||
|
|
||||||
u64 orig_hit_cnt, new_hit_cnt;
|
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;
|
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||||
|
|
||||||
afl->stage_name = "input-to-state";
|
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:
|
exit_its:
|
||||||
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||||
afl->stage_finds[STAGE_ITS] += new_hit_cnt - orig_hit_cnt;
|
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);
|
memcpy(orig_buf, buf, len);
|
||||||
|
|
||||||
|
@ -32,95 +32,9 @@
|
|||||||
/* Execute target application, monitoring for timeouts. Return status
|
/* Execute target application, monitoring for timeouts. Return status
|
||||||
information. The called program will update afl->fsrv->trace_bits. */
|
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;
|
fsrv_run_result_t res = afl_fsrv_run_target(&afl->fsrv, &afl->stop_soon);
|
||||||
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;
|
|
||||||
|
|
||||||
#ifdef WORD_SIZE_64
|
#ifdef WORD_SIZE_64
|
||||||
classify_counts(afl, (u64 *)fsrv->trace_bits);
|
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);
|
classify_counts(afl, (u32 *)fsrv->trace_bits);
|
||||||
#endif /* ^WORD_SIZE_64 */
|
#endif /* ^WORD_SIZE_64 */
|
||||||
|
|
||||||
fsrv->prev_timed_out = fsrv->child_timed_out;
|
return res;
|
||||||
|
|
||||||
/* 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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -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 &&
|
if (!afl->dumb_mode && !afl->stage_cur &&
|
||||||
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
!count_bytes(afl, afl->fsrv.trace_bits)) {
|
||||||
|
|
||||||
fault = FAULT_NOINST;
|
fault = FSRV_RUN_NOINST;
|
||||||
goto abort_calibration;
|
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
|
parent. This is a non-critical problem, but something to warn the user
|
||||||
about. */
|
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:
|
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);
|
fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||||
++afl->trim_execs;
|
++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?
|
/* 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 (afl->stop_soon) return 1;
|
||||||
|
|
||||||
if (fault == FAULT_TMOUT) {
|
if (fault == FSRV_RUN_TMOUT) {
|
||||||
|
|
||||||
if (afl->subseq_tmouts++ > TMOUT_LIMIT) {
|
if (afl->subseq_tmouts++ > TMOUT_LIMIT) {
|
||||||
|
|
||||||
|
@ -108,14 +108,14 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
|||||||
afl->start_time / 1000, cur_time / 1000,
|
afl->start_time / 1000, cur_time / 1000,
|
||||||
(cur_time - afl->start_time) / 1000, getpid(),
|
(cur_time - afl->start_time) / 1000, getpid(),
|
||||||
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
||||||
afl->total_execs,
|
afl->fsrv.total_execs,
|
||||||
afl->total_execs / ((double)(get_cur_time() - afl->start_time) / 1000),
|
afl->fsrv.total_execs / ((double)(get_cur_time() - afl->start_time) / 1000),
|
||||||
afl->queued_paths, afl->queued_favored, afl->queued_discovered,
|
afl->queued_paths, afl->queued_favored, afl->queued_discovered,
|
||||||
afl->queued_imported, afl->max_depth, afl->current_entry,
|
afl->queued_imported, afl->max_depth, afl->current_entry,
|
||||||
afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable,
|
afl->pending_favored, afl->pending_not_fuzzed, afl->queued_variable,
|
||||||
stability, bitmap_cvg, afl->unique_crashes, afl->unique_hangs,
|
stability, bitmap_cvg, afl->unique_crashes, afl->unique_hangs,
|
||||||
afl->last_path_time / 1000, afl->last_crash_time / 1000,
|
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,
|
afl->fsrv.exec_tmout, afl->slowest_exec_ms,
|
||||||
#ifdef __APPLE__
|
#ifdef __APPLE__
|
||||||
(unsigned long int)(rus.ru_maxrss >> 20),
|
(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_key == 1) {
|
||||||
|
|
||||||
if (afl->most_execs <= afl->total_execs) {
|
if (afl->most_execs <= afl->fsrv.total_execs) {
|
||||||
|
|
||||||
afl->most_execs_key = 2;
|
afl->most_execs_key = 2;
|
||||||
afl->stop_soon = 2;
|
afl->stop_soon = 2;
|
||||||
@ -251,11 +251,11 @@ void show_stats(afl_state_t *afl) {
|
|||||||
if (!afl->stats_last_execs) {
|
if (!afl->stats_last_execs) {
|
||||||
|
|
||||||
afl->stats_avg_exec =
|
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 {
|
} 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);
|
1000 / (cur_ms - afl->stats_last_ms);
|
||||||
|
|
||||||
/* If there is a dramatic (5x+) jump in speed, reset the indicator
|
/* 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_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). */
|
/* 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
|
SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
|
||||||
" new crashes : %s%-22s" bSTG bV "\n",
|
" 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);
|
afl->unique_crashes ? cLRD : cRST, tmp);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
|
SAYF(bV bSTOP " total execs : " cRST "%-20s " bSTG bV bSTOP
|
||||||
" total crashes : %s%-22s" bSTG bV "\n",
|
" 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);
|
afl->unique_crashes ? cLRD : cRST, tmp);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -480,7 +480,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
case 'C': /* crash mode */
|
case 'C': /* crash mode */
|
||||||
|
|
||||||
if (afl->crash_mode) FATAL("Multiple -C options not supported");
|
if (afl->crash_mode) FATAL("Multiple -C options not supported");
|
||||||
afl->crash_mode = FAULT_CRASH;
|
afl->crash_mode = FSRV_RUN_CRASH;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'n': /* dumb mode */
|
case 'n': /* dumb mode */
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
|
@ -69,7 +69,7 @@ static u8 *in_data; /* Input data */
|
|||||||
static u32 total, highest; /* tuple content information */
|
static u32 total, highest; /* tuple content information */
|
||||||
|
|
||||||
static u32 in_len, /* Input data length */
|
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? */
|
static u8 quiet_mode, /* Hide non-essential messages? */
|
||||||
edges_only, /* Ignore hit counts? */
|
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 (cmin_mode) {
|
||||||
|
|
||||||
if (fsrv->child_timed_out) break;
|
if (fsrv->last_run_timed_out) break;
|
||||||
if (!caa && child_crashed != cco) break;
|
if (!caa && child_crashed != cco) break;
|
||||||
|
|
||||||
fprintf(f, "%u%u\n", fsrv->trace_bits[i], i);
|
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
|
/* Execute target application. */
|
||||||
1 if they should be kept. */
|
|
||||||
|
|
||||||
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) {
|
u32 len) {
|
||||||
|
|
||||||
struct itimerval it;
|
|
||||||
int status = 0;
|
|
||||||
|
|
||||||
memset(fsrv->trace_bits, 0, MAP_SIZE);
|
|
||||||
MEM_BARRIER();
|
|
||||||
|
|
||||||
write_to_testcase(fsrv, mem, len);
|
write_to_testcase(fsrv, mem, len);
|
||||||
|
|
||||||
s32 res;
|
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");
|
||||||
/* 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]);
|
|
||||||
|
|
||||||
classify_counts(fsrv->trace_bits,
|
classify_counts(fsrv->trace_bits,
|
||||||
binary_mode ? count_class_binary : count_class_human);
|
binary_mode ? count_class_binary : count_class_human);
|
||||||
total_execs++;
|
|
||||||
|
|
||||||
if (stop_soon) {
|
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. */
|
/* Read initial file. */
|
||||||
@ -425,7 +352,7 @@ static void run_target(afl_forkserver_t *fsrv, char **argv) {
|
|||||||
|
|
||||||
if (fsrv->exec_tmout) {
|
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_sec = (fsrv->exec_tmout / 1000);
|
||||||
it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 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 (!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;
|
child_crashed = 1;
|
||||||
|
|
||||||
if (!quiet_mode) {
|
if (!quiet_mode) {
|
||||||
|
|
||||||
if (fsrv->child_timed_out)
|
if (fsrv->last_run_timed_out)
|
||||||
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
SAYF(cLRD "\n+++ Program timed off +++\n" cRST);
|
||||||
else if (stop_soon)
|
else if (stop_soon)
|
||||||
SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST);
|
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);
|
closedir(dir_in);
|
||||||
if (dir_out) closedir(dir_out);
|
if (dir_out) closedir(dir_out);
|
||||||
@ -1010,7 +937,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
afl_shm_deinit(&shm);
|
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);
|
if (fsrv->target_path) ck_free(fsrv->target_path);
|
||||||
|
|
||||||
|
109
src/afl-tmin.c
109
src/afl-tmin.c
@ -67,7 +67,6 @@ static u8 *in_data; /* Input data for trimming */
|
|||||||
|
|
||||||
static u32 in_len, /* Input data length */
|
static u32 in_len, /* Input data length */
|
||||||
orig_cksum, /* Original checksum */
|
orig_cksum, /* Original checksum */
|
||||||
total_execs, /* Total number of execs */
|
|
||||||
missed_hangs, /* Misses due to hangs */
|
missed_hangs, /* Misses due to hangs */
|
||||||
missed_crashes, /* Misses due to crashes */
|
missed_crashes, /* Misses due to crashes */
|
||||||
missed_paths; /* Misses due to exec path diffs */
|
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,
|
static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
|
||||||
u8 first_run) {
|
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);
|
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
|
if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child");
|
||||||
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 (!hang_mode) {
|
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) {
|
if (stop_soon) {
|
||||||
|
|
||||||
SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST);
|
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 (hang_mode) {
|
||||||
|
|
||||||
if (fsrv->child_timed_out) return 1;
|
switch (ret)
|
||||||
|
{
|
||||||
if (WIFSIGNALED(status) ||
|
case FSRV_RUN_TMOUT:
|
||||||
(WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
|
return 1;
|
||||||
(WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) {
|
case FSRV_RUN_CRASH:
|
||||||
|
|
||||||
missed_crashes++;
|
missed_crashes++;
|
||||||
|
return 0;
|
||||||
} else {
|
default:
|
||||||
|
|
||||||
missed_hangs++;
|
missed_hangs++;
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fsrv->child_timed_out) {
|
if (ret == FSRV_RUN_TMOUT) {
|
||||||
|
|
||||||
missed_hangs++;
|
missed_hangs++;
|
||||||
return 0;
|
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. */
|
/* Handle crashing inputs depending on current mode. */
|
||||||
|
|
||||||
if (WIFSIGNALED(status) ||
|
if (ret == FSRV_RUN_CRASH) {
|
||||||
(WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
|
|
||||||
(WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) {
|
|
||||||
|
|
||||||
if (first_run) crash_mode = 1;
|
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;
|
if (first_run) orig_cksum = cksum;
|
||||||
|
|
||||||
@ -640,11 +575,11 @@ finalize_all:
|
|||||||
|
|
||||||
SAYF("\n" cGRA " File size reduced by : " cRST
|
SAYF("\n" cGRA " File size reduced by : " cRST
|
||||||
"%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " 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",
|
" Fruitless execs : " cRST "termination=%u crash=%u\n\n",
|
||||||
100 - ((double)in_len) * 100 / orig_len, in_len,
|
100 - ((double)in_len) * 100 / orig_len, in_len,
|
||||||
in_len == 1 ? "" : "s",
|
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_paths, missed_crashes);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
@ -652,13 +587,13 @@ finalize_all:
|
|||||||
|
|
||||||
SAYF("\n" cGRA " File size reduced by : " cRST
|
SAYF("\n" cGRA " File size reduced by : " cRST
|
||||||
"%0.02f%% (to %u byte%s)\n" cGRA " Characters simplified : " 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",
|
" 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",
|
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);
|
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);
|
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);
|
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(
|
FATAL(
|
||||||
"Target binary did not time out but hang minimization mode "
|
"Target binary did not time out but hang minimization mode "
|
||||||
"(-H) was set (-t %u).",
|
"(-H) was set (-t %u).",
|
||||||
fsrv->exec_tmout);
|
fsrv->exec_tmout);
|
||||||
|
|
||||||
if (fsrv->child_timed_out && !hang_mode)
|
if (fsrv->last_run_timed_out && !hang_mode)
|
||||||
FATAL(
|
FATAL(
|
||||||
"Target binary times out (adjusting -t may help). Use -H to minimize a "
|
"Target binary times out (adjusting -t may help). Use -H to minimize a "
|
||||||
"hang.");
|
"hang.");
|
||||||
|
Reference in New Issue
Block a user