diff options
author | van Hauser <vh@thc.org> | 2020-05-29 14:35:05 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-29 14:35:05 +0200 |
commit | 710dda522186310a7fb4e3b6a05cae0b28fa619e (patch) | |
tree | f96fcfe756fe5e6e0dde11be8df8b3df9f654952 /src | |
parent | 6892018142cc21ba9a0744c0757d39f21e9b66bc (diff) | |
parent | c3b864d8d4dfaf148158a689df0c5ddf4bcc1f32 (diff) | |
download | afl++-710dda522186310a7fb4e3b6a05cae0b28fa619e.tar.gz |
Merge pull request #374 from AFLplusplus/dev
Dev
Diffstat (limited to 'src')
-rw-r--r-- | src/afl-as.c | 10 | ||||
-rw-r--r-- | src/afl-common.c | 2 | ||||
-rw-r--r-- | src/afl-forkserver.c | 83 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 80 | ||||
-rw-r--r-- | src/afl-fuzz-mutators.c | 3 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 34 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 129 | ||||
-rw-r--r-- | src/afl-fuzz.c | 30 |
8 files changed, 279 insertions, 92 deletions
diff --git a/src/afl-as.c b/src/afl-as.c index 4809a731..f16d6060 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -232,8 +232,8 @@ static void edit_params(int argc, char **argv) { } - modified_file = - alloc_printf("%s/.afl-%u-%u.s", tmp_dir, (u32)getpid(), (u32)time(NULL)); + modified_file = alloc_printf("%s/.afl-%u-%u-%u.s", tmp_dir, (u32)getpid(), + (u32)time(NULL), (u32)random()); wrap_things_up: @@ -531,7 +531,7 @@ static void add_instrumentation(void) { int main(int argc, char **argv) { s32 pid; - u32 rand_seed; + u32 rand_seed, i, j; int status; u8 *inst_ratio_str = getenv("AFL_INST_RATIO"); @@ -590,6 +590,10 @@ int main(int argc, char **argv) { gettimeofday(&tv, &tz); rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); + // in fast systems where pids can repeat in the same seconds we need this + for (i = 1; i < argc; i++) + for (j = 0; j < strlen(argv[i]); j++) + rand_seed += argv[i][j]; srandom(rand_seed); diff --git a/src/afl-common.c b/src/afl-common.c index 808c9812..1bb58a60 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -67,7 +67,7 @@ char *afl_environment_variables[] = { "AFL_LLVM_SKIPSINGLEBLOCK", "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", - "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", + "AFL_LLVM_LAF_ALL", "AFL_LLVM_LAF_TRANSFORM_COMPARES", "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1c0ba349..137a4f99 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -442,7 +442,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { - if (!be_quiet && getenv("AFL_DEBUG")) { + if (getenv("AFL_DEBUG")) { ACTF("Extended forkserver functions received (%08x).", status); @@ -455,6 +455,28 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } + if ((status & FS_OPT_SHDMEM_FUZZ) == FS_OPT_SHDMEM_FUZZ) { + + if (fsrv->support_shdmen_fuzz) { + + fsrv->use_shdmen_fuzz = 1; + if (!be_quiet) { ACTF("Using SHARED MEMORY FUZZING feature."); } + + if ((status & FS_OPT_AUTODICT) == 0) { + + u32 send_status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ); + if (write(fsrv->fsrv_ctl_fd, &send_status, 4) != 4) { + + FATAL("Writing to forkserver failed."); + + } + + } + + } + + } + if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); @@ -490,7 +512,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (fsrv->function_ptr == NULL || fsrv->function_opt == NULL) { // this is not afl-fuzz - we deny and return - status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT)); + if (fsrv->use_shdmen_fuzz) + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT | FS_OPT_SHDMEM_FUZZ); + else + status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { FATAL("Writing to forkserver failed."); @@ -677,9 +702,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, SAYF("\n" cLRD "[-] " cRST "Hmm, looks like the target binary terminated before we could" - "complete a handshake with the injected code.\n" + " complete a handshake with the injected code.\n" "If the target was compiled with afl-clang-lto then recompiling with" - "AFL_LLVM_MAP_DYNAMIC might solve your problem.\n" + " AFL_LLVM_MAP_DYNAMIC might solve your problem.\n" "Otherwise there is a horrible bug in the fuzzer.\n" "Poke <afl-users@googlegroups.com> for troubleshooting tips.\n"); @@ -749,39 +774,48 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) { void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { - s32 fd = fsrv->out_fd; + if (fsrv->shdmem_fuzz) { - if (fsrv->out_file) { + memcpy(fsrv->shdmem_fuzz, buf, len); + fsrv->shdmem_fuzz_len = len; - if (fsrv->no_unlink) { + } else { - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); + s32 fd = fsrv->out_fd; - } else { + if (fsrv->out_file) { - unlink(fsrv->out_file); /* Ignore errors. */ - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + if (fsrv->no_unlink) { - } + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); } + } else { - } else { + unlink(fsrv->out_file); /* Ignore errors. */ + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - lseek(fd, 0, SEEK_SET); + } - } + if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); } - ck_write(fd, buf, len, fsrv->out_file); + } else { - if (!fsrv->out_file) { + lseek(fd, 0, SEEK_SET); - if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); } - lseek(fd, 0, SEEK_SET); + } - } else { + ck_write(fd, buf, len, fsrv->out_file); - close(fd); + if (!fsrv->out_file) { + + if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); } + lseek(fd, 0, SEEK_SET); + + } else { + + close(fd); + + } } @@ -795,6 +829,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, s32 res; u32 exec_ms; + u32 write_value = fsrv->last_run_timed_out; /* After this memset, fsrv->trace_bits[] are effectively volatile, so we must prevent any earlier operations from venturing into that @@ -804,10 +839,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, MEM_BARRIER(); + if (fsrv->shdmem_fuzz_len) write_value += (fsrv->shdmem_fuzz_len << 8); + /* we have the fork server (or faux server) up and running First, tell it if the previous run timed out. */ - if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) { + if ((res = write(fsrv->fsrv_ctl_fd, &write_value, 4)) != 4) { if (*stop_soon_p) { return 0; } RPFATAL(res, "Unable to request new process from fork server (OOM?)"); diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 613d1437..9349fefe 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1315,6 +1315,39 @@ dir_cleanup_failed: } +/* If this is a -S slave, ensure a -M master is running, if a master is + running when another master is started then warn */ + +int check_master_exists(afl_state_t *afl) { + + DIR * sd; + struct dirent *sd_ent; + u8 * fn; + + sd = opendir(afl->sync_dir); + if (!sd) { return 0; } + + while ((sd_ent = readdir(sd))) { + + /* Skip dot files and our own output directory. */ + + if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) { + + continue; + + } + + fn = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + int res = access(fn, F_OK); + free(fn); + if (res == 0) return 1; + + } + + return 0; + +} + /* Prepare output directories and fds. */ void setup_dirs_fds(afl_state_t *afl) { @@ -1330,19 +1363,6 @@ void setup_dirs_fds(afl_state_t *afl) { } - /* - if (afl->is_master) { - - u8 *x = alloc_printf("%s/%s/is_master", afl->sync_dir, afl->sync_id); - int fd = open(x, O_CREAT | O_RDWR, 0644); - if (fd < 0) FATAL("cannot create %s", x); - free(x); - close(fd); - - } - - */ - if (mkdir(afl->out_dir, 0700)) { if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); } @@ -1372,6 +1392,16 @@ void setup_dirs_fds(afl_state_t *afl) { } + if (afl->is_master) { + + u8 *x = alloc_printf("%s/is_master", afl->out_dir); + int fd = open(x, O_CREAT | O_RDWR, 0644); + if (fd < 0) FATAL("cannot create %s", x); + free(x); + close(fd); + + } + /* Queue directory for any starting & discovered paths. */ tmp = alloc_printf("%s/queue", afl->out_dir); @@ -2123,6 +2153,30 @@ void check_binary(afl_state_t *afl, u8 *fname) { OKF(cPIN "Persistent mode binary detected."); setenv(PERSIST_ENV_VAR, "1", 1); afl->persistent_mode = 1; + // do not fail if we can not get the fuzzing shared mem + if ((afl->shm_fuzz = calloc(1, sizeof(sharedmem_t)))) { + + // we need to set the dumb mode to not overwrite the SHM_ENV_VAR + if ((afl->fsrv.shdmem_fuzz = afl_shm_init(afl->shm_fuzz, MAX_FILE, 1))) { + +#ifdef USEMMAP + setenv(SHM_FUZZ_ENV_VAR, afl->shm_fuzz->g_shm_file_path, 1); +#else + u8 *shm_str; + shm_str = alloc_printf("%d", afl->shm_fuzz->shm_id); + setenv(SHM_FUZZ_ENV_VAR, shm_str, 1); + ck_free(shm_str); +#endif + afl->fsrv.support_shdmen_fuzz = 1; + + } else { + + free(afl->shm_fuzz); + afl->shm_fuzz = NULL; + + } + + } } else if (getenv("AFL_PERSISTENT")) { diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 87cb86fa..29e10d02 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -108,9 +108,6 @@ void setup_custom_mutators(afl_state_t *afl) { #endif - if (afl->post_library_mutator) - list_append(&afl->custom_mutator_list, afl->post_library_mutator); - } void destroy_custom_mutators(afl_state_t *afl) { diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index ddd15c84..56f16b4c 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -4250,11 +4250,27 @@ pacemaker_fuzzing: u64 temp_temp_puppet = afl->queued_paths + afl->unique_crashes - temp_total_found; afl->total_puppet_find = afl->total_puppet_find + temp_temp_puppet; - for (i = 0; i < operator_num; ++i) { - if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) { + if (MOpt_globals.is_pilot_mode) { + + for (i = 0; i < operator_num; ++i) { + + if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) { + + MOpt_globals.finds_v2[i] += temp_temp_puppet; - MOpt_globals.finds_v2[i] += temp_temp_puppet; + } + + } + + } else { + + for (i = 0; i < operator_num; i++) { + + if (afl->core_operator_cycles_puppet_v2[i] > + afl->core_operator_cycles_puppet_v3[i]) + + afl->core_operator_finds_puppet_v2[i] += temp_temp_puppet; } @@ -4437,7 +4453,6 @@ pacemaker_fuzzing: afl->total_pacemaker_time += *MOpt_globals.pTime; *MOpt_globals.pTime = 0; - afl->temp_puppet_find = afl->total_puppet_find; new_hit_cnt = afl->queued_paths + afl->unique_crashes; if (MOpt_globals.is_pilot_mode) { @@ -4448,6 +4463,7 @@ pacemaker_fuzzing: } + afl->temp_puppet_find = afl->total_puppet_find; u64 temp_stage_finds_puppet = 0; for (i = 0; i < operator_num; ++i) { @@ -4530,6 +4546,16 @@ pacemaker_fuzzing: } else { + for (i = 0; i < operator_num; i++) { + + afl->core_operator_finds_puppet[i] = + afl->core_operator_finds_puppet_v2[i]; + afl->core_operator_cycles_puppet[i] = + afl->core_operator_cycles_puppet_v2[i]; + temp_stage_finds_puppet += afl->core_operator_finds_puppet[i]; + + } + afl->key_module = 2; afl->old_hit_count = new_hit_cnt; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index bbcd9a99..04450363 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -231,6 +231,16 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, afl_fsrv_start(&afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child_output); + if (afl->fsrv.support_shdmen_fuzz && !afl->fsrv.use_shdmen_fuzz) { + + afl_shm_deinit(afl->shm_fuzz); + free(afl->shm_fuzz); + afl->shm_fuzz = NULL; + afl->fsrv.support_shdmen_fuzz = 0; + afl->fsrv.shdmem_fuzz = NULL; + + } + } if (q->exec_cksum) { @@ -373,7 +383,8 @@ void sync_fuzzers(afl_state_t *afl) { DIR * sd; struct dirent *sd_ent; - u32 sync_cnt = 0; + u32 sync_cnt = 0, synced = 0, entries = 0; + u8 path[PATH_MAX]; sd = opendir(afl->sync_dir); if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } @@ -386,10 +397,8 @@ void sync_fuzzers(afl_state_t *afl) { while ((sd_ent = readdir(sd))) { - DIR * qd; - struct dirent *qd_ent; - u8 * qd_path, *qd_synced_path; - u32 min_accept = 0, next_min_accept; + u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX]; + u32 min_accept = 0, next_min_accept; s32 id_fd; @@ -401,35 +410,52 @@ void sync_fuzzers(afl_state_t *afl) { } - /* - // a slave only syncs from a master, a master syncs from everyone - if (likely(afl->is_slave)) { + entries++; + + // a slave only syncs from a master, a master syncs from everyone + if (likely(afl->is_slave)) { - u8 x = alloc_printf("%s/%s/is_master", afl->sync_dir, sd_ent->d_name); - int res = access(x, F_OK); - free(x); - if (res != 0) - continue; + sprintf(qd_path, "%s/%s/is_master", afl->sync_dir, sd_ent->d_name); + int res = access(qd_path, F_OK); + if (unlikely(afl->is_master)) { // an elected temporary master + + if (likely(res == 0)) { // there is another master? downgrade. + + afl->is_master = 0; + sprintf(qd_path, "%s/is_master", afl->out_dir); + unlink(qd_path); } - */ + } else { + + if (likely(res != 0)) { continue; } + + } + + } + + synced++; /* Skip anything that doesn't have a queue/ subdirectory. */ - qd_path = alloc_printf("%s/%s/queue", afl->sync_dir, sd_ent->d_name); + sprintf(qd_path, "%s/%s/queue", afl->sync_dir, sd_ent->d_name); + + struct dirent **namelist = NULL; + int m = 0, n, o; - if (!(qd = opendir(qd_path))) { + n = scandir(qd_path, &namelist, NULL, alphasort); - ck_free(qd_path); + if (n < 1) { + + if (namelist) free(namelist); continue; } /* Retrieve the ID of the last seen test case. */ - qd_synced_path = - alloc_printf("%s/.synced/%s", afl->out_dir, sd_ent->d_name); + sprintf(qd_synced_path, "%s/.synced/%s", afl->out_dir, sd_ent->d_name); id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); @@ -454,42 +480,42 @@ void sync_fuzzers(afl_state_t *afl) { /* For every file queued by this fuzzer, parse ID and see if we have looked at it before; exec a test case if not. */ - while ((qd_ent = readdir(qd))) { + u8 entry[12]; + sprintf(entry, "id:%06u", next_min_accept); + while (m < n) { - u8 * path; - s32 fd; - struct stat st; + if (memcmp(namelist[m]->d_name, entry, 9)) { + + m++; - if (qd_ent->d_name[0] == '.' || - sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &afl->syncing_case) != 1 || - afl->syncing_case < min_accept) { + } else { - continue; + break; } - /* OK, sounds like a new one. Let's give it a try. */ + } - if (afl->syncing_case >= next_min_accept) { + if (m >= n) { goto close_sync; } // nothing new + o = n - 1; - next_min_accept = afl->syncing_case + 1; + while (o >= m) { - } + s32 fd; + struct stat st; - path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); + sprintf(path, "%s/%s", qd_path, namelist[o]->d_name); + afl->syncing_case = next_min_accept; + next_min_accept++; + o--; /* Allow this to fail in case the other fuzzer is resuming or so... */ fd = open(path, O_RDONLY); - if (fd < 0) { - - ck_free(path); - continue; + if (fd < 0) { continue; } - } - - if (fstat(fd, &st)) { PFATAL("fstat() failed"); } + if (fstat(fd, &st)) { WARNF("fstat() failed"); } /* Ignore zero-sized or oversized files. */ @@ -516,11 +542,8 @@ void sync_fuzzers(afl_state_t *afl) { munmap(mem, st.st_size); - if (!(afl->stage_cur++ % afl->stats_update_freq)) { show_stats(afl); } - } - ck_free(path); close(fd); } @@ -529,14 +552,30 @@ void sync_fuzzers(afl_state_t *afl) { close_sync: close(id_fd); - closedir(qd); - ck_free(qd_path); - ck_free(qd_synced_path); + if (n > 0) + for (m = 0; m < n; m++) + free(namelist[m]); + free(namelist); } closedir(sd); + // If we are a slave and no master was found to sync then become the master + if (unlikely(synced == 0) && likely(entries) && likely(afl->is_slave)) { + + // there is a small race condition here that another slave runs at the same + // time. If so, the first temporary master running again will demote + // themselves so this is not an issue + + u8 path[PATH_MAX]; + afl->is_master = 1; + sprintf(path, "%s/is_master", afl->out_dir); + int fd = open(path, O_CREAT | O_RDWR, 0644); + if (fd >= 0) { close(fd); } + + } + } /* Trim all new test cases to save cycles when doing deterministic checks. The diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8625c37c..e024e9a4 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1065,8 +1065,22 @@ int main(int argc, char **argv_orig, char **envp) { init_count_class16(); + if (afl->is_master && check_master_exists(afl) == 1) { + + WARNF("it is wasteful to run more than one master!"); + sleep(1); + + } + setup_dirs_fds(afl); + if (afl->is_slave && check_master_exists(afl) == 0) { + + WARNF("no -M master found. You need to run one master!"); + sleep(5); + + } + setup_custom_mutators(afl); setup_cmdline_file(afl, argv + optind); @@ -1352,11 +1366,27 @@ stop_fuzzing: time_spent_working / afl->fsrv.total_execs); #endif + if (afl->is_master) { + + u8 path[PATH_MAX]; + sprintf(path, "%s/is_master", afl->out_dir); + unlink(path); + + } + fclose(afl->fsrv.plot_file); destroy_queue(afl); destroy_extras(afl); destroy_custom_mutators(afl); afl_shm_deinit(&afl->shm); + + if (afl->shm_fuzz) { + + afl_shm_deinit(afl->shm_fuzz); + free(afl->shm_fuzz); + + } + afl_fsrv_deinit(&afl->fsrv); if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } ck_free(afl->fsrv.target_path); |