From e30b2c6af6e369844c92c00a20ebdd53473a747c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 5 Sep 2020 13:18:28 +0200 Subject: final changes for pre-3.0 --- src/afl-fuzz-stats.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 51eed14b..c60c65aa 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -982,10 +982,9 @@ void show_stats(afl_state_t *afl) { void show_init_stats(afl_state_t *afl) { struct queue_entry *q = afl->queue; - u32 min_bits = 0, max_bits = 0; + u32 min_bits = 0, max_bits = 0, max_len = 0, count = 0; u64 min_us = 0, max_us = 0; u64 avg_us = 0; - u32 max_len = 0; u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX]; #define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)]) @@ -1006,6 +1005,7 @@ void show_init_stats(afl_state_t *afl) { if (q->len > max_len) { max_len = q->len; } + ++count; q = q->next; } @@ -1072,10 +1072,10 @@ void show_init_stats(afl_state_t *afl) { OKF("Here are some useful stats:\n\n" cGRA " Test case count : " cRST - "%u favored, %u variable, %u total\n" cGRA " Bitmap range : " cRST + "%u favored, %u variable, %u ignored, %u total\n" cGRA " Bitmap range : " cRST "%u to %u bits (average: %0.02f bits)\n" cGRA " Exec timing : " cRST "%s to %s us (average: %s us)\n", - afl->queued_favored, afl->queued_variable, afl->queued_paths, min_bits, + afl->queued_favored, afl->queued_variable, afl->queued_paths - count, afl->queued_paths, min_bits, max_bits, ((double)afl->total_bitmap_size) / (afl->total_bitmap_entries ? afl->total_bitmap_entries : 1), -- cgit 1.4.1 From 2f90f2faba92c0ef5e081ff74b54fb07eb1faaa9 Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 5 Sep 2020 13:19:19 +0200 Subject: code-format --- src/afl-fuzz-init.c | 23 +++++++++++++---------- src/afl-fuzz-queue.c | 3 ++- src/afl-fuzz-stats.c | 16 +++++++++------- 3 files changed, 24 insertions(+), 18 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 1351d274..c834e5db 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -617,24 +617,27 @@ void read_testcases(afl_state_t *afl, u8 *directory) { s32 nl_cnt, subdirs = 1; u32 i; u8 * fn1, *dir = directory; - u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX]; + u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX]; /* Auto-detect non-in-place resumption attempts. */ -if (dir == NULL) { - fn1 = alloc_printf("%s/queue", afl->in_dir); - if (!access(fn1, F_OK)) { + if (dir == NULL) { - afl->in_dir = fn1; - subdirs = 0; + fn1 = alloc_printf("%s/queue", afl->in_dir); + if (!access(fn1, F_OK)) { - } else { + afl->in_dir = fn1; + subdirs = 0; + + } else { - ck_free(fn1); + ck_free(fn1); + + } + + dir = afl->in_dir; } - dir = afl->in_dir; -} ACTF("Scanning '%s'...", dir); diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index af52aa45..8c7bfc55 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -138,7 +138,8 @@ static u8 check_if_text(struct queue_entry *q) { } // non-overlong 2-byte - if (len - offset > 1 && ((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && + if (len - offset > 1 && + ((0xC2 <= buf[offset + 0] && buf[offset + 0] <= 0xDF) && (0x80 <= buf[offset + 1] && buf[offset + 1] <= 0xBF))) { offset += 2; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index c60c65aa..dfc0cd97 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -35,12 +35,12 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { u8 fn[PATH_MAX]; snprintf(fn, PATH_MAX, "%s/fuzzer_setup", afl->out_dir); FILE *f = create_ffile(fn); - u32 i; + u32 i; fprintf(f, "# environment variables:\n"); - u32 s_afl_env = (u32) - sizeof(afl_environment_variables) / sizeof(afl_environment_variables[0]) - - 1U; + u32 s_afl_env = (u32)sizeof(afl_environment_variables) / + sizeof(afl_environment_variables[0]) - + 1U; for (i = 0; i < s_afl_env; ++i) { @@ -75,6 +75,7 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) { } } + fprintf(f, "\n"); fclose(f); @@ -1072,11 +1073,12 @@ void show_init_stats(afl_state_t *afl) { OKF("Here are some useful stats:\n\n" cGRA " Test case count : " cRST - "%u favored, %u variable, %u ignored, %u total\n" cGRA " Bitmap range : " cRST + "%u favored, %u variable, %u ignored, %u total\n" cGRA + " Bitmap range : " cRST "%u to %u bits (average: %0.02f bits)\n" cGRA " Exec timing : " cRST "%s to %s us (average: %s us)\n", - afl->queued_favored, afl->queued_variable, afl->queued_paths - count, afl->queued_paths, min_bits, - max_bits, + afl->queued_favored, afl->queued_variable, afl->queued_paths - count, + afl->queued_paths, min_bits, max_bits, ((double)afl->total_bitmap_size) / (afl->total_bitmap_entries ? afl->total_bitmap_entries : 1), stringify_int(IB(0), min_us), stringify_int(IB(1), max_us), -- cgit 1.4.1 From 6404abd7d609350ffd6c6f221cbf56e60b2ef030 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 7 Sep 2020 17:30:28 +0200 Subject: bugfix for fixed seeds --- src/afl-fuzz-queue.c | 2 +- src/afl-fuzz-stats.c | 12 ++++++++++-- 2 files changed, 11 insertions(+), 3 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 8c7bfc55..336b7f4f 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -502,7 +502,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { // Longer execution time means longer work on the input, the deeper in // coverage, the better the fuzzing, right? -mh - if (afl->schedule >= RARE && likely(!afl->fixed_seed)) { + if (likely(afl->schedule < RARE) && likely(!afl->fixed_seed)) { if (q->exec_us * 0.1 > avg_exec_us) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index dfc0cd97..1d5b169d 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1022,7 +1022,11 @@ void show_init_stats(afl_state_t *afl) { /* Let's keep things moving with slow binaries. */ - if (avg_us > 50000) { + if (unlikely(afl->fixed_seed)) { + + afl->havoc_div = 1; + + } else if (avg_us > 50000) { afl->havoc_div = 10; /* 0-19 execs/sec */ @@ -1093,7 +1097,11 @@ void show_init_stats(afl_state_t *afl) { random scheduler jitter is less likely to have any impact, and because our patience is wearing thin =) */ - if (avg_us > 50000) { + if (unlikely(afl->fixed_seed)) { + + afl->fsrv.exec_tmout = avg_us * 5 / 1000; + + } else if (avg_us > 50000) { afl->fsrv.exec_tmout = avg_us * 2 / 1000; -- cgit 1.4.1 From 6006cce0cf012884d1509c00ef0f088aeac66bb7 Mon Sep 17 00:00:00 2001 From: Edznux Date: Sun, 4 Oct 2020 03:24:09 +0200 Subject: Define config, change parent func to show_stats --- include/config.h | 1 + src/afl-fuzz-run.c | 6 ------ src/afl-fuzz-stats.c | 8 ++++++++ 3 files changed, 9 insertions(+), 6 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/include/config.h b/include/config.h index 104276e3..c55dda2b 100644 --- a/include/config.h +++ b/include/config.h @@ -46,6 +46,7 @@ Server config can be adjusted with AFL_STATSD_HOST and AFL_STATSD_PORT env var. */ #define USE_STATSD +#define STATSD_UPDATE_SEC 1 /* If you want to have the original afl internal memory corruption checks. Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index b7c4ae05..6fa142d2 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -901,12 +901,6 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { afl->stage_cur + 1 == afl->stage_max) { show_stats(afl); - #ifdef USE_STATSD - if(send_statsd_metric(afl)){ - //Change me to something realistic; don't fail on connection / lookup fail for metrics... - exit(1); - } - #endif } return 0; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 51eed14b..bbbe6ba6 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -422,6 +422,14 @@ void show_stats(afl_state_t *afl) { } + #ifdef USE_STATSD + if (cur_ms - afl->stats_last_stats_ms > STATSD_UPDATE_SEC * 1000) { + if(send_statsd_metric(afl)){ + WARNF("coundln't send statsd metric."); + } + } + #endif + /* Every now and then, write plot data. */ if (cur_ms - afl->stats_last_plot_ms > PLOT_UPDATE_SEC * 1000) { -- cgit 1.4.1 From ca6106a1dc5b39df9f167b3d30ea4472636564c9 Mon Sep 17 00:00:00 2001 From: Edznux Date: Sun, 4 Oct 2020 14:24:25 +0200 Subject: Refactor --- include/afl-fuzz.h | 4 ++- include/config.h | 2 ++ src/afl-fuzz-stats.c | 6 +++-- src/afl-fuzz-statsd.c | 73 ++++++++++++++++++++++++++------------------------- 4 files changed, 46 insertions(+), 39 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index eecfcf75..f341e300 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -635,6 +635,8 @@ typedef struct afl_state { u64 plot_prev_qc, plot_prev_uc, plot_prev_uh, plot_prev_ed; u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs; + // StatsD + u64 statsd_last_send_ms; double stats_avg_exec; u8 *clean_trace; @@ -957,7 +959,7 @@ void show_init_stats(afl_state_t *); /* StatsD */ int statsd_socket_init(char *host, int port); -int send_statsd_metric(afl_state_t *afl); +int statsd_send_metric(afl_state_t *afl); int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen); /* Run */ diff --git a/include/config.h b/include/config.h index c55dda2b..8cdf0633 100644 --- a/include/config.h +++ b/include/config.h @@ -47,6 +47,8 @@ Server config can be adjusted with AFL_STATSD_HOST and AFL_STATSD_PORT env var. #define USE_STATSD #define STATSD_UPDATE_SEC 1 +#define STATSD_DEFAULT_PORT 8125 +#define STATSD_DEFAULT_HOST "127.0.0.1" /* If you want to have the original afl internal memory corruption checks. Disabled by default for speed. it is better to use "make ASAN_BUILD=1". */ diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index bbbe6ba6..ffef7647 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -423,8 +423,10 @@ void show_stats(afl_state_t *afl) { } #ifdef USE_STATSD - if (cur_ms - afl->stats_last_stats_ms > STATSD_UPDATE_SEC * 1000) { - if(send_statsd_metric(afl)){ + if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) { + /* reset counter, even if send failed. */ + afl->statsd_last_send_ms = cur_ms; + if(statsd_send_metric(afl)){ WARNF("coundln't send statsd metric."); } } diff --git a/src/afl-fuzz-statsd.c b/src/afl-fuzz-statsd.c index d9cd12d2..5bd1b537 100644 --- a/src/afl-fuzz-statsd.c +++ b/src/afl-fuzz-statsd.c @@ -13,11 +13,12 @@ #define MAX_TAG_LEN 200 #define METRIC_PREFIX "fuzzing" -int sock = 0; struct sockaddr_in server; int error = 0; +int statds_sock = 0; int statsd_socket_init(char *host, int port){ + int sock; if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ perror("socket"); exit(1); @@ -42,72 +43,72 @@ int statsd_socket_init(char *host, int port){ memcpy(&(server.sin_addr), &((struct sockaddr_in*)result->ai_addr)->sin_addr, sizeof(struct in_addr)); freeaddrinfo(result); - return 0; + return sock; } -int send_statsd_metric(afl_state_t *afl){ - /* default port and host. +int statsd_send_metric(afl_state_t *afl){ + + char buff[MAX_STATSD_PACKET_SIZE] = {0}; + /* Default port and host. Will be overwritten by AFL_STATSD_PORT and AFL_STATSD_HOST environment variable, if they exists. - */ - u16 port = 8125; - char* host = "127.0.0.1"; + */ + u16 port = STATSD_DEFAULT_PORT; + char* host = STATSD_DEFAULT_HOST; char* port_env; char* host_env; if ((port_env = getenv("AFL_STATSD_PORT")) != NULL) { - // sanitization check ? port = atoi(port_env); } if ((host_env = getenv("AFL_STATSD_HOST")) != NULL) { - // sanitization check ? host = host_env; } - - error = statsd_socket_init(host, port); - if (error){ - perror("Failed to init statsd client. Aborting"); - return -1; - } - - if(!sock){ - perror("sock"); - return -1; - } - char buff[MAX_STATSD_PACKET_SIZE] = {0}; + /* statds_sock is a global variable. We set it once in the beginning and reuse the socket. + If the sendto later fail, we reset it to 0 to be able to recreate it. + */ + if(!statds_sock){ + statds_sock = statsd_socket_init(host, port); + if(!statds_sock){ + perror("Cannot create socket"); + return -1; + } + } statsd_format_metric(afl, buff, MAX_STATSD_PACKET_SIZE); - if (sendto(sock, buff, strlen(buff), 0, - (struct sockaddr *)&server, sizeof(server)) == -1) { - perror("sendto"); - return -1; + if (sendto(statds_sock, buff, strlen(buff), 0, (struct sockaddr *)&server, sizeof(server)) == -1) { + if(!close(statds_sock)){ + perror("Cannot close socket"); + } + statds_sock = 0; + perror("Cannot sendto"); + return -1; } - close(sock); - sock=0; - return 0; } int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen){ - /* - metric format: - :|| - tags format: + /* Metric format: + :| */ #ifdef USE_STATSD_TAGS - /* #key:value,key:value,key + /* Tags format: DogStatsD + :||#key:value,key:value,key */ char tags[MAX_TAG_LEN * 2] = {0}; snprintf(tags, MAX_TAG_LEN * 2, "|#banner:%s,afl_version:%s", afl->use_banner, VERSION); - #else + #else + /* No tags. + */ char *tags = ""; #endif - // Sends multiple metrics with one UDP Packet. - // bufflen will limit to the max safe size. + /* Sends multiple metrics with one UDP Packet. + bufflen will limit to the max safe size. + */ snprintf(buff, bufflen, METRIC_PREFIX".cycle_done:%llu|g%s\n" METRIC_PREFIX".cycles_wo_finds:%llu|g%s\n" -- cgit 1.4.1 From 1a12db1b59e792c7a46e606fba60bdf855d00c29 Mon Sep 17 00:00:00 2001 From: Edznux Date: Sun, 4 Oct 2020 16:11:05 +0200 Subject: Code format --- include/afl-fuzz.h | 1 + src/afl-fuzz-run.c | 1 + src/afl-fuzz-stats.c | 11 ++- src/afl-fuzz-statsd.c | 256 +++++++++++++++++++++++++------------------------- 4 files changed, 136 insertions(+), 133 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 427e1aec..75dfc4e5 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -635,6 +635,7 @@ typedef struct afl_state { u64 stats_last_stats_ms, stats_last_plot_ms, stats_last_ms, stats_last_execs; // StatsD u64 statsd_last_send_ms; + double stats_avg_exec; u8 *clean_trace; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 5e74dff3..ee22b0f6 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -903,6 +903,7 @@ common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { afl->stage_cur + 1 == afl->stage_max) { show_stats(afl); + } return 0; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 2f1e3367..942670b4 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -423,15 +423,16 @@ void show_stats(afl_state_t *afl) { } - #ifdef USE_STATSD +#ifdef USE_STATSD if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) { + /* reset counter, even if send failed. */ afl->statsd_last_send_ms = cur_ms; - if(statsd_send_metric(afl)){ - WARNF("coundln't send statsd metric."); - } + if (statsd_send_metric(afl)) { WARNF("coundln't send statsd metric."); } + } - #endif + +#endif /* Every now and then, write plot data. */ diff --git a/src/afl-fuzz-statsd.c b/src/afl-fuzz-statsd.c index 298138be..e94f090c 100644 --- a/src/afl-fuzz-statsd.c +++ b/src/afl-fuzz-statsd.c @@ -8,149 +8,149 @@ #include #include "afl-fuzz.h" - #define MAX_STATSD_PACKET_SIZE 4096 #define MAX_TAG_LEN 200 #define METRIC_PREFIX "fuzzing" struct sockaddr_in server; -int error = 0; -int statds_sock = 0; - -int statsd_socket_init(char *host, int port){ - int sock; - if((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1){ - perror("socket"); - exit(1); - } +int error = 0; +int statds_sock = 0; - memset(&server, 0, sizeof(server)); - server.sin_family = AF_INET; - server.sin_port = htons(port); - - struct addrinfo *result; - struct addrinfo hints; +int statsd_socket_init(char *host, int port) { - memset(&hints, 0, sizeof(struct addrinfo)); - hints.ai_family = AF_INET; - hints.ai_socktype = SOCK_DGRAM; + int sock; + if ((sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { - if ( (error = getaddrinfo(host, NULL, &hints, &result)) ) { - perror("getaddrinfo"); - exit(1); - } + FATAL("Failed to create socket"); + + } + + memset(&server, 0, sizeof(server)); + server.sin_family = AF_INET; + server.sin_port = htons(port); + + struct addrinfo *result; + struct addrinfo hints; + + memset(&hints, 0, sizeof(struct addrinfo)); + hints.ai_family = AF_INET; + hints.ai_socktype = SOCK_DGRAM; - memcpy(&(server.sin_addr), &((struct sockaddr_in*)result->ai_addr)->sin_addr, sizeof(struct in_addr)); - freeaddrinfo(result); + if ((error = getaddrinfo(host, NULL, &hints, &result))) { + + FATAL("Fail to getaddrinfo"); + + } + + memcpy(&(server.sin_addr), &((struct sockaddr_in *)result->ai_addr)->sin_addr, + sizeof(struct in_addr)); + freeaddrinfo(result); + + return sock; - return sock; } -int statsd_send_metric(afl_state_t *afl){ - - char buff[MAX_STATSD_PACKET_SIZE] = {0}; - /* Default port and host. - Will be overwritten by AFL_STATSD_PORT and AFL_STATSD_HOST environment variable, if they exists. - */ - u16 port = STATSD_DEFAULT_PORT; - char* host = STATSD_DEFAULT_HOST; - - char* port_env; - char* host_env; - if ((port_env = getenv("AFL_STATSD_PORT")) != NULL) { - port = atoi(port_env); - } - if ((host_env = getenv("AFL_STATSD_HOST")) != NULL) { - host = host_env; - } +int statsd_send_metric(afl_state_t *afl) { - /* statds_sock is a global variable. We set it once in the beginning and reuse the socket. - If the sendto later fail, we reset it to 0 to be able to recreate it. - */ - if(!statds_sock){ - statds_sock = statsd_socket_init(host, port); - if(!statds_sock){ - perror("Cannot create socket"); - return -1; - } - } + char buff[MAX_STATSD_PACKET_SIZE] = {0}; + /* Default port and host. + Will be overwritten by AFL_STATSD_PORT and AFL_STATSD_HOST environment + variable, if they exists. + */ + u16 port = STATSD_DEFAULT_PORT; + char *host = STATSD_DEFAULT_HOST; + + char *port_env; + char *host_env; + if ((port_env = getenv("AFL_STATSD_PORT")) != NULL) { port = atoi(port_env); } + if ((host_env = getenv("AFL_STATSD_HOST")) != NULL) { host = host_env; } + + /* statds_sock is a global variable. We set it once in the beginning and reuse + the socket. If the sendto later fail, we reset it to 0 to be able to recreate + it. + */ + if (!statds_sock) { + + statds_sock = statsd_socket_init(host, port); + if (!statds_sock) { + + WARNF("Cannot create socket"); + return -1; - statsd_format_metric(afl, buff, MAX_STATSD_PACKET_SIZE); - if (sendto(statds_sock, buff, strlen(buff), 0, (struct sockaddr *)&server, sizeof(server)) == -1) { - if(!close(statds_sock)){ - perror("Cannot close socket"); - } - statds_sock = 0; - perror("Cannot sendto"); - return -1; } - return 0; + } + + statsd_format_metric(afl, buff, MAX_STATSD_PACKET_SIZE); + if (sendto(statds_sock, buff, strlen(buff), 0, (struct sockaddr *)&server, + sizeof(server)) == -1) { + + if (!close(statds_sock)) { perror("Cannot close socket"); } + statds_sock = 0; + WARNF("Cannot sendto"); + return -1; + + } + + return 0; + +} + +int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen) { + +/* Metric format: +:| +*/ +#ifdef USE_DOGSTATSD_TAGS + /* Tags format: DogStatsD + :||#key:value,key:value,key + */ + char tags[MAX_TAG_LEN * 2] = {0}; + snprintf(tags, MAX_TAG_LEN * 2, "|#banner:%s,afl_version:%s", afl->use_banner, + VERSION); +#else + /* No tags. + */ + char *tags = ""; +#endif + /* Sends multiple metrics with one UDP Packet. + bufflen will limit to the max safe size. + */ + snprintf(buff, bufflen, + METRIC_PREFIX ".cycle_done:%llu|g%s\n" METRIC_PREFIX + ".cycles_wo_finds:%llu|g%s\n" METRIC_PREFIX + ".execs_done:%llu|g%s\n" METRIC_PREFIX + ".execs_per_sec:%0.02f|g%s\n" METRIC_PREFIX + ".paths_total:%u|g%s\n" METRIC_PREFIX + ".paths_favored:%u|g%s\n" METRIC_PREFIX + ".paths_found:%u|g%s\n" METRIC_PREFIX + ".paths_imported:%u|g%s\n" METRIC_PREFIX + ".max_depth:%u|g%s\n" METRIC_PREFIX + ".cur_path:%u|g%s\n" METRIC_PREFIX + ".pending_favs:%u|g%s\n" METRIC_PREFIX + ".pending_total:%u|g%s\n" METRIC_PREFIX + ".variable_paths:%u|g%s\n" METRIC_PREFIX + ".unique_crashes:%llu|g%s\n" METRIC_PREFIX + ".unique_hangs:%llu|g%s\n" METRIC_PREFIX + ".total_crashes:%llu|g%s\n" METRIC_PREFIX + ".slowest_exec_ms:%u|g%s\n" METRIC_PREFIX + ".edges_found:%u|g%s\n" METRIC_PREFIX + ".var_byte_count:%u|g%s\n" METRIC_PREFIX + ".havoc_expansion:%u|g%s\n", + afl->queue_cycle ? (afl->queue_cycle - 1) : 0, tags, + afl->cycles_wo_finds, tags, afl->fsrv.total_execs, tags, + afl->fsrv.total_execs / + ((double)(get_cur_time() - afl->start_time) / 1000), + tags, afl->queued_paths, tags, afl->queued_favored, tags, + afl->queued_discovered, tags, afl->queued_imported, tags, + afl->max_depth, tags, afl->current_entry, tags, afl->pending_favored, + tags, afl->pending_not_fuzzed, tags, afl->queued_variable, tags, + afl->unique_crashes, tags, afl->unique_hangs, tags, + afl->total_crashes, tags, afl->slowest_exec_ms, tags, + count_non_255_bytes(afl, afl->virgin_bits), tags, + afl->var_byte_count, tags, afl->expand_havoc, tags); + + return 0; + } -int statsd_format_metric(afl_state_t *afl, char *buff, size_t bufflen){ - /* Metric format: - :| - */ - #ifdef USE_DOGSTATSD_TAGS - /* Tags format: DogStatsD - :||#key:value,key:value,key - */ - char tags[MAX_TAG_LEN * 2] = {0}; - snprintf(tags, MAX_TAG_LEN * 2, - "|#banner:%s,afl_version:%s", - afl->use_banner, - VERSION); - #else - /* No tags. - */ - char *tags = ""; - #endif - /* Sends multiple metrics with one UDP Packet. - bufflen will limit to the max safe size. - */ - snprintf(buff, bufflen, - METRIC_PREFIX".cycle_done:%llu|g%s\n" - METRIC_PREFIX".cycles_wo_finds:%llu|g%s\n" - METRIC_PREFIX".execs_done:%llu|g%s\n" - METRIC_PREFIX".execs_per_sec:%0.02f|g%s\n" - METRIC_PREFIX".paths_total:%u|g%s\n" - METRIC_PREFIX".paths_favored:%u|g%s\n" - METRIC_PREFIX".paths_found:%u|g%s\n" - METRIC_PREFIX".paths_imported:%u|g%s\n" - METRIC_PREFIX".max_depth:%u|g%s\n" - METRIC_PREFIX".cur_path:%u|g%s\n" - METRIC_PREFIX".pending_favs:%u|g%s\n" - METRIC_PREFIX".pending_total:%u|g%s\n" - METRIC_PREFIX".variable_paths:%u|g%s\n" - METRIC_PREFIX".unique_crashes:%llu|g%s\n" - METRIC_PREFIX".unique_hangs:%llu|g%s\n" - METRIC_PREFIX".total_crashes:%llu|g%s\n" - METRIC_PREFIX".slowest_exec_ms:%u|g%s\n" - METRIC_PREFIX".edges_found:%u|g%s\n" - METRIC_PREFIX".var_byte_count:%u|g%s\n" - METRIC_PREFIX".havoc_expansion:%u|g%s\n", - afl->queue_cycle ? (afl->queue_cycle - 1) : 0, tags, - afl->cycles_wo_finds, tags, - afl->fsrv.total_execs, tags, - afl->fsrv.total_execs / ((double)(get_cur_time() - afl->start_time) / 1000), tags, - afl->queued_paths, tags, - afl->queued_favored, tags, - afl->queued_discovered, tags, - afl->queued_imported, tags, - afl->max_depth, tags, - afl->current_entry, tags, - afl->pending_favored, tags, - afl->pending_not_fuzzed, tags, - afl->queued_variable, tags, - afl->unique_crashes, tags, - afl->unique_hangs, tags, - afl->total_crashes, tags, - afl->slowest_exec_ms, tags, - count_non_255_bytes(afl, afl->virgin_bits), tags, - afl->var_byte_count, tags, - afl->expand_havoc, tags - ); - - return 0; -} \ No newline at end of file -- cgit 1.4.1 From fd4efd04a1d55b070934e5307b8dd8f81aa8e8ac Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 5 Oct 2020 23:07:22 +0200 Subject: fixed gcc 10 warning --- src/afl-fuzz-stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 1d5b169d..654d9059 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -955,7 +955,7 @@ void show_stats(afl_state_t *afl) { #else SAYF("%s" cGRA " [cpu:%s%3u%%" cGRA "]\r" cRST, spacing, cpu_color, - MIN(cur_utilization, 999)); + MIN(cur_utilization, (u32)999)); #endif /* ^HAVE_AFFINITY */ -- cgit 1.4.1 From 0220a8ff6670da2b9fd8cb883528d2a86f683c74 Mon Sep 17 00:00:00 2001 From: Edznux Date: Thu, 8 Oct 2020 20:48:46 +0200 Subject: Add env var toggle for StatsD --- include/afl-fuzz.h | 2 +- include/config.h | 7 +++---- include/envs.h | 1 + src/afl-fuzz-state.c | 7 +++++++ src/afl-fuzz-stats.c | 15 ++++++++------- src/afl-fuzz.c | 8 +++----- 6 files changed, 23 insertions(+), 17 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index df7dd644..8ad0ced1 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -355,7 +355,7 @@ typedef struct afl_env_vars { afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui, afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one, afl_bench_until_crash, afl_debug_child_output, afl_autoresume, - afl_cal_fast, afl_cycle_schedules, afl_expand_havoc; + afl_cal_fast, afl_cycle_schedules, afl_expand_havoc, afl_statsd; u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, diff --git a/include/config.h b/include/config.h index 3d6b0395..405c2712 100644 --- a/include/config.h +++ b/include/config.h @@ -41,11 +41,10 @@ #define USE_COLOR -/* Enable sending statistics over a StatsD daemon. -Server config can be adjusted with AFL_STATSD_HOST and AFL_STATSD_PORT env var. +/* StatsD config + Config can be adjusted via AFL_STATSD_HOST and AFL_STATSD_PORT environment + variable. */ - -#define USE_STATSD #define STATSD_UPDATE_SEC 1 #define STATSD_DEFAULT_PORT 8125 #define STATSD_DEFAULT_HOST "127.0.0.1" diff --git a/include/envs.h b/include/envs.h index 16da14cb..51520312 100644 --- a/include/envs.h +++ b/include/envs.h @@ -135,6 +135,7 @@ static char *afl_environment_variables[] = { "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES", + "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 77b30b5b..a7c7aff9 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -316,6 +316,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_cal_fast = get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_STATSD", + + afl_environment_variable_len)) { + + afl->afl_env.afl_statsd = + get_afl_env(afl_environment_variables[i]) ? 1 : 0; + } else if (!strncmp(env, "AFL_TMPDIR", afl_environment_variable_len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 942670b4..0d6c6a66 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -423,16 +423,17 @@ void show_stats(afl_state_t *afl) { } -#ifdef USE_STATSD - if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) { + if (unlikely(afl->afl_env.afl_statsd == 1)) { - /* reset counter, even if send failed. */ - afl->statsd_last_send_ms = cur_ms; - if (statsd_send_metric(afl)) { WARNF("coundln't send statsd metric."); } + if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) { - } + /* reset counter, even if send failed. */ + afl->statsd_last_send_ms = cur_ms; + if (statsd_send_metric(afl)) { WARNF("coundln't send statsd metric."); } -#endif + } + + } /* Every now and then, write plot data. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c26e53b9..2c2f0ba5 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -194,7 +194,8 @@ static void usage(u8 *argv0, int more_help) { "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" - "AFL_STATSD_HOST: change default statsd host. (default 127.0.0.1)" + "AFL_STATSD: enables StatsD metrics collection" + "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)" "AFL_STATSD_PORT: change default statsd port (default: 8125)" "AFL_STATSD_TAGS_FLAVOR: change default statsd tags format (default will disable tags)." " Supported formats are: 'dogstatsd', 'librato', 'signalfx' and 'influxdb'" @@ -893,10 +894,7 @@ int main(int argc, char **argv_orig, char **envp) { } - #ifdef USE_STATSD - statsd_setup_format(afl); - - #endif + if (unlikely(afl->afl_env.afl_statsd == 1)) { statsd_setup_format(afl); } if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { -- cgit 1.4.1 From 4cb4772e2af9511c2320de833a81bc43500cef14 Mon Sep 17 00:00:00 2001 From: Edznux Date: Fri, 9 Oct 2020 18:58:27 +0200 Subject: Remove ==1 in the condition --- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 0d6c6a66..8a1c2cc6 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -423,7 +423,7 @@ void show_stats(afl_state_t *afl) { } - if (unlikely(afl->afl_env.afl_statsd == 1)) { + if (unlikely(afl->afl_env.afl_statsd)) { if (cur_ms - afl->statsd_last_send_ms > STATSD_UPDATE_SEC * 1000) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 2c2f0ba5..aa36a6c6 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -894,7 +894,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (unlikely(afl->afl_env.afl_statsd == 1)) { statsd_setup_format(afl); } + if (unlikely(afl->afl_env.afl_statsd)) { statsd_setup_format(afl); } if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { -- cgit 1.4.1 From 5dc3bc175b664f0921ebd1265d4419d611aa4a74 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 10 Oct 2020 10:41:30 +0200 Subject: fix typo --- docs/Changelog.md | 1 + src/afl-fuzz-stats.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/docs/Changelog.md b/docs/Changelog.md index ba7028df..aa55fbde 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -15,6 +15,7 @@ sending a mail to . - afl-llvm/gcc-rt.o merged into afl-compiler-rt.o - afl-fuzz - memory limits are now disabled by default, set them with -m if required + - statsd support by Edznux, thanks a lot! - Marcel Boehme submitted a patch that improves all AFFast schedules :) - reading testcases from -i now descends into subdirectories - allow up to 4 -x command line options diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 0cd6f399..76f24977 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -429,7 +429,7 @@ void show_stats(afl_state_t *afl) { /* reset counter, even if send failed. */ afl->statsd_last_send_ms = cur_ms; - if (statsd_send_metric(afl)) { WARNF("coundln't send statsd metric."); } + if (statsd_send_metric(afl)) { WARNF("could not send statsd metric."); } } -- cgit 1.4.1 From 56ac3fcdc511d124ad058412021ead21bbbcf4bf Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 14 Oct 2020 15:30:30 +0200 Subject: configurable testcache with malloc (#581) * cache item number to cache memory size * reload testcase if trimming changed the size * fix splicing selection * slim splicing * import sync fix * write testcache stats to fuzzer_stats * fix new seed selection algo * malloc+read instead of mmap * fix * testcache is configurable now and no reference counts * fixes compilation, test script * fixes * switch TEST_CC to afl-cc in makefile * code format * fix * fix crash * fix crash * fix env help output * remove unnecessary pointer resets * fix endless loop bug * actually use the cache if set * one more fix * increase default cache entries, add default cache size value to config.h Co-authored-by: hexcoder- --- GNUmakefile | 4 +- include/afl-fuzz.h | 31 +++++++- include/config.h | 9 +++ include/envs.h | 1 + src/afl-fuzz-init.c | 4 +- src/afl-fuzz-one.c | 169 +++++++++---------------------------------- src/afl-fuzz-queue.c | 167 ++++++++++++++++++++++++++++++++++++++---- src/afl-fuzz-run.c | 6 ++ src/afl-fuzz-state.c | 8 ++ src/afl-fuzz-stats.c | 7 +- src/afl-fuzz.c | 29 ++++++-- src/afl-performance.c | 2 +- test/test-custom-mutators.sh | 2 +- 13 files changed, 276 insertions(+), 163 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/GNUmakefile b/GNUmakefile index c885a935..80b7b68b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -223,8 +223,6 @@ ifneq "$(findstring OpenBSD, $(shell uname))" "" LDFLAGS += -lpthread endif -TEST_CC = afl-gcc - COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h ifeq "$(shell echo '$(HASH)include @int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" @@ -488,7 +486,7 @@ code-format: ifndef AFL_NO_X86 test_build: afl-cc afl-as afl-showmap @echo "[*] Testing the CC wrapper and instrumentation output..." - @unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 ) + @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 || (echo "Oops, afl-cc failed"; exit 1 ) ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr @rm -f test-instr diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 85597150..940c5602 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -168,6 +168,8 @@ struct queue_entry { double perf_score; /* performance score */ + u8 *testcase_buf; /* The testcase buffer, if loaded. */ + struct queue_entry *next; /* Next element, if any */ }; @@ -363,7 +365,7 @@ typedef struct afl_env_vars { u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, - *afl_statsd_tags_flavor; + *afl_statsd_tags_flavor, *afl_testcache_size; } afl_env_vars_t; @@ -675,6 +677,9 @@ typedef struct afl_state { u8 *in_scratch_buf; u8 *ex_buf; + + u8 *testcase_buf, *splicecase_buf; + u32 custom_mutators_count; list_t custom_mutator_list; @@ -686,6 +691,22 @@ typedef struct afl_state { /* queue entries ready for splicing count (len > 4) */ u32 ready_for_splicing_count; + /* This is the user specified maximum size to use for the testcase cache */ + u64 q_testcase_max_cache_size; + + /* How much of the testcase cache is used so far */ + u64 q_testcase_cache_size; + + /* highest cache count so far */ + u32 q_testcase_max_cache_count; + + /* How many queue entries currently have cached testcases */ + u32 q_testcase_cache_count; + + /* Refs to each queue entry with cached testcase (for eviction, if cache_count + * is too large) */ + struct queue_entry *q_testcase_cache[TESTCASE_ENTRIES]; + } afl_state_t; struct custom_mutator { @@ -1135,5 +1156,13 @@ static inline u64 next_p2(u64 val) { } +/* Returns the testcase buf from the file behind this queue entry. + Increases the refcount. */ +u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q); + +/* If trimming changes the testcase size we have to reload it */ +void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q, + u32 old_len); + #endif diff --git a/include/config.h b/include/config.h index 7dd045e3..b4f3a775 100644 --- a/include/config.h +++ b/include/config.h @@ -295,6 +295,15 @@ #define RESEED_RNG 100000 +/* The maximum number of testcases to cache */ + +#define TESTCASE_ENTRIES 16384 + +/* The default maximum testcase cache size in MB, 0 = disable. + A value between 50 and 250 is a good default value. */ + +#define TESTCASE_CACHE 0 + /* Maximum line length passed from GCC to 'as' and used for parsing configuration files: */ diff --git a/include/envs.h b/include/envs.h index 51520312..a1b3ad12 100644 --- a/include/envs.h +++ b/include/envs.h @@ -139,6 +139,7 @@ static char *afl_environment_variables[] = { "AFL_STATSD_HOST", "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", + "AFL_TESTCACHE_SIZE", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 881bf10f..607b652f 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1045,7 +1045,7 @@ restart_outer_cull_loop: while (q) { - if (q->cal_failed || !q->exec_cksum) continue; + if (q->cal_failed || !q->exec_cksum) { goto next_entry; } restart_inner_cull_loop: @@ -1090,6 +1090,8 @@ restart_outer_cull_loop: } + next_entry: + prev = q; q = q->next; diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index fc092f8d..154e4b45 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -370,7 +370,7 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) { u8 fuzz_one_original(afl_state_t *afl) { - s32 len, fd, temp_len; + s32 len, temp_len; u32 j; u32 i; u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; @@ -453,32 +453,9 @@ u8 fuzz_one_original(afl_state_t *afl) { } - /* Map the test case into memory. */ - - fd = open(afl->queue_cur->fname, O_RDONLY); - - if (unlikely(fd < 0)) { - - PFATAL("Unable to open '%s'", afl->queue_cur->fname); - - } - + orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); len = afl->queue_cur->len; - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (unlikely(orig_in == MAP_FAILED)) { - - PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); - - } - - close(fd); - - /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every - single byte anyway, so it wouldn't give us any performance or memory usage - benefits. */ - out_buf = afl_realloc(AFL_BUF_PARAM(out), len); if (unlikely(!out_buf)) { PFATAL("alloc"); } @@ -526,6 +503,7 @@ u8 fuzz_one_original(afl_state_t *afl) { !afl->disable_trim)) { u8 res = trim_case(afl, afl->queue_cur, in_buf); + orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); if (unlikely(res == FSRV_RUN_ERROR)) { @@ -1720,17 +1698,7 @@ custom_mutator_stage: afl->splicing_with = tid; /* Read the additional testcase into a new buffer. */ - fd = open(target->fname, O_RDONLY); - if (unlikely(fd < 0)) { - - PFATAL("Unable to open '%s'", target->fname); - - } - - new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), target->len); - if (unlikely(!new_buf)) { PFATAL("alloc"); } - ck_read(fd, new_buf, target->len, target->fname); - close(fd); + new_buf = queue_testcase_get(afl, target); target_len = target->len; } @@ -2182,7 +2150,6 @@ havoc_stage: afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch)); out_buf = new_buf; - new_buf = NULL; temp_len += clone_len; } @@ -2326,43 +2293,21 @@ havoc_stage: /* Pick a random queue entry and seek to it. */ u32 tid; - do - tid = rand_below(afl, afl->queued_paths); - while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); - - struct queue_entry *target = afl->queue_buf[tid]; - - /* Read the testcase into a new buffer. */ - - fd = open(target->fname, O_RDONLY); - - if (unlikely(fd < 0)) { - - PFATAL("Unable to open '%s'", target->fname); - - } - - u32 new_len = target->len; - u8 *new_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), new_len); - if (unlikely(!new_buf)) { PFATAL("alloc"); } - - ck_read(fd, new_buf, new_len, target->fname); + do { - close(fd); + tid = rand_below(afl, afl->queued_paths); - u8 overwrite = 0; - if (temp_len >= 2 && rand_below(afl, 2)) - overwrite = 1; - else if (temp_len + HAVOC_BLK_XL >= MAX_FILE) { + } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); - if (temp_len >= 2) - overwrite = 1; - else - break; + /* Get the testcase for splicing. */ + struct queue_entry *target = afl->queue_buf[tid]; + u32 new_len = target->len; + u8 * new_buf = queue_testcase_get(afl, target); - } + if ((temp_len >= 2 && rand_below(afl, 2)) || + temp_len + HAVOC_BLK_XL >= MAX_FILE) { - if (overwrite) { + /* overwrite mode */ u32 copy_from, copy_to, copy_len; @@ -2376,15 +2321,16 @@ havoc_stage: } else { + /* insert mode */ + u32 clone_from, clone_to, clone_len; clone_len = choose_block_len(afl, new_len); clone_from = rand_below(afl, new_len - clone_len + 1); + clone_to = rand_below(afl, temp_len + 1); - clone_to = rand_below(afl, temp_len); - - u8 *temp_buf = - afl_realloc(AFL_BUF_PARAM(out_scratch), temp_len + clone_len); + u8 *temp_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), + temp_len + clone_len + 1); if (unlikely(!temp_buf)) { PFATAL("alloc"); } /* Head */ @@ -2496,21 +2442,10 @@ retry_splicing: } while (tid == afl->current_entry || afl->queue_buf[tid]->len < 4); + /* Get the testcase */ afl->splicing_with = tid; target = afl->queue_buf[tid]; - - /* Read the testcase into a new buffer. */ - - fd = open(target->fname, O_RDONLY); - - if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); } - - new_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), target->len); - if (unlikely(!new_buf)) { PFATAL("alloc"); } - - ck_read(fd, new_buf, target->len, target->fname); - - close(fd); + new_buf = queue_testcase_get(afl, target); /* Find a suitable splicing location, somewhere between the first and the last differing byte. Bail out if the difference is just a single @@ -2527,18 +2462,16 @@ retry_splicing: /* Do the thing. */ len = target->len; - memcpy(new_buf, in_buf, split_at); - afl_swap_bufs(AFL_BUF_PARAM(in), AFL_BUF_PARAM(in_scratch)); - in_buf = new_buf; + afl->in_scratch_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), len); + memcpy(afl->in_scratch_buf, in_buf, split_at); + memcpy(afl->in_scratch_buf + split_at, new_buf, len - split_at); + in_buf = afl->in_scratch_buf; out_buf = afl_realloc(AFL_BUF_PARAM(out), len); if (unlikely(!out_buf)) { PFATAL("alloc"); } memcpy(out_buf, in_buf, len); goto custom_mutator_stage; - /* ???: While integrating Python module, the author decided to jump to - python stage, but the reason behind this is not clear.*/ - // goto havoc_stage; } @@ -2564,9 +2497,7 @@ abandon_entry: } ++afl->queue_cur->fuzz_level; - - munmap(orig_in, afl->queue_cur->len); - + orig_in = NULL; return ret_val; #undef FLIP_BIT @@ -2587,7 +2518,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { } - s32 len, fd, temp_len; + s32 len, temp_len; u32 i; u32 j; u8 *in_buf, *out_buf, *orig_in, *ex_tmp, *eff_map = 0; @@ -2652,32 +2583,11 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { } /* Map the test case into memory. */ - - fd = open(afl->queue_cur->fname, O_RDONLY); - - if (fd < 0) { PFATAL("Unable to open '%s'", afl->queue_cur->fname); } - + orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); len = afl->queue_cur->len; - - orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - - if (orig_in == MAP_FAILED) { - - PFATAL("Unable to mmap '%s'", afl->queue_cur->fname); - - } - - close(fd); - - /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every - single byte anyway, so it wouldn't give us any performance or memory usage - benefits. */ - out_buf = afl_realloc(AFL_BUF_PARAM(out), len); if (unlikely(!out_buf)) { PFATAL("alloc"); } - afl->subseq_tmouts = 0; - afl->cur_depth = afl->queue_cur->depth; /******************************************* @@ -2721,6 +2631,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u32 old_len = afl->queue_cur->len; u8 res = trim_case(afl, afl->queue_cur, in_buf); + orig_in = in_buf = queue_testcase_get(afl, afl->queue_cur); if (res == FSRV_RUN_ERROR) { @@ -4497,17 +4408,7 @@ pacemaker_fuzzing: target = afl->queue_buf[tid]; /* Read the testcase into a new buffer. */ - - fd = open(target->fname, O_RDONLY); - - if (fd < 0) { PFATAL("Unable to open '%s'", target->fname); } - - new_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), target->len); - if (unlikely(!new_buf)) { PFATAL("alloc"); } - - ck_read(fd, new_buf, target->len, target->fname); - - close(fd); + new_buf = queue_testcase_get(afl, target); /* Find a suitable splicin g location, somewhere between the first and the last differing byte. Bail out if the difference is just a single @@ -4529,9 +4430,11 @@ pacemaker_fuzzing: /* Do the thing. */ len = target->len; - memcpy(new_buf, in_buf, split_at); - afl_swap_bufs(AFL_BUF_PARAM(in), AFL_BUF_PARAM(in_scratch)); - in_buf = new_buf; + afl->in_scratch_buf = afl_realloc(AFL_BUF_PARAM(in_scratch), len); + memcpy(afl->in_scratch_buf, in_buf, split_at); + memcpy(afl->in_scratch_buf + split_at, new_buf, len - split_at); + in_buf = afl->in_scratch_buf; + out_buf = afl_realloc(AFL_BUF_PARAM(out), len); if (unlikely(!out_buf)) { PFATAL("alloc"); } memcpy(out_buf, in_buf, len); @@ -4569,7 +4472,7 @@ pacemaker_fuzzing: // if (afl->queue_cur->favored) --afl->pending_favored; // } - munmap(orig_in, afl->queue_cur->len); + orig_in = NULL; if (afl->key_puppet == 1) { diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f224d851..c634328f 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -31,11 +31,12 @@ inline u32 select_next_queue_entry(afl_state_t *afl) { - u32 s = rand_below(afl, afl->queued_paths); + u32 s = rand_below(afl, afl->queued_paths); double p = rand_next_percent(afl); /* fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u" - " ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p < afl->alias_probability[s] ? s : afl->alias_table[s]); + " ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p < + afl->alias_probability[s] ? s : afl->alias_table[s]); */ return (p < afl->alias_probability[s] ? s : afl->alias_table[s]); @@ -55,7 +56,7 @@ void create_alias_table(afl_state_t *afl) { int * S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32)); int * L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32)); - if (!P || !S || !L) FATAL("could not aquire memory for alias table"); + if (!P || !S || !L) { FATAL("could not aquire memory for alias table"); } memset((void *)afl->alias_table, 0, n * sizeof(u32)); memset((void *)afl->alias_probability, 0, n * sizeof(double)); @@ -65,7 +66,7 @@ void create_alias_table(afl_state_t *afl) { struct queue_entry *q = afl->queue_buf[i]; - if (!q->disabled) q->perf_score = calculate_score(afl, q); + if (!q->disabled) { q->perf_score = calculate_score(afl, q); } sum += q->perf_score; @@ -74,19 +75,23 @@ void create_alias_table(afl_state_t *afl) { for (i = 0; i < n; i++) { struct queue_entry *q = afl->queue_buf[i]; - - P[i] = q->perf_score * n / sum; + P[i] = (q->perf_score * n) / sum; } int nS = 0, nL = 0, s; for (s = (s32)n - 1; s >= 0; --s) { - if (P[s] < 1) + if (P[s] < 1) { + S[nS++] = s; - else + + } else { + L[nL++] = s; + } + } while (nS && nL) { @@ -96,11 +101,16 @@ void create_alias_table(afl_state_t *afl) { afl->alias_probability[a] = P[a]; afl->alias_table[a] = g; P[g] = P[g] + P[a] - 1; - if (P[g] < 1) + if (P[g] < 1) { + S[nS++] = g; - else + + } else { + L[nL++] = g; + } + } while (nL) @@ -110,11 +120,10 @@ void create_alias_table(afl_state_t *afl) { afl->alias_probability[S[--nS]] = 1; /* - fprintf(stderr, " %-3s %-3s %-9s %-9s\n", "entry", "alias", "prob", "perf"); - for (u32 i = 0; i < n; ++i) - fprintf(stderr, " %3i %3i %9.7f %9.7f\n", i, afl->alias_table[i], - afl->alias_probability[i], afl->queue_buf[i]->perf_score); - + fprintf(stderr, " entry alias probability perf_score\n"); + for (u32 i = 0; i < n; ++i) + fprintf(stderr, " %5u %5u %11u %0.9f\n", i, afl->alias_table[i], + afl->alias_probability[i], afl->queue_buf[i]->perf_score); */ } @@ -860,3 +869,131 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { } +void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q, + u32 old_len) { + + if (likely(q->testcase_buf)) { + + free(q->testcase_buf); + int fd = open(q->fname, O_RDONLY); + + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); } + + u32 len = q->len; + q->testcase_buf = malloc(len); + + if (unlikely(!q->testcase_buf)) { + + PFATAL("Unable to mmap '%s' with len %d", q->fname, len); + + } + + close(fd); + afl->q_testcase_cache_size = afl->q_testcase_cache_size + q->len - old_len; + + } + +} + +/* Returns the testcase buf from the file behind this queue entry. + Increases the refcount. */ +inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { + + u32 len = q->len; + + /* first handle if no testcase cache is configured */ + + if (unlikely(!afl->q_testcase_max_cache_size)) { + + u8 *buf; + + if (q == afl->queue_cur) { + + buf = afl_realloc((void **)&afl->testcase_buf, len); + + } else { + + buf = afl_realloc((void **)&afl->splicecase_buf, len); + + } + + if (unlikely(!buf)) { + + PFATAL("Unable to malloc '%s' with len %u", q->fname, len); + + } + + int fd = open(q->fname, O_RDONLY); + + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); } + + ck_read(fd, buf, len, q->fname); + close(fd); + return buf; + + } + + /* now handle the testcase cache */ + + if (unlikely(!q->testcase_buf)) { + + /* Buf not cached, let's load it */ + u32 tid = 0; + + while (unlikely(afl->q_testcase_cache_size + len >= + afl->q_testcase_max_cache_size || + afl->q_testcase_cache_count >= TESTCASE_ENTRIES - 1)) { + + /* Cache full. We neet to evict one to map one. + Get a random one which is not in use */ + + do { + + tid = rand_below(afl, afl->q_testcase_max_cache_count); + + } while (afl->q_testcase_cache[tid] == NULL || + + afl->q_testcase_cache[tid] == afl->queue_cur); + + struct queue_entry *old_cached = afl->q_testcase_cache[tid]; + free(old_cached->testcase_buf); + old_cached->testcase_buf = NULL; + afl->q_testcase_cache_size -= old_cached->len; + afl->q_testcase_cache[tid] = NULL; + --afl->q_testcase_cache_count; + + } + + while (likely(afl->q_testcase_cache[tid] != NULL)) + ++tid; + + /* Map the test case into memory. */ + + int fd = open(q->fname, O_RDONLY); + + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); } + + q->testcase_buf = malloc(len); + + if (unlikely(!q->testcase_buf)) { + + PFATAL("Unable to malloc '%s' with len %u", q->fname, len); + + } + + ck_read(fd, q->testcase_buf, len, q->fname); + close(fd); + + /* Register testcase as cached */ + afl->q_testcase_cache[tid] = q; + afl->q_testcase_cache_size += q->len; + ++afl->q_testcase_cache_count; + if (tid >= afl->q_testcase_max_cache_count) + afl->q_testcase_max_cache_count = tid + 1; + + } + + return q->testcase_buf; + +} + diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index ee22b0f6..ab870319 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -692,6 +692,8 @@ void sync_fuzzers(afl_state_t *afl) { u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { + u32 orig_len = q->len; + /* Custom mutator trimmer */ if (afl->custom_mutators_count) { @@ -709,6 +711,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { }); + if (orig_len != q->len) { queue_testcase_retake(afl, q, orig_len); } + if (custom_trimmed) return trimmed_case; } @@ -842,6 +846,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { close(fd); + if (orig_len != q->len) queue_testcase_retake(afl, q, orig_len); + memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size); update_bitmap_score(afl, q); diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index a0a2795e..0824b77f 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -103,6 +103,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_avg_exec = -1; afl->skip_deterministic = 1; afl->use_splicing = 1; + afl->q_testcase_max_cache_size = TESTCASE_CACHE * 1024000; #ifdef HAVE_AFFINITY afl->cpu_aff = -1; /* Selected CPU core */ @@ -353,6 +354,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_forksrv_init_tmout = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_TESTCACHE_SIZE", + + afl_environment_variable_len)) { + + afl->afl_env.afl_testcache_size = + (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_STATSD_HOST", afl_environment_variable_len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 76f24977..4f0cab4c 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -165,6 +165,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "edges_found : %u\n" "var_byte_count : %u\n" "havoc_expansion : %u\n" + "testcache_size : %llu\n" + "testcache_count : %u\n" "afl_banner : %s\n" "afl_version : " VERSION "\n" @@ -198,8 +200,9 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, #else -1, #endif - t_bytes, afl->var_byte_count, afl->expand_havoc, afl->use_banner, - afl->unicorn_mode ? "unicorn" : "", + t_bytes, afl->var_byte_count, afl->expand_havoc, + afl->q_testcase_cache_size, afl->q_testcase_cache_count, + afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->non_instrumented_mode ? " non_instrumented " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 6498eb30..a59abb7d 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -196,11 +196,13 @@ static void usage(u8 *argv0, int more_help) { "AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n" "AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n" "AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n" - "AFL_STATSD: enables StatsD metrics collection" - "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)" - "AFL_STATSD_PORT: change default statsd port (default: 8125)" - "AFL_STATSD_TAGS_FLAVOR: change default statsd tags format (default will disable tags)." - " Supported formats are: 'dogstatsd', 'librato', 'signalfx' and 'influxdb'" + "AFL_STATSD: enables StatsD metrics collection\n" + "AFL_STATSD_HOST: change default statsd host (default 127.0.0.1)\n" + "AFL_STATSD_PORT: change default statsd port (default: 8125)\n" + "AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n" + " Supported formats are: 'dogstatsd', 'librato', 'signalfx'\n" + " and 'influxdb'\n" + "AFL_TESTCACHE_SIZE: use a cache for testcases, improves performance (in MB)\n" "AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n" //"AFL_PERSISTENT: not supported anymore -> no effect, just a warning\n" //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n" @@ -885,7 +887,7 @@ int main(int argc, char **argv_orig, char **envp) { auto_sync = 1; afl->sync_id = ck_strdup("default"); afl->is_secondary_node = 1; - OKF("no -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id); + OKF("No -M/-S set, autoconfiguring for \"-S %s\"", afl->sync_id); } @@ -1006,6 +1008,21 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->afl_env.afl_testcache_size) { + + afl->q_testcase_max_cache_size = + (u64)atoi(afl->afl_env.afl_testcache_size) * 1024000; + OKF("Enabled testcache with %llu MB", + afl->q_testcase_max_cache_size / 1024000); + + } else { + + ACTF( + "No testcache was configured. it is recommended to use a testcache, it " + "improves performance: set AFL_TESTCACHE_SIZE=(value in MB)"); + + } + if (afl->afl_env.afl_forksrv_init_tmout) { afl->fsrv.init_tmout = atoi(afl->afl_env.afl_forksrv_init_tmout); diff --git a/src/afl-performance.c b/src/afl-performance.c index 6fa95dea..e070a05e 100644 --- a/src/afl-performance.c +++ b/src/afl-performance.c @@ -71,7 +71,7 @@ inline uint64_t rand_next(afl_state_t *afl) { inline double rand_next_percent(afl_state_t *afl) { - return (double)(((double)rand_next(afl)) / (double) 0xffffffffffffffff); + return (double)(((double)rand_next(afl)) / (double)0xffffffffffffffff); } diff --git a/test/test-custom-mutators.sh b/test/test-custom-mutators.sh index f7677ac5..d4d21048 100755 --- a/test/test-custom-mutators.sh +++ b/test/test-custom-mutators.sh @@ -1,4 +1,4 @@ -f#!/bin/sh +#!/bin/sh . ./test-pre.sh -- cgit 1.4.1 From fcea01a8ea7ec507b675d839035eb0fed2f06867 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 17 Oct 2020 11:38:55 +0200 Subject: add eviction stat --- include/afl-fuzz.h | 3 +++ src/afl-fuzz-queue.c | 1 + src/afl-fuzz-stats.c | 4 +++- 3 files changed, 7 insertions(+), 1 deletion(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index e94f389a..880b8d50 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -704,6 +704,9 @@ typedef struct afl_state { /* How many queue entries currently have cached testcases */ u32 q_testcase_cache_count; + /* How often did we evict from the cache */ + u32 q_testcase_evictions; + /* Refs to each queue entry with cached testcase (for eviction, if cache_count * is too large) */ struct queue_entry *q_testcase_cache[TESTCASE_ENTRIES]; diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index f8034ebd..e0df7206 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -996,6 +996,7 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { afl->q_testcase_cache_size -= old_cached->len; afl->q_testcase_cache[tid] = NULL; --afl->q_testcase_cache_count; + ++afl->q_testcase_evictions; } diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 4f0cab4c..d213d054 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -167,6 +167,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, "havoc_expansion : %u\n" "testcache_size : %llu\n" "testcache_count : %u\n" + "testcache_evict : %u\n" "afl_banner : %s\n" "afl_version : " VERSION "\n" @@ -202,7 +203,8 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, #endif t_bytes, afl->var_byte_count, afl->expand_havoc, afl->q_testcase_cache_size, afl->q_testcase_cache_count, - afl->use_banner, afl->unicorn_mode ? "unicorn" : "", + afl->q_testcase_evictions, afl->use_banner, + afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", afl->non_instrumented_mode ? " non_instrumented " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", -- cgit 1.4.1 From 0e748ccda713708de6a501d23a58788aba9d0b03 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 23 Oct 2020 14:05:34 +0200 Subject: set max testcache entries automated if not specified by the user --- include/afl-fuzz.h | 7 ++++-- include/config.h | 10 ++++---- include/envs.h | 1 + src/afl-fuzz-queue.c | 11 +++++---- src/afl-fuzz-state.c | 10 +++++++- src/afl-fuzz-stats.c | 2 +- src/afl-fuzz.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++--- 7 files changed, 91 insertions(+), 18 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 220380b9..11feb9f7 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -366,7 +366,7 @@ typedef struct afl_env_vars { u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path, *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload, *afl_max_det_extras, *afl_statsd_host, *afl_statsd_port, - *afl_statsd_tags_flavor, *afl_testcache_size; + *afl_statsd_tags_flavor, *afl_testcache_size, *afl_testcache_entries; } afl_env_vars_t; @@ -695,6 +695,9 @@ typedef struct afl_state { /* This is the user specified maximum size to use for the testcase cache */ u64 q_testcase_max_cache_size; + /* This is the user specified maximum entries in the testcase cache */ + u32 q_testcase_max_cache_entries; + /* How much of the testcase cache is used so far */ u64 q_testcase_cache_size; @@ -712,7 +715,7 @@ typedef struct afl_state { /* Refs to each queue entry with cached testcase (for eviction, if cache_count * is too large) */ - struct queue_entry *q_testcase_cache[TESTCASE_ENTRIES]; + struct queue_entry **q_testcase_cache; } afl_state_t; diff --git a/include/config.h b/include/config.h index b4f3a775..491d8132 100644 --- a/include/config.h +++ b/include/config.h @@ -295,14 +295,12 @@ #define RESEED_RNG 100000 -/* The maximum number of testcases to cache */ - -#define TESTCASE_ENTRIES 16384 - /* The default maximum testcase cache size in MB, 0 = disable. - A value between 50 and 250 is a good default value. */ + A value between 50 and 250 is a good default value. Note that the + number of entries will be auto assigned if not specified via the + AFL_TESTCACHE_ENTRIES env variable */ -#define TESTCASE_CACHE 0 +#define TESTCASE_CACHE_SIZE 50 /* Maximum line length passed from GCC to 'as' and used for parsing configuration files: */ diff --git a/include/envs.h b/include/envs.h index a1b3ad12..b753d5f8 100644 --- a/include/envs.h +++ b/include/envs.h @@ -140,6 +140,7 @@ static char *afl_environment_variables[] = { "AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_TESTCACHE_SIZE", + "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE", diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index db387c33..baa80e61 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -978,9 +978,9 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { /* Buf not cached, let's load it */ u32 tid = afl->q_testcase_max_cache_count; - while (unlikely(afl->q_testcase_cache_size + len >= - afl->q_testcase_max_cache_size || - afl->q_testcase_cache_count >= TESTCASE_ENTRIES - 1)) { + while (unlikely( + afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size || + afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) { /* Cache full. We neet to evict one or more to map one. Get a random one which is not in use */ @@ -1009,7 +1009,7 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) { } - if (unlikely(tid >= TESTCASE_ENTRIES)) { + if (unlikely(tid >= afl->q_testcase_max_cache_entries)) { // uh we were full, so now we have to search from start tid = afl->q_testcase_smallest_free; @@ -1062,7 +1062,8 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, if (unlikely(afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size || - afl->q_testcase_cache_count >= TESTCASE_ENTRIES - 1)) { + afl->q_testcase_cache_count >= + afl->q_testcase_max_cache_entries - 1)) { // no space? will be loaded regularly later. return; diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 0824b77f..ae7d410b 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -103,7 +103,8 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->stats_avg_exec = -1; afl->skip_deterministic = 1; afl->use_splicing = 1; - afl->q_testcase_max_cache_size = TESTCASE_CACHE * 1024000; + afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL; + afl->q_testcase_max_cache_entries = 4096; #ifdef HAVE_AFFINITY afl->cpu_aff = -1; /* Selected CPU core */ @@ -361,6 +362,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) { afl->afl_env.afl_testcache_size = (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_TESTCACHE_ENTRIES", + + afl_environment_variable_len)) { + + afl->afl_env.afl_testcache_entries = + (u8 *)get_afl_env(afl_environment_variables[i]); + } else if (!strncmp(env, "AFL_STATSD_HOST", afl_environment_variable_len)) { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index d213d054..bec90519 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1028,7 +1028,7 @@ void show_init_stats(afl_state_t *afl) { } - SAYF("\n"); + // SAYF("\n"); if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) { diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 7215ecec..637e1985 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -251,7 +251,7 @@ static int stricmp(char const *a, char const *b) { int main(int argc, char **argv_orig, char **envp) { - s32 opt, i, auto_sync = 0; + s32 opt, i, auto_sync = 0, user_set_cache = 0; u64 prev_queued = 0; u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, map_size = MAP_SIZE; u8 *extras_dir[4]; @@ -1015,6 +1015,22 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->afl_env.afl_testcache_entries) { + + afl->q_testcase_max_cache_entries = + (u32)atoi(afl->afl_env.afl_testcache_entries); + + user_set_cache = 1; + + } + + if (!afl->afl_env.afl_testcache_size || !afl->afl_env.afl_testcache_entries) { + + afl->afl_env.afl_testcache_entries = 0; + afl->afl_env.afl_testcache_size = 0; + + } + if (!afl->q_testcase_max_cache_size) { ACTF( @@ -1347,6 +1363,52 @@ int main(int argc, char **argv_orig, char **envp) { perform_dry_run(afl); + if (!user_set_cache && afl->q_testcase_max_cache_size) { + + /* The user defined not a fixed number of entries for the cache. + Hence we autodetect a good value. After the dry run inputs are + trimmed and we know the average and max size of the input seeds. + We use this information to set a fitting size to max entries + based on the cache size. */ + + struct queue_entry *q = afl->queue; + u64 size = 0, count = 0, avg = 0, max = 0; + + while (q) { + + ++count; + size += q->len; + if (max < q->len) { max = q->len; } + q = q->next; + + } + + if (count) { + + avg = size / count; + avg = ((avg + max) / 2) + 1; + + } + + if (avg < 10240) { avg = 10240; } + + afl->q_testcase_max_cache_entries = afl->q_testcase_max_cache_size / avg; + + if (afl->q_testcase_max_cache_entries > 32768) + afl->q_testcase_max_cache_entries = 32768; + + } + + if (afl->q_testcase_max_cache_entries) { + + OKF("Setting %u maximum entries for the testcase cache", + afl->q_testcase_max_cache_entries); + afl->q_testcase_cache = + ck_alloc(afl->q_testcase_max_cache_entries * sizeof(size_t)); + if (!afl->q_testcase_cache) { PFATAL("malloc failed for cache entries"); } + + } + cull_queue(afl); if (!afl->pending_not_fuzzed) @@ -1366,8 +1428,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!afl->not_on_tty) { - sleep(4); - afl->start_time += 4000; + sleep(1); if (afl->stop_soon) { goto stop_fuzzing; } } @@ -1654,6 +1715,7 @@ stop_fuzzing: ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.out_file); ck_free(afl->sync_id); + if (afl->q_testcase_cache) { ck_free(afl->q_testcase_cache); } afl_state_deinit(afl); free(afl); /* not tracked */ -- cgit 1.4.1 From 0b9b4adbd3955102902823d8f07f4d155d954b8b Mon Sep 17 00:00:00 2001 From: Ruben ten Hove Date: Wed, 28 Oct 2020 14:03:01 +0100 Subject: show supplied -t option so we know it's used --- src/afl-fuzz-stats.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index bec90519..b4b2f747 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1152,6 +1152,10 @@ void show_init_stats(afl_state_t *afl) { ACTF("Applying timeout settings from resumed session (%u ms).", afl->fsrv.exec_tmout); + } else { + + OKF("-t option specified. We'll use an exec timeout of %s ms.", fsrv->exec_tmout); + } /* In non-instrumented mode, re-running every timing out test case with a -- cgit 1.4.1 From 587f66f1b341e9ad42655bc74843a2ed1d93ee09 Mon Sep 17 00:00:00 2001 From: Ruben ten Hove Date: Wed, 28 Oct 2020 15:42:07 +0100 Subject: whoops.. --- src/afl-fuzz-stats.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index b4b2f747..6841eb88 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1154,7 +1154,7 @@ void show_init_stats(afl_state_t *afl) { } else { - OKF("-t option specified. We'll use an exec timeout of %s ms.", fsrv->exec_tmout); + OKF("-t option specified. We'll use an exec timeout of %s ms.", afl->fsrv.exec_tmout); } -- cgit 1.4.1 From b5686eb63e1fcd6dac49cc458c50e52b51709f8c Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 29 Oct 2020 00:05:28 +0100 Subject: fixes two huge bugs --- src/afl-fuzz-one.c | 5 +++-- src/afl-fuzz-run.c | 3 ++- src/afl-fuzz-stats.c | 3 ++- 3 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src/afl-fuzz-stats.c') diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 35ff5466..0f3393d2 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -1850,8 +1850,9 @@ havoc_stage: r_max += 1; } - - if (unlikely(get_cur_time() - afl->last_path_time > 5000)) { + + if (unlikely(get_cur_time() - afl->last_path_time > 5000 && + afl->ready_for_splicing_count > 1)) { /* add expensive havoc cases here if there is no findings in the last 5s */ diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index dfd3abfb..fb259b5d 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -587,9 +587,10 @@ void sync_fuzzers(afl_state_t *afl) { u8 entry[12]; sprintf(entry, "id:%06u", next_min_accept); + while (m < n) { - if (memcmp(namelist[m]->d_name, entry, 9)) { + if (strcmp(namelist[m]->d_name, entry)) { m++; diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 6841eb88..321bbb35 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -1154,7 +1154,8 @@ void show_init_stats(afl_state_t *afl) { } else { - OKF("-t option specified. We'll use an exec timeout of %s ms.", afl->fsrv.exec_tmout); + ACTF("-t option specified. We'll use an exec timeout of %d ms.", + afl->fsrv.exec_tmout); } -- cgit 1.4.1