From abb337c8034c04edd4f2e1eca95c958644cb3b48 Mon Sep 17 00:00:00 2001 From: Guillaume Weghsteen Date: Mon, 26 Aug 2019 17:37:20 +0200 Subject: [PATCH 1/4] get max_rss stat at the end of the fuzzing session --- afl-fuzz.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/afl-fuzz.c b/afl-fuzz.c index 962bbf0b9..c40d99a5c 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -3385,6 +3385,7 @@ static void find_timeout(void) { static void write_stats_file(double bitmap_cvg, double stability, double eps) { static double last_bcvg, last_stab, last_eps; + static struct rusage usage; u8* fn = alloc_printf("%s/fuzzer_stats", out_dir); s32 fd; @@ -3457,6 +3458,19 @@ static void write_stats_file(double bitmap_cvg, double stability, double eps) { orig_cmdline); /* ignore errors */ + /* Get rss value from the children + We must have killed the forkserver process and called waitpid + before calling getrusage */ + if (getrusage(RUSAGE_CHILDREN, &usage)){ + WARNF("getrusage failed"); + } + else if (usage.ru_maxrss == 0){ + fprintf(f, "peak_rss_mb : not available while afl is running\n"); + } + else{ + fprintf(f, "peak_rss_mb : %zu\n", usage.ru_maxrss); + } + fclose(f); } @@ -8071,6 +8085,11 @@ int main(int argc, char** argv) { if (queue_cur) show_stats(); + /* Now that we've killed the forkserver, we wait for it to be able to get rusage stats. */ + if( waitpid(forksrv_pid, NULL, 0) <= 0 ) { + WARNF("error waitpid\n"); + } + write_bitmap(); write_stats_file(0, 0, 0); save_auto(); From 3890a9abdc353cd73b88b130002bdd5eed99682c Mon Sep 17 00:00:00 2001 From: Guillaume Weghsteen Date: Tue, 27 Aug 2019 13:17:11 +0200 Subject: [PATCH 2/4] add slowest_exec_ms metric (that is not a hang) --- afl-fuzz.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/afl-fuzz.c b/afl-fuzz.c index c40d99a5c..dd7bfed5b 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -181,6 +181,7 @@ EXP_ST u64 total_crashes, /* Total number of crashes */ 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) */ @@ -2272,6 +2273,7 @@ static u8 run_target(char** argv, u32 timeout) { static struct itimerval it; static u32 prev_timed_out = 0; + static u64 exec_ms = 0; int status = 0; u32 tb4; @@ -2419,6 +2421,12 @@ static u8 run_target(char** argv, u32 timeout) { } if (!WIFSTOPPED(status)) child_pid = 0; + + getitimer (ITIMER_REAL, &it); + exec_ms = (u64) timeout - (it.it_value.tv_sec * 1000 + it.it_value.tv_usec / 1000); + if (slowest_exec_ms < exec_ms){ + slowest_exec_ms = exec_ms; + } it.it_value.tv_sec = 0; it.it_value.tv_usec = 0; @@ -3441,7 +3449,8 @@ static void write_stats_file(double bitmap_cvg, double stability, double eps) { "afl_banner : %s\n" "afl_version : " VERSION "\n" "target_mode : %s%s%s%s%s%s%s\n" - "command_line : %s\n", + "command_line : %s\n" + "slowest_exec_ms : %llu\n", start_time / 1000, get_cur_time() / 1000, getpid(), queue_cycle ? (queue_cycle - 1) : 0, total_execs, eps, queued_paths, queued_favored, queued_discovered, queued_imported, @@ -3455,7 +3464,7 @@ static void write_stats_file(double bitmap_cvg, double stability, double eps) { persistent_mode ? "persistent " : "", deferred_mode ? "deferred " : "", (qemu_mode || dumb_mode || no_forkserver || crash_mode || persistent_mode || deferred_mode) ? "" : "default", - orig_cmdline); + orig_cmdline, slowest_exec_ms); /* ignore errors */ /* Get rss value from the children From e99b54d3bb2f307cbddd2210f713849ca7ce5d3b Mon Sep 17 00:00:00 2001 From: Guillaume Weghsteen Date: Tue, 27 Aug 2019 14:20:06 +0200 Subject: [PATCH 3/4] make sure the forkserver and current runner are killed when the session stops programmatically before calling waitpid --- afl-fuzz.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/afl-fuzz.c b/afl-fuzz.c index dd7bfed5b..3086077a9 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -8094,6 +8094,12 @@ int main(int argc, char** argv) { if (queue_cur) show_stats(); + /* if we stopped programmatically, we kill the forkserver and the current runner. + if we stopped manually, this is done by the signal handler */ + if (stop_soon == 2){ + if (child_pid > 0) kill(child_pid, SIGKILL); + if (forksrv_pid > 0) kill(forksrv_pid, SIGKILL); + } /* Now that we've killed the forkserver, we wait for it to be able to get rusage stats. */ if( waitpid(forksrv_pid, NULL, 0) <= 0 ) { WARNF("error waitpid\n"); From 4583aaed2bde15b39c0e3c67674f29dd60bcd693 Mon Sep 17 00:00:00 2001 From: Guillaume Weghsteen Date: Wed, 28 Aug 2019 10:37:12 +0200 Subject: [PATCH 4/4] This work is inspired by libFuzzer which already gathers these metrics. --- afl-fuzz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/afl-fuzz.c b/afl-fuzz.c index 3086077a9..021004889 100644 --- a/afl-fuzz.c +++ b/afl-fuzz.c @@ -2421,7 +2421,7 @@ static u8 run_target(char** argv, u32 timeout) { } if (!WIFSTOPPED(status)) child_pid = 0; - + getitimer (ITIMER_REAL, &it); exec_ms = (u64) timeout - (it.it_value.tv_sec * 1000 + it.it_value.tv_usec / 1000); if (slowest_exec_ms < exec_ms){