diff --git a/afl-fuzz.c b/afl-fuzz.c index ddeebd5f..41d0518d 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -116,8 +116,7 @@ EXP_ST u8 skip_deterministic, /* Skip deterministic stages? */ bitmap_changed = 1, /* Time to update bitmap? */ qemu_mode, /* Running in QEMU mode? */ skip_requested, /* Skip request, via SIGUSR1 */ - run_over10m, /* Run time over 10 minutes? */ - persistent_mode; /* Running in persistent mode? */ + run_over10m; /* Run time over 10 minutes? */ static s32 out_fd, /* Persistent fd for out_file */ dev_urandom_fd = -1, /* Persistent fd for /dev/urandom */ @@ -4201,7 +4200,7 @@ static void show_stats(void) { else strcpy(tmp, "n/a"); SAYF(" stability : %s%-10s " bSTG bV "\n", stab_ratio < 90 ? cLRD : - ((queued_variable && !persistent_mode) ? cMGN : cRST), tmp); + (queued_variable ? cMGN : cRST), tmp); if (!bytes_trim_out) { @@ -6870,7 +6869,6 @@ EXP_ST void check_binary(u8* fname) { OKF(cPIN "Deferred forkserver binary detected."); setenv(DEFER_ENV_VAR, "1", 1); - persistent_mode = 1; } else if (getenv("AFL_DEFER_FORKSRV")) { diff --git a/config.h b/config.h index 3bd31230..18beddbc 100644 --- a/config.h +++ b/config.h @@ -21,7 +21,7 @@ /* Version string: */ -#define VERSION "2.22b" +#define VERSION "2.23b" /****************************************************** * * diff --git a/docs/ChangeLog b/docs/ChangeLog index 64b80c1c..8f1cd7f1 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -16,6 +16,16 @@ Not sure if you should upgrade? The lowest currently recommended version is 2.21b. If you're stuck on an earlier release, it's strongly advisable to get on with the times. +-------------- +Version 2.23b: +-------------- + + - Improved the stability metric for persistent mode binaries. Problem + spotted by Kurt Roeckx. + + - Made a related improvement that may bring the metric to 100% for those + targets. + -------------- Version 2.22b: -------------- diff --git a/docs/README b/docs/README index 9c672dfb..85ae16b4 100644 --- a/docs/README +++ b/docs/README @@ -465,6 +465,7 @@ bug reports, or patches from: Austin Seipp Daniel Komaromy Daniel Binderman Jonathan Metzman Vegard Nossum Jan Kneschke + Kurt Roeckx Thank you! diff --git a/docs/status_screen.txt b/docs/status_screen.txt index d72f72e1..8068f93e 100644 --- a/docs/status_screen.txt +++ b/docs/status_screen.txt @@ -333,8 +333,10 @@ there are several things to look at: - Replace pthreads with GNU Pth (https://www.gnu.org/software/pth/), which allows you to use a deterministic scheduler. - - In persistent mode, the code within __AFL_LOOP() not working correctly on - subsequent iterations (e.g., due to incomplete clean-up or + - In persistent mode, minor reduction in the "stability" metric can be + normal, because not all the code behaves identically when re-entered; but + major drops may signify that the code within __AFL_LOOP() not working + correctly on subsequent iterations (e.g., due to incomplete clean-up or reinitialization of the state). The paths where variable behavior is detected are marked with a matching entry diff --git a/experimental/post_library/post_library.so.c b/experimental/post_library/post_library.so.c index 5cdee085..72620ff0 100644 --- a/experimental/post_library/post_library.so.c +++ b/experimental/post_library/post_library.so.c @@ -21,11 +21,11 @@ in the targeted binary (as shown in ../libpng_no_checksum/). One possible exception is the process of fuzzing binary-only software in QEMU mode. - 2) Use of postprocessors for anything other than checksums is questionable + 2) The use of postprocessors for anything other than checksums is questionable and may cause more harm than good. AFL is normally pretty good about dealing with length fields, magic values, etc. - 3) Post-processors that do anything non-trivial must be extremely robust to + 3) Postprocessors that do anything non-trivial must be extremely robust to gracefully handle malformed data and other error conditions - otherwise, they will crash and take afl-fuzz down with them. Be wary of reading past *len and of integer overflows when calculating file offsets. diff --git a/llvm_mode/README.llvm b/llvm_mode/README.llvm index 602d0e6c..f7d48c91 100644 --- a/llvm_mode/README.llvm +++ b/llvm_mode/README.llvm @@ -161,11 +161,6 @@ do not fully reset the critical state, you may end up with false positives or waste a whole lot of CPU power doing nothing useful at all. Be particularly wary of memory leaks and of the state of file descriptors. -When running in this mode, the execution paths will inherently vary a bit -depending on whether the input loop is being entered for the first time or -executed again. This can cause the "stability" metric in the UI to dip -slightly under 100%. - PS. Because there are task switches still involved, the mode isn't as fast as "pure" in-process fuzzing offered, say, by LLVM's LibFuzzer; but it is a lot faster than the normal fork() model, and compared to in-process fuzzing, diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 8f3f303d..62768d6f 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -169,18 +169,42 @@ int __afl_persistent_loop(unsigned int max_cnt) { if (first_pass) { + /* Make sure that every iteration of __AFL_LOOP() starts with a clean slate. + On subsequent calls, the parent will take care of that, but on the first + iteration, it's our job to erase any trace of whatever happened + before the loop. */ + + if (is_persistent) { + memset(__afl_area_ptr, 0, MAP_SIZE); + __afl_area_ptr[0] = 1; + } + cycle_cnt = max_cnt; first_pass = 0; return 1; } - if (is_persistent && --cycle_cnt) { + if (is_persistent) { - raise(SIGSTOP); - return 1; + if (--cycle_cnt) { + + raise(SIGSTOP); + return 1; + + } else { + + /* When exiting __AFL_LOOP(), make sure that the subsequent code that + follows the loop is not traced. We do that by pivoting back to the + dummy output region. */ + + __afl_area_ptr = __afl_area_initial; + + } + + } - } else return 0; + return 0; }