diff options
Diffstat (limited to 'src/afl-fuzz-init.c')
-rw-r--r-- | src/afl-fuzz-init.c | 221 |
1 files changed, 211 insertions, 10 deletions
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index adfc55ad..3fe308b8 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -24,8 +24,12 @@ */ #include "afl-fuzz.h" -#include <limits.h> +#include "aflrun.h" #include "cmplog.h" +#include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> #ifdef HAVE_AFFINITY @@ -624,7 +628,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) { u32 len = write_to_testcase(afl, (void **)&mem, st.st_size, 1); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); afl->syncing_party = foreign_name; - afl->queued_imported += save_if_interesting(afl, mem, len, fault); + afl->queued_imported += save_if_interesting(afl, mem, len, fault, 0); afl->syncing_party = 0; munmap(mem, st.st_size); close(fd); @@ -655,8 +659,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) { void read_testcases(afl_state_t *afl, u8 *directory) { struct dirent **nl; - s32 nl_cnt, subdirs = 1; - u32 i; + s32 i, nl_cnt, subdirs = 1; u8 *fn1, *dir = directory; u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX]; @@ -716,10 +719,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) { if (nl_cnt) { - i = nl_cnt; - do { - - --i; + for (i = 0; i < nl_cnt; ++i) { struct stat st; u8 dfn[PATH_MAX]; @@ -810,7 +810,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) { */ - } while (i > 0); + } } @@ -1163,7 +1163,7 @@ void perform_dry_run(afl_state_t *afl) { struct queue_entry *p = afl->queue_buf[i]; if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; } - if (p->exec_cksum == q->exec_cksum) { + if (p->exec_cksum == q->exec_cksum && p->path_cksum == q->path_cksum) { duplicates = 1; @@ -1179,6 +1179,7 @@ void perform_dry_run(afl_state_t *afl) { } p->disabled = 1; + aflrun_remove_seed(p->id); p->perf_score = 0; } else { @@ -1192,6 +1193,7 @@ void perform_dry_run(afl_state_t *afl) { } q->disabled = 1; + aflrun_remove_seed(q->id); q->perf_score = 0; done = 1; @@ -1222,6 +1224,9 @@ void perform_dry_run(afl_state_t *afl) { OKF("All test cases processed."); + if (getenv("AFLRUN_TRACE_CORPUS")) + exit(0); + } /* Helper function: link() if possible, copy otherwise. */ @@ -1813,6 +1818,10 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); + fn = alloc_printf("%s/cvx", afl->out_dir); + if (delete_files(fn, NULL)) { goto dir_cleanup_failed; } + ck_free(fn); + /* And now, for some finishing touches. */ if (afl->file_extension) { @@ -2027,6 +2036,12 @@ void setup_dirs_fds(afl_state_t *afl) { if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); + /* All convex optimization information */ + + tmp = alloc_printf("%s/cvx", afl->out_dir); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } + ck_free(tmp); + /* All recorded hangs. */ tmp = alloc_printf("%s/hangs", afl->out_dir); @@ -2863,6 +2878,13 @@ void check_binary(afl_state_t *afl, u8 *fname) { } + // Load path to AFLRun temporary directory + const char* temp_str = memmem( + f_data, f_len, AFLRUN_TEMP_SIG, strlen(AFLRUN_TEMP_SIG)); + if (temp_str == NULL) + FATAL("Binary is not compiled from AFLRun compiler."); + afl->temp_dir = strdup(temp_str + strlen(AFLRUN_TEMP_SIG)); + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } } @@ -2968,3 +2990,182 @@ void save_cmdline(afl_state_t *afl, u32 argc, char **argv) { } +/* Initialize AFLRun with the temp dir */ + +void aflrun_temp_dir_init(afl_state_t* afl, const char* temp_dir) { + + u8* bbr_path = alloc_printf("%s/BBreachable.txt", temp_dir); + FILE* fd = fopen(bbr_path, "r"); + ck_free(bbr_path); + if (fd == NULL) + FATAL("Failed to open BBreachable.txt"); + char* line = NULL; size_t len = 0; + ssize_t res = getline(&line, &len, fd); + if (res == -1 || line == NULL) + FATAL("Failed to read BBreachable.txt"); + + char* endptr; + afl->fsrv.num_targets = strtoul(line, &endptr, 10); + if (*endptr != ',') + FATAL("Wrong format for BBreachable.txt"); + *endptr = 0; + afl->fsrv.num_reachables = strtoul(endptr + 1, &endptr, 10); + if (*endptr != 0 && *endptr != '\n') + FATAL("Wrong format for BBreachable.txt"); + + if (afl->fsrv.num_targets == 0 || + afl->fsrv.num_targets > afl->fsrv.num_reachables) + FATAL("Wrong number of targets and reachables"); + + afl->reachable_names = malloc( + afl->fsrv.num_reachables * sizeof(char*)); + + free(line); + + afl->reachable_to_targets = + malloc(afl->fsrv.num_reachables * sizeof(reach_t*)); + afl->reachable_to_size = + malloc(afl->fsrv.num_reachables * sizeof(reach_t)); + afl->virgin_reachables = + malloc(MAP_RBB_SIZE(afl->fsrv.num_reachables)); + afl->target_weights = + malloc(afl->fsrv.num_targets * sizeof(double)); + + reach_t next_idx = 0; + while (1) { + line = NULL; len = 0; + res = getline(&line, &len, fd); + if (res == -1) { + free(line); + break; + } + + // Parse the line into targets + reach_t* buf = malloc(afl->fsrv.num_targets * sizeof(reach_t)); + reach_t idx = 0; + char* iter = strchr(line, ','); + if (iter == NULL) + FATAL("Wrong format for BBreachable.txt"); + *iter = 0; + afl->reachable_names[next_idx] = strdup(line); + ++iter; + char* endptr; + while (1) { + if (idx >= afl->fsrv.num_targets) + FATAL("Too many elements in line of BBreachable.txt"); + reach_t t = strtoul(iter, &endptr, 10); + if (t >= afl->fsrv.num_targets) + FATAL("Invalid target in line of BBreachable.txt"); + buf[idx++] = t; + if (*endptr != ',') + break; + iter = endptr + 1; + } + if (next_idx < afl->fsrv.num_targets) { + if (*endptr != '|') + FATAL("Need weight for each target"); + afl->target_weights[next_idx] = strtod(endptr + 1, NULL); + } + + if (next_idx >= afl->fsrv.num_reachables) + FATAL("Header and countent of BBreachable.txt does not match"); + afl->reachable_to_size[next_idx] = idx; + afl->reachable_to_targets[next_idx++] = + realloc(buf, idx * sizeof(reach_t)); + free(line); + } + if (next_idx != afl->fsrv.num_reachables) + FATAL("Header and countent of BBreachable.txt does not match"); + + fclose(fd); + + aflrun_load_freachables( + temp_dir, &afl->fsrv.num_ftargets, &afl->fsrv.num_freachables); + if (afl->fsrv.num_ftargets == 0 || + afl->fsrv.num_ftargets > afl->fsrv.num_freachables) + FATAL("Parsing Freachable.txt failed"); + afl->virgin_freachables = malloc( + MAP_RF_SIZE(afl->fsrv.num_freachables)); + + ACTF("Loading edges..."); + aflrun_load_edges(temp_dir, afl->fsrv.num_reachables); + ACTF("Loading distances..."); + aflrun_load_dists( + temp_dir, afl->fsrv.num_targets, + afl->fsrv.num_reachables, afl->reachable_names); + aflrun_init_groups(afl->fsrv.num_targets); + +} + +/* Search directory with name `temp_dir` in directory `root`, + return its full path if any is found, the returned buffer needs free(). */ + +static char* search_temp_dir(const char* dir_path, const char* temp_dir) { + + DIR *dir = opendir(dir_path); + if (dir == NULL) + return NULL; + + struct dirent *entry; + while ((entry = readdir(dir)) != NULL) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + + char* sub_dir = malloc(PATH_MAX); + snprintf(sub_dir, PATH_MAX, "%s/%s", dir_path, entry->d_name); + + struct stat path_stat; + if (lstat(sub_dir, &path_stat) != 0) { + free(sub_dir); + continue; + } + + if (S_ISDIR(path_stat.st_mode)) { + if (strcmp(entry->d_name, temp_dir) == 0) + return sub_dir; + char* res = search_temp_dir(sub_dir, temp_dir); + if (res) { + free(sub_dir); + return res; + } + } + + free(sub_dir); + + } + + closedir(dir); + return NULL; +} + +/* Given the temp dir found in the binary, we find its real path. + We always return the allocated real path if any is found */ + +char* aflrun_find_temp(char* temp_dir) { + + size_t len = strlen(temp_dir); + if (len == 0) { + return NULL; + } + + // If the path in the binary is correct, simply use the directory. + struct stat path_stat; + if (lstat(temp_dir, &path_stat) == 0 && S_ISDIR(path_stat.st_mode)) + return strdup(temp_dir); + + // Remove the trailing slashes + for (char* p = temp_dir + len - 1; *p == '/' || *p == '\\'; --p) *p = 0; + + char* dir_name = strrchr(temp_dir, '/') + 1; + + char pwd[PATH_MAX]; + if (getcwd(pwd, PATH_MAX) == NULL) + FATAL("getcwd() failed"); + + // We alternatively find a directory whose name is same as the stored name. + // Since the name of temp dir is randomly generated with unlikely collition, + // the approach should work properly. + + return search_temp_dir(pwd, dir_name); + +} \ No newline at end of file |