mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-10 01:01:33 +00:00
added read_timed
This commit is contained in:
parent
ef3a13fa63
commit
f4844e2c0c
@ -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
|
||||
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 <afl-users+subscribe@googlegroups.com>.
|
||||
(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
|
||||
|
@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#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
|
||||
|
||||
|
@ -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) \
|
||||
|
@ -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 {
|
||||
|
@ -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");
|
||||
|
||||
} else if (time_ms > timeout_ms) {
|
||||
|
||||
afl->fsrv.child_timed_out = 1;
|
||||
kill(afl->cmplog_fsrv_pid, SIGKILL);
|
||||
|
||||
} else {
|
||||
|
||||
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
|
||||
|
@ -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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -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. */
|
||||
time_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
Loading…
x
Reference in New Issue
Block a user