added read_timed

This commit is contained in:
Dominik Maier
2020-03-30 00:50:04 +02:00
parent 3ce5efc44b
commit 452067ffca
7 changed files with 112 additions and 81 deletions

View File

@ -16,12 +16,14 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
! development and acceptance of PRs now happen only in the dev branch ! development and acceptance of PRs now happen only in the dev branch
and only occasionally when everything is fine we PR to master and only occasionally when everything is fine we PR to master
- all: - 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 multiple fuzzing threads in the future or even become a library
- afl basic tools now report on the environment variables picked up - afl basic tools now report on the environment variables picked up
- more tools get environment variable usage info in the help output - more tools get environment variable usage info in the help output
- force all output to stdout (some OK/SAY/WARN messages were sent to - force all output to stdout (some OK/SAY/WARN messages were sent to
stdout, some to stderr) stdout, some to stderr)
- uninstrumented mode uses an internal forkserver ("fauxserver")
- reduced number of (de)allocations
- afl-fuzz: - afl-fuzz:
- python mutator modules and custom mutator modules now use the same - python mutator modules and custom mutator modules now use the same
interface and hence the API changed interface and hence the API changed
@ -38,7 +40,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
(https://github.com/adrianherrera/afl-ngram-pass/), activate by setting (https://github.com/adrianherrera/afl-ngram-pass/), activate by setting
AFL_LLVM_NGRAM_SIZE AFL_LLVM_NGRAM_SIZE
- llvm_mode InsTrim mode: - 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 imported fix by author
- made skipping 1 block functions an option and is disable by default, - made skipping 1 block functions an option and is disable by default,
set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to re-enable this set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to re-enable this

View File

@ -29,6 +29,7 @@
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <sys/time.h> #include <sys/time.h>
#include "types.h" #include "types.h"
#include "stdbool.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 #endif

View File

@ -58,8 +58,22 @@ typedef int32_t s32;
typedef int64_t s64; typedef int64_t s64;
#ifndef MIN #ifndef MIN
#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a)) #define MIN(a, b) \
#define MAX(_a, _b) ((_a) > (_b) ? (_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 */ #endif /* !MIN */
#define SWAP16(_x) \ #define SWAP16(_x) \

View File

@ -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) { void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
struct timeval timeout; int st_pipe[2], ctl_pipe[2];
int st_pipe[2], ctl_pipe[2]; int status;
int status; s32 rlen;
s32 rlen;
if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:"); if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:");
@ -318,24 +317,15 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
rlen = 0; rlen = 0;
if (fsrv->exec_tmout) { 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); if (!time) {
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) {
fsrv->child_timed_out = 1; fsrv->child_timed_out = 1;
kill(fsrv->child_pid, SIGKILL); kill(fsrv->child_pid, SIGKILL);
} else {
rlen = read(fsrv->fsrv_st_fd, &status, 4);
} }
} else { } else {

View File

@ -31,10 +31,9 @@
void init_cmplog_forkserver(afl_state_t *afl) { void init_cmplog_forkserver(afl_state_t *afl) {
struct timeval timeout; int st_pipe[2], ctl_pipe[2];
int st_pipe[2], ctl_pipe[2]; int status;
int status; s32 rlen;
s32 rlen;
ACTF("Spinning up the cmplog fork server..."); ACTF("Spinning up the cmplog fork server...");
@ -185,21 +184,19 @@ void init_cmplog_forkserver(afl_state_t *afl) {
rlen = 0; rlen = 0;
if (afl->fsrv.exec_tmout) { if (afl->fsrv.exec_tmout) {
fd_set readfds; rlen = 4;
FD_ZERO(&readfds); u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
FD_SET(afl->cmplog_fsrv_st_fd, &readfds); /* Reuse readfds as exceptfds to see when the child closed the pipe */
timeout.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000); u32 time_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms);
timeout.tv_usec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
int sret = if (!time_ms) {
select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
if (sret == 0) { PFATAL("Error in timed read");
} else if (time_ms > timeout_ms) {
afl->fsrv.child_timed_out = 1;
kill(afl->cmplog_fsrv_pid, SIGKILL); kill(afl->cmplog_fsrv_pid, SIGKILL);
} else {
rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); 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. /* If we have a four-byte "hello" message from the server, we're all set.
Otherwise, try to figure out what went wrong. */ 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) { if (rlen == 4) {
OKF("All right - fork server is up."); 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) if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0)
PFATAL("waitpid() failed"); 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) { u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
struct timeval it; int status = 0;
int status = 0; u64 exec_ms;
int sret;
u64 exec_ms;
u32 tb4; u32 tb4;
s32 res; s32 res;
fd_set readfds;
afl->fsrv.child_timed_out = 0; afl->fsrv.child_timed_out = 0;
/* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we /* 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. /* 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); if (time_ms > timeout) {
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 there was no response from forkserver after timeout seconds, /* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */ 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); kill(afl->cmplog_child_pid, SIGKILL);
afl->fsrv.child_timed_out = 1; 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; if (afl->stop_soon) return 0;
SAYF("\n" cLRD "[-] " cRST 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; 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; if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms;
it.tv_sec = 0;
it.tv_usec = 0;
++afl->total_execs; ++afl->total_execs;
/* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the /* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the

View File

@ -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].hits) continue;
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) 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 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);
} }

View File

@ -33,13 +33,10 @@
u8 run_target(afl_state_t *afl, u32 timeout) { u8 run_target(afl_state_t *afl, u32 timeout) {
s32 res; s32 res;
int sret; u32 time_ms;
fd_set readfds; int status = 0;
u32 tb4;
struct timeval it;
int status = 0;
u32 tb4;
afl->fsrv.child_timed_out = 0; 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?)"); if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
/* use select to monitor the forkserver for timeouts. */ time_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout);
FD_ZERO(&readfds); if (time_ms > timeout) {
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);
if (sret == 0) {
/* If there was no response from forkserver after timeout seconds, /* If there was no response from forkserver after timeout seconds,
we kill the child. The forkserver should inform us afterwards */ we kill the child. The forkserver should inform us afterwards */
kill(afl->fsrv.child_pid, SIGKILL); kill(afl->fsrv.child_pid, SIGKILL);
afl->fsrv.child_timed_out = 1; 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; if (afl->stop_soon) return 0;
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST