From 9785b15ed264951b006093f9ee4564820c153593 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 28 Mar 2020 04:57:44 +0100 Subject: more custom mutator remodelling --- src/afl-fuzz-cmplog.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src/afl-fuzz-cmplog.c') diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 6c6f05ac..7c398507 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -527,8 +527,13 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { if (afl->post_handler) { - out_buf = afl->post_handler(out_buf, &len); - if (!out_buf || !len) return 0; + u8 *post_buf = NULL; + + size_t post_len = + afl->post_handler(afl->post_data, out_buf, len, &post_buf); + if (!post_buf || !post_len) return 0; + out_buf = post_buf; + len = post_len; } -- cgit 1.4.1 From 452067ffca0de664fa4a11211c54f34c3842f20e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 30 Mar 2020 00:50:04 +0200 Subject: added read_timed --- docs/Changelog.md | 6 +++-- include/common.h | 50 ++++++++++++++++++++++++++++++++++++ include/types.h | 18 +++++++++++-- src/afl-forkserver.c | 24 ++++++------------ src/afl-fuzz-cmplog.c | 67 ++++++++++++++++++------------------------------- src/afl-fuzz-redqueen.c | 5 ++-- src/afl-fuzz-run.c | 23 ++++++----------- 7 files changed, 112 insertions(+), 81 deletions(-) (limited to 'src/afl-fuzz-cmplog.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index 198909d1..407a3324 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -16,12 +16,14 @@ sending a mail to . ! development and acceptance of PRs now happen only in the dev branch and only occasionally when everything is fine we PR to master - all: - - big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn + - big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn multiple fuzzing threads in the future or even become a library - afl basic tools now report on the environment variables picked up - more tools get environment variable usage info in the help output - force all output to stdout (some OK/SAY/WARN messages were sent to stdout, some to stderr) + - uninstrumented mode uses an internal forkserver ("fauxserver") + - reduced number of (de)allocations - afl-fuzz: - python mutator modules and custom mutator modules now use the same interface and hence the API changed @@ -38,7 +40,7 @@ sending a mail to . (https://github.com/adrianherrera/afl-ngram-pass/), activate by setting AFL_LLVM_NGRAM_SIZE - llvm_mode InsTrim mode: - - removed workaround for bug where paths were not instrumented and + - removed workaround for bug where paths were not instrumented and imported fix by author - made skipping 1 block functions an option and is disable by default, set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to re-enable this diff --git a/include/common.h b/include/common.h index 8b21b55f..e8558e24 100644 --- a/include/common.h +++ b/include/common.h @@ -29,6 +29,7 @@ #include #include +#include #include #include "types.h" #include "stdbool.h" @@ -390,5 +391,54 @@ static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) { } +/* Wrapper for select() and read(), reading exactly len bytes. + Returns the time passed to read. + If the wait times out, returns timeout_ms + 1; + Returns 0 if an error occurred (fd closed, signal, ...); */ +static inline u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) { + + struct timeval timeout; + fd_set readfds; + FD_ZERO(&readfds); + FD_SET(fd, &readfds); + + timeout.tv_sec = (timeout_ms / 1000); + timeout.tv_usec = (timeout_ms % 1000) * 1000; + + size_t read_total = 0; + size_t len_read = 0; + + while (len_read < len) { + + /* set exceptfds as well to return when a child exited/closed the pipe. */ + int sret = select(fd + 1, &readfds, NULL, NULL, &timeout); + + if (!sret) { + + // printf("Timeout in sret."); + return timeout_ms + 1; + + } else if (sret < 0) { + + // perror("sret malloc"); + // TODO: catch other (errno == EINTR) than ctrl+c? + return 0; + + } + + len_read = read(fd, buf + len_read, len - len_read); + if (!len_read) { return 0; } + read_total += len_read; + + } + + s32 exec_ms = + MIN(timeout_ms, + ((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000))); + return exec_ms > 0 ? exec_ms + : 1; // at least 1 milli must have passed (0 is an error) + +} + #endif diff --git a/include/types.h b/include/types.h index ebc561f7..da95cb39 100644 --- a/include/types.h +++ b/include/types.h @@ -58,8 +58,22 @@ typedef int32_t s32; typedef int64_t s64; #ifndef MIN -#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) -#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b)) +#define MIN(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a < _b ? _a : _b; \ + \ + }) +#define MAX(a, b) \ + ({ \ + \ + __typeof__(a) _a = (a); \ + __typeof__(b) _b = (b); \ + _a > _b ? _a : _b; \ + \ + }) #endif /* !MIN */ #define SWAP16(_x) \ diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 2dd7a9f0..01a606c3 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -164,10 +164,9 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { - struct timeval timeout; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:"); @@ -318,24 +317,15 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { rlen = 0; if (fsrv->exec_tmout) { - fd_set readfds; + rlen = 4; + u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen, + fsrv->exec_tmout * FORK_WAIT_MULT); - FD_ZERO(&readfds); - FD_SET(fsrv->fsrv_st_fd, &readfds); - timeout.tv_sec = ((fsrv->exec_tmout * FORK_WAIT_MULT) / 1000); - timeout.tv_usec = ((fsrv->exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; - - int sret = select(fsrv->fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout); - - if (sret == 0) { + if (!time) { fsrv->child_timed_out = 1; kill(fsrv->child_pid, SIGKILL); - } else { - - rlen = read(fsrv->fsrv_st_fd, &status, 4); - } } else { diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 7c398507..08ac15c7 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -31,10 +31,9 @@ void init_cmplog_forkserver(afl_state_t *afl) { - struct timeval timeout; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; ACTF("Spinning up the cmplog fork server..."); @@ -185,21 +184,19 @@ void init_cmplog_forkserver(afl_state_t *afl) { rlen = 0; if (afl->fsrv.exec_tmout) { - fd_set readfds; - FD_ZERO(&readfds); - FD_SET(afl->cmplog_fsrv_st_fd, &readfds); - timeout.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000); - timeout.tv_usec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + rlen = 4; + u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT; + /* Reuse readfds as exceptfds to see when the child closed the pipe */ + u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); - int sret = - select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout); + if (!time_ms) { - if (sret == 0) { + PFATAL("Error in timed read"); - kill(afl->cmplog_fsrv_pid, SIGKILL); - - } else { + } else if (time_ms > timeout_ms) { + afl->fsrv.child_timed_out = 1; + kill(afl->cmplog_fsrv_pid, SIGKILL); rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); } @@ -213,6 +210,11 @@ void init_cmplog_forkserver(afl_state_t *afl) { /* If we have a four-byte "hello" message from the server, we're all set. Otherwise, try to figure out what went wrong. */ + if (afl->fsrv.child_timed_out) + FATAL( + "Timeout while initializing cmplog fork server (adjusting -t may " + "help)"); + if (rlen == 4) { OKF("All right - fork server is up."); @@ -220,11 +222,6 @@ void init_cmplog_forkserver(afl_state_t *afl) { } - if (afl->fsrv.child_timed_out) - FATAL( - "Timeout while initializing cmplog fork server (adjusting -t may " - "help)"); - if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed"); @@ -379,16 +376,12 @@ void init_cmplog_forkserver(afl_state_t *afl) { u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { - struct timeval it; - int status = 0; - int sret; - u64 exec_ms; + int status = 0; + u64 exec_ms; u32 tb4; s32 res; - fd_set readfds; - afl->fsrv.child_timed_out = 0; /* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we @@ -423,18 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { /* Configure timeout, as requested by user, then wait for child to terminate. */ + u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); - it.tv_sec = (timeout / 1000); - it.tv_usec = (timeout % 1000) * 1000; - - FD_ZERO(&readfds); - FD_SET(afl->cmplog_fsrv_st_fd, &readfds); - it.tv_sec = ((timeout) / 1000); - it.tv_usec = ((timeout) % 1000) * 1000; - - sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it); - - if (sret == 0) { + if (time_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ @@ -442,9 +426,12 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { kill(afl->cmplog_child_pid, SIGKILL); afl->fsrv.child_timed_out = 1; + /* After killing the child, the forkserver should tell us */ + if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) time_ms = 0; + } - if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) { + if (!time_ms) { // Something went wrong. if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST @@ -467,12 +454,8 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0; - exec_ms = (u64)timeout - (it.tv_sec * 1000 + it.tv_usec / 1000); if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms; - it.tv_sec = 0; - it.tv_usec = 0; - ++afl->total_execs; /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index b069fa77..4acc204b 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -529,9 +529,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, if (!afl->shm.cmp_map->headers[k].hits) continue; if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) - afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_H); + afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H); else - afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H); + afl->stage_max += + MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H); } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 90cb2ed5..f58e1a33 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -33,13 +33,10 @@ u8 run_target(afl_state_t *afl, u32 timeout) { s32 res; - int sret; + u32 time_ms; - fd_set readfds; - - struct timeval it; - int status = 0; - u32 tb4; + int status = 0; + u32 tb4; afl->fsrv.child_timed_out = 0; @@ -70,26 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) { if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - /* use select to monitor the forkserver for timeouts. */ - - FD_ZERO(&readfds); - FD_SET(afl->fsrv.fsrv_st_fd, &readfds); - it.tv_sec = ((timeout) / 1000); - it.tv_usec = ((timeout) % 1000) * 1000; - - sret = select(afl->fsrv.fsrv_st_fd + 1, &readfds, NULL, NULL, &it); + time_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); - if (sret == 0) { + if (time_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ kill(afl->fsrv.child_pid, SIGKILL); afl->fsrv.child_timed_out = 1; + if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) time_ms = 0; } - if ((res = read(afl->fsrv.fsrv_st_fd, &status, 4)) != 4) { + if (!time_ms) { if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST -- cgit 1.4.1 From 5a4d4ad7360875fea9efb330a55afe4771e1a428 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Tue, 31 Mar 2020 04:22:22 +0200 Subject: fixed bug in cmplog --- include/afl-fuzz.h | 14 +++++++------- src/afl-fuzz-cmplog.c | 16 ++++++++-------- src/afl-fuzz-run.c | 10 +++++----- src/afl-fuzz-stats.c | 2 +- 4 files changed, 21 insertions(+), 21 deletions(-) (limited to 'src/afl-fuzz-cmplog.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e750d7c9..47aad5af 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -484,11 +484,6 @@ typedef struct afl_state { unique_tmouts, /* Timeouts with unique signatures */ unique_hangs, /* Hangs with unique signatures */ total_execs, /* Total execve() calls */ - slowest_exec_ms, /* Slowest testcase non hang in ms */ - start_time, /* Unix start time (ms) */ - last_path_time, /* Time for most recent path (ms) */ - last_crash_time, /* Time for most recent crash (ms) */ - last_hang_time, /* Time for most recent hang (ms) */ last_crash_execs, /* Exec counter at last crash */ queue_cycle, /* Queue round counter */ cycles_wo_finds, /* Cycles without any new paths */ @@ -496,9 +491,14 @@ typedef struct afl_state { bytes_trim_in, /* Bytes coming into the trimmer */ bytes_trim_out, /* Bytes coming outa the trimmer */ blocks_eff_total, /* Blocks subject to effector maps */ - blocks_eff_select; /* Blocks selected as fuzzable */ + blocks_eff_select, /* Blocks selected as fuzzable */ + start_time, /* Unix start time (ms) */ + last_path_time, /* Time for most recent path (ms) */ + last_crash_time, /* Time for most recent crash (ms) */ + last_hang_time; /* Time for most recent hang (ms) */ - u32 subseq_tmouts; /* Number of timeouts in a row */ + u32 slowest_exec_ms, /* Slowest testcase non hang in ms */ + subseq_tmouts; /* Number of timeouts in a row */ u8 *stage_name, /* Name of the current fuzz stage */ *stage_short, /* Short stage name */ diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 08ac15c7..f932f33b 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -187,13 +187,13 @@ void init_cmplog_forkserver(afl_state_t *afl) { rlen = 4; u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT; /* Reuse readfds as exceptfds to see when the child closed the pipe */ - u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); + u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms); - if (!time_ms) { + if (!exec_ms) { PFATAL("Error in timed read"); - } else if (time_ms > timeout_ms) { + } else if (exec_ms > timeout_ms) { afl->fsrv.child_timed_out = 1; kill(afl->cmplog_fsrv_pid, SIGKILL); @@ -377,7 +377,7 @@ void init_cmplog_forkserver(afl_state_t *afl) { u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { int status = 0; - u64 exec_ms; + u32 exec_ms; u32 tb4; s32 res; @@ -416,9 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { /* Configure timeout, as requested by user, then wait for child to terminate. */ - u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); + exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout); - if (time_ms > timeout) { + if (exec_ms > timeout) { /* If there was no response from forkserver after timeout seconds, we kill the child. The forkserver should inform us afterwards */ @@ -427,11 +427,11 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) { afl->fsrv.child_timed_out = 1; /* After killing the child, the forkserver should tell us */ - if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) time_ms = 0; + if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) exec_ms = 0; } - if (!time_ms) { // Something went wrong. + if (!exec_ms) { // Something went wrong. if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index f58e1a33..8cef78b9 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -33,7 +33,7 @@ u8 run_target(afl_state_t *afl, u32 timeout) { s32 res; - u32 time_ms; + u32 exec_ms; int status = 0; u32 tb4; @@ -67,20 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) { if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); - time_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); + exec_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout); - if (time_ms > timeout) { + 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(afl->fsrv.child_pid, SIGKILL); afl->fsrv.child_timed_out = 1; - if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) time_ms = 0; + if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0; } - if (!time_ms) { + if (!exec_ms) { if (afl->stop_soon) return 0; SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 7fde2fdc..98a97a34 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -95,7 +95,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "last_hang : %llu\n" "execs_since_crash : %llu\n" "exec_timeout : %u\n" - "slowest_exec_ms : %llu\n" + "slowest_exec_ms : %u\n" "peak_rss_mb : %lu\n" "afl_banner : %s\n" "afl_version : " VERSION -- cgit 1.4.1