diff options
author | Rishi Ranjan <43873720+rish9101@users.noreply.github.com> | 2020-03-10 17:37:29 +0530 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-03-10 13:07:29 +0100 |
commit | cd377f3d99b142da0520b812998acac0dd415224 (patch) | |
tree | 419d0b2c238d70b78e43790bc71ac38f9ca0aeef | |
parent | 0def6e3471b8bbe7190843d6c266f2d88e454df1 (diff) | |
download | afl++-cd377f3d99b142da0520b812998acac0dd415224.tar.gz |
Replace alarms with select and threads (#243)
* Use select to monitor forkserver for timeouts instead of alarm * Remove redundent conditons in select monitoring of fdsin forkserver and cmplog * Replace SIGALARM with POSIX timers in afl-fuzz-run * Make changes to Makefile to use POSIX timers * Resolve Merge Conflicts and rename variables accordingly * Change forkserver and cmplog to handle exec_tmout = 0 * Handle timeout function bug rectify * Add error handling to afl-fuzz run timers * Add timer_delete to afl-fuzz-run * Remove memory leaks
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/afl-forkserver.c | 36 | ||||
-rw-r--r-- | src/afl-fuzz-cmplog.c | 36 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 100 |
4 files changed, 132 insertions, 42 deletions
diff --git a/Makefile b/Makefile index ee6f2453..40c7cc57 100644 --- a/Makefile +++ b/Makefile @@ -282,7 +282,7 @@ src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa. $(MAKE) -C src/third_party/libradamsa/ CFLAGS="$(CFLAGS)" afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86 - $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS) + $(CC) $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) -lrt src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS) afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86 $(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index bccd3d96..70bb4cfd 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -41,6 +41,7 @@ #include <sys/time.h> #include <sys/wait.h> #include <sys/resource.h> +#include <sys/select.h> /* Describe integer as memory size. */ @@ -168,10 +169,10 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { - static struct itimerval it; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; + struct timeval timeout; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; if (!getenv("AFL_QUIET")) ACTF("Spinning up the fork server..."); @@ -311,19 +312,30 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) { if (fsrv->exec_tmout) { - it.it_value.tv_sec = ((fsrv->exec_tmout * FORK_WAIT_MULT) / 1000); - it.it_value.tv_usec = ((fsrv->exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + fd_set readfds; - } + 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); - setitimer(ITIMER_REAL, &it, NULL); + if (sret == 0) { - rlen = read(fsrv->fsrv_st_fd, &status, 4); + fsrv->child_timed_out = 1; + kill(fsrv->child_pid, SIGKILL); - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; + } else { - setitimer(ITIMER_REAL, &it, NULL); + rlen = read(fsrv->fsrv_st_fd, &status, 4); + + } + } else { + + rlen = read(fsrv->fsrv_st_fd, &status, 4); + + } /* If we have a four-byte "hello" message from the server, we're all set. Otherwise, try to figure out what went wrong. */ diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index c32ed546..6e9f603b 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -24,15 +24,17 @@ */ +#include <sys/select.h> + #include "afl-fuzz.h" #include "cmplog.h" void init_cmplog_forkserver(afl_state_t *afl) { - static struct itimerval it; - int st_pipe[2], ctl_pipe[2]; - int status; - s32 rlen; + static struct timeval timeout; + int st_pipe[2], ctl_pipe[2]; + int status; + s32 rlen; ACTF("Spinning up the cmplog fork server..."); @@ -182,20 +184,28 @@ void init_cmplog_forkserver(afl_state_t *afl) { if (afl->fsrv.exec_tmout) { - it.it_value.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000); - it.it_value.tv_usec = - ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000; + 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; - } + int sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout); - setitimer(ITIMER_REAL, &it, NULL); + if (sret == 0) { - rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); + kill(afl->cmplog_fsrv_pid, SIGKILL); - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; + } else { - setitimer(ITIMER_REAL, &it, NULL); + rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); + + } + } else { + + rlen = read(afl->cmplog_fsrv_st_fd, &status, 4); + + } /* If we have a four-byte "hello" message from the server, we're all set. Otherwise, try to figure out what went wrong. */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index fd8b1e46..786c5c68 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -24,18 +24,31 @@ */ #include "afl-fuzz.h" +#include <sys/time.h> +#include <signal.h> /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv.trace_bits[]. */ +void timeout_handle(union sigval timer_data) { + + pid_t child_pid = timer_data.sival_int; + if (child_pid > 0) kill(child_pid, SIGKILL); + +} + u8 run_target(afl_state_t* afl, u32 timeout) { - static struct itimerval it; - static u32 prev_timed_out = 0; - static u64 exec_ms = 0; + // static struct itimerval it; + struct sigevent timer_signal_event; + static timer_t timer; + static struct itimerspec timer_period; + static u32 prev_timed_out = 0; + static u64 exec_ms = 0; int status = 0; u32 tb4; + int timer_status; afl->fsrv.child_timed_out = 0; @@ -44,6 +57,11 @@ u8 run_target(afl_state_t* afl, u32 timeout) { territory. */ memset(afl->fsrv.trace_bits, 0, MAP_SIZE); + memset(&timer_signal_event, 0, sizeof(struct sigevent)); + + timer_signal_event.sigev_notify = SIGEV_THREAD; + timer_signal_event.sigev_notify_function = timeout_handle; + MEM_BARRIER(); /* If we're running in "dumb" mode, we can't rely on the fork server @@ -142,14 +160,14 @@ u8 run_target(afl_state_t* afl, u32 timeout) { if ((res = write(afl->fsrv.fsrv_ctl_fd, &prev_timed_out, 4)) != 4) { - if (afl->stop_soon) return 0; + if (afl->stop_soon) goto handle_stop_soon; RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } if ((res = read(afl->fsrv.fsrv_st_fd, &afl->fsrv.child_pid, 4)) != 4) { - if (afl->stop_soon) return 0; + if (afl->stop_soon) goto handle_stop_soon; RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } @@ -160,27 +178,56 @@ u8 run_target(afl_state_t* afl, u32 timeout) { /* Configure timeout, as requested by user, then wait for child to terminate. */ + timer_signal_event.sigev_value.sival_int = afl->fsrv.child_pid; + timer_status = timer_create(CLOCK_MONOTONIC, &timer_signal_event, &timer); + + if (timer_status == -1) { - it.it_value.tv_sec = (timeout / 1000); - it.it_value.tv_usec = (timeout % 1000) * 1000; + FATAL("Failed to create Timer"); + + } + + timer_period.it_value.tv_sec = (timeout / 1000); + timer_period.it_value.tv_nsec = (timeout % 1000) * 1000000; + timer_period.it_interval.tv_sec = 0; + timer_period.it_interval.tv_nsec = 0; + + timer_status = timer_settime(timer, 0, &timer_period, NULL); + + if (timer_status == -1) { + + timer_delete(timer); + if (errno == EINVAL) { + + FATAL("Failed to set the timer. The timeout given is invalid."); + + } else { + + FATAL("Failed to set the timer to the given timeout"); + + } + + } - setitimer(ITIMER_REAL, &it, NULL); /* The SIGALRM handler simply kills the afl->fsrv.child_pid and sets * afl->fsrv.child_timed_out. */ if (afl->dumb_mode == 1 || afl->no_forkserver) { - if (waitpid(afl->fsrv.child_pid, &status, 0) <= 0) + if (waitpid(afl->fsrv.child_pid, &status, 0) <= 0) { + + timer_delete(timer); PFATAL("waitpid() failed"); + } } else { s32 res; if ((res = read(afl->fsrv.fsrv_st_fd, &status, 4)) != 4) { - if (afl->stop_soon) return 0; + if (afl->stop_soon) goto handle_stop_soon; SAYF( "\n" cLRD "[-] " cRST "Unable to communicate with fork server. Some possible reasons:\n\n" @@ -200,6 +247,7 @@ u8 run_target(afl_state_t* afl, u32 timeout) { "If all else fails you can disable the fork server via " "AFL_NO_FORKSRV=1.\n", afl->fsrv.mem_limit); + timer_delete(timer); RPFATAL(res, "Unable to communicate with fork server"); } @@ -208,15 +256,30 @@ u8 run_target(afl_state_t* afl, u32 timeout) { if (!WIFSTOPPED(status)) afl->fsrv.child_pid = 0; - getitimer(ITIMER_REAL, &it); - exec_ms = - (u64)timeout - (it.it_value.tv_sec * 1000 + it.it_value.tv_usec / 1000); + timer_gettime(timer, &timer_period); + exec_ms = (u64)timeout - (timer_period.it_value.tv_sec * 1000 + + timer_period.it_value.tv_nsec / 1000000); if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms; - it.it_value.tv_sec = 0; - it.it_value.tv_usec = 0; + if (exec_ms >= timeout) { + + afl->fsrv.child_timed_out = 1; + + } + + timer_period.it_value.tv_sec = 0; + timer_period.it_value.tv_nsec = 0; + + timer_status = timer_settime(timer, 0, &timer_period, NULL); + + if (timer_status == -1) { - setitimer(ITIMER_REAL, &it, NULL); + timer_delete(timer); + FATAL("Failed to reset the timer."); + + } + + timer_delete(timer); ++afl->total_execs; @@ -264,6 +327,11 @@ u8 run_target(afl_state_t* afl, u32 timeout) { return FAULT_NONE; + handle_stop_soon: + printf("CALLED"); + timer_delete(timer); + return 0; + } /* Write modified data to file for testing. If afl->fsrv.out_file is set, the |