diff options
author | Andrea Fioraldi <andreafioraldi@gmail.com> | 2020-04-16 19:53:51 +0200 |
---|---|---|
committer | Andrea Fioraldi <andreafioraldi@gmail.com> | 2020-04-16 19:53:51 +0200 |
commit | 23ea7279159dce964c69b3dfa5e7e36f3d5a5085 (patch) | |
tree | c29eeca17acee61a862646149b8cd1d9a4cf97f3 | |
parent | f157bca54858dce131e90f664da2505d43e0f65f (diff) | |
parent | 35937e62634f69b34c852abb0aaeca546a712f4f (diff) | |
download | afl++-23ea7279159dce964c69b3dfa5e7e36f3d5a5085.tar.gz |
Merge branch 'dev' of github.com:vanhauser-thc/AFLplusplus into dev
-rw-r--r-- | GNUmakefile | 2 | ||||
-rw-r--r-- | README.md | 1 | ||||
-rw-r--r-- | include/afl-fuzz.h | 4 | ||||
-rw-r--r-- | include/common.h | 10 | ||||
-rw-r--r-- | include/debug.h | 4 | ||||
-rw-r--r-- | include/forkserver.h | 16 | ||||
-rw-r--r-- | llvm_mode/README.lto.md | 16 | ||||
-rw-r--r-- | llvm_mode/afl-clang-fast.c | 6 | ||||
-rw-r--r-- | src/afl-analyze.c | 73 | ||||
-rw-r--r-- | src/afl-common.c | 80 | ||||
-rw-r--r-- | src/afl-forkserver.c | 84 | ||||
-rw-r--r-- | src/afl-fuzz-bitmap.c | 36 | ||||
-rw-r--r-- | src/afl-fuzz-cmplog.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-mutators.c | 5 | ||||
-rw-r--r-- | src/afl-fuzz-one.c | 4 | ||||
-rw-r--r-- | src/afl-fuzz-python.c | 2 | ||||
-rw-r--r-- | src/afl-fuzz-redqueen.c | 4 | ||||
-rw-r--r-- | src/afl-fuzz-run.c | 56 | ||||
-rw-r--r-- | src/afl-fuzz.c | 4 | ||||
-rw-r--r-- | src/afl-sharedmem.c | 2 | ||||
-rw-r--r-- | src/afl-showmap.c | 133 | ||||
-rw-r--r-- | src/afl-tmin.c | 161 | ||||
-rw-r--r-- | src/third_party/libradamsa/libradamsa.c | 76 | ||||
-rw-r--r-- | src/third_party/libradamsa/radamsa.h | 6 | ||||
-rw-r--r-- | test/unittests/unit_list.c | 2 | ||||
-rw-r--r-- | test/unittests/unit_maybe_alloc.c | 2 | ||||
-rw-r--r-- | test/unittests/unit_preallocable.c | 2 |
27 files changed, 345 insertions, 448 deletions
diff --git a/GNUmakefile b/GNUmakefile index 74a290e6..11dfa803 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -69,7 +69,7 @@ ifneq "$(shell uname -m)" "x86_64" endif CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) -override CFLAGS += -Wall -g -Wno-pointer-sign \ +override CFLAGS += -Wall -g -Wno-pointer-sign -Wmissing-declarations\ -I include/ -Werror -DAFL_PATH=\"$(HELPER_PATH)\" \ -DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" diff --git a/README.md b/README.md index f14ccd36..a6afe73a 100644 --- a/README.md +++ b/README.md @@ -352,6 +352,7 @@ Here are some good writeups to show how to effectively use AFL++: * [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/) * [https://bananamafia.dev/post/gb-fuzz/](https://bananamafia.dev/post/gb-fuzz/) * [https://securitylab.github.com/research/fuzzing-challenges-solutions-1](https://securitylab.github.com/research/fuzzing-challenges-solutions-1) + * [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP) If you are interested in fuzzing structured data (where you define what the structure is), these two links have you covered: diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 7c6019e6..363776cb 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -808,6 +808,7 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf); /* Python */ #ifdef USE_PYTHON +void load_custom_mutator_py(afl_state_t *, char *); void finalize_py_module(void *); size_t pre_save_py(void *, u8 *, size_t, u8 **); @@ -835,7 +836,6 @@ u32 calculate_score(afl_state_t *, struct queue_entry *); /* Bitmap */ -void read_bitmap(afl_state_t *, u8 *); void write_bitmap(afl_state_t *); u32 count_bits(afl_state_t *, u8 *); u32 count_bytes(afl_state_t *, u8 *); @@ -873,7 +873,7 @@ void show_init_stats(afl_state_t *); /* Run */ -fsrv_run_result_t run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); +fsrv_run_result_t fuzz_run_target(afl_state_t *, afl_forkserver_t *fsrv, u32); void write_to_testcase(afl_state_t *, void *, u32); u8 calibrate_case(afl_state_t *, struct queue_entry *, u8 *, u32, u8); void sync_fuzzers(afl_state_t *); diff --git a/include/common.h b/include/common.h index 8dd66355..f5ace878 100644 --- a/include/common.h +++ b/include/common.h @@ -51,6 +51,16 @@ char * get_afl_env(char *env); extern u8 be_quiet; extern u8 *doc_path; /* path to documentation dir */ +/* Find binary, used by analyze, showmap, tmin + @returns the path, allocating the string */ + +u8 *find_binary(u8 *fname); + +/* Read a bitmap from file fname to memory + This is for the -B option again. */ + +void read_bitmap(u8 *fname, u8 *map, size_t len); + /* Get unix time in milliseconds */ u64 get_cur_time(void); diff --git a/include/debug.h b/include/debug.h index 8824ff6b..4cce56b5 100644 --- a/include/debug.h +++ b/include/debug.h @@ -29,12 +29,8 @@ #include "config.h" /* __FUNCTION__ is non-iso */ -#ifndef __FUNCTION__ #ifdef __func__ #define __FUNCTION__ __func__ -#else -#define __FUNCTION__ "func_unknown" -#endif #endif /******************* diff --git a/include/forkserver.h b/include/forkserver.h index f24393bc..ac89b681 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -51,6 +51,8 @@ typedef struct afl_forkserver { fsrv_ctl_fd, /* Fork server control pipe (write) */ fsrv_st_fd; /* Fork server status pipe (read) */ + u8 no_unlink; /* do not unlink cur_input */ + u32 exec_tmout; /* Configurable exec timeout (ms) */ u32 map_size; /* map size used by the target */ u32 snapshot; /* is snapshot feature used */ @@ -63,7 +65,8 @@ typedef struct afl_forkserver { FILE *plot_file; /* Gnuplot output file */ - u8 last_run_timed_out; /* Traced process timed out? */ + /* Note: lat_run_timed_out is u32 to send it to the child as 4 byte array */ + u32 last_run_timed_out; /* Traced process timed out? */ u8 last_kill_signal; /* Signal that killed the child */ @@ -97,12 +100,11 @@ void afl_fsrv_init(afl_forkserver_t *fsrv); void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from); void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output); -fsrv_run_result_t afl_fsrv_run_target( - afl_forkserver_t *fsrv, u32 timeout, - void(classify_counts_func)(afl_forkserver_t *fsrv), - volatile u8 *stop_soon_p); -void afl_fsrv_killall(void); -void afl_fsrv_deinit(afl_forkserver_t *fsrv); +void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len); +fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, + volatile u8 *stop_soon_p); +void afl_fsrv_killall(void); +void afl_fsrv_deinit(afl_forkserver_t *fsrv); #ifdef __APPLE__ #define MSG_FORK_ON_APPLE \ diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 51b50544..9af9ffff 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -17,17 +17,17 @@ This version requires a current llvm 11 compiled from the github master. ## Introduction and problem description A big issue with how afl/afl++ works is that the basic block IDs that are -set during compilation are random - and hence natually the larger the number -of instrumented locations, the higher the number of edge collisions in the +set during compilation are random - and hence naturally the larger the number +of instrumented locations, the higher the number of edge collisions are in the map. This can result in not discovering new paths and therefore degrade the -efficiency of the fuzzing. +efficiency of the fuzzing process. -*This issue is understimated in the fuzzing community!* +*This issue is underestimated in the fuzzing community!* With a 2^16 = 64kb standard map at already 256 instrumented blocks there is on average one collision. On average a target has 10.000 to 50.000 instrumented blocks hence the real collisions are between 750-18.000! -To get to a solution that prevents any collision took several approaches +To reach a solution that prevents any collisions took several approaches and many dead ends until we got to this: * We instrument at link time when we have all files pre-compiled @@ -76,7 +76,7 @@ $ make install ## How to use afl-clang-lto -Just use afl-clang-lto like you did afl-clang-fast or afl-gcc. +Just use afl-clang-lto like you did with afl-clang-fast or afl-gcc. Also whitelisting (AFL_LLVM_WHITELIST -> [README.whitelist.md](README.whitelist.md)) and laf-intel/compcov (AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work. @@ -120,7 +120,7 @@ Please report issues at: ## Upcoming Work -1. Currently the LTO whitelist feature does not allow to not instrument main, +1. Currently the LTO whitelist feature does not allow to instrument main, start and init functions ## History @@ -138,7 +138,7 @@ This was first implemented in January and work ... kinda. The LTO time instrumentation worked, however the "how" the basic blocks were instrumented was a problem, as reducing duplicates turned out to be very, very difficult with a program that has so many paths and therefore so many -dependencies. At lot of stratgies were implemented - and failed. +dependencies. At lot of strategies were implemented - and failed. And then sat solvers were tried, but with over 10.000 variables that turned out to be a dead-end too. diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 57d7b89a..c0471033 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -223,8 +223,10 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (getenv("LAF_TRANSFORM_COMPARES") || - getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) { + if ((!(getenv("AFL_LLVM_LTO_AUTODICTIONARY") // disabled when autodictionary + && instrument_mode != INSTRUMENT_LTO)) // and lto_mode is used + && (getenv("LAF_TRANSFORM_COMPARES") || + getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES"))) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; diff --git a/src/afl-analyze.c b/src/afl-analyze.c index 952786b0..6f946ed5 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -209,7 +209,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { /* Execute target application. Returns exec checksum, or 0 if program times out. */ -static u32 run_target(char **argv, u8 *mem, u32 len, u8 first_run) { +static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { static struct itimerval it; int status = 0; @@ -560,16 +560,16 @@ static void analyze(char **argv) { code. */ in_data[i] ^= 0xff; - xor_ff = run_target(argv, in_data, in_len, 0); + xor_ff = analyze_run_target(argv, in_data, in_len, 0); in_data[i] ^= 0xfe; - xor_01 = run_target(argv, in_data, in_len, 0); + xor_01 = analyze_run_target(argv, in_data, in_len, 0); in_data[i] = (in_data[i] ^ 0x01) - 0x10; - sub_10 = run_target(argv, in_data, in_len, 0); + sub_10 = analyze_run_target(argv, in_data, in_len, 0); in_data[i] += 0x20; - add_10 = run_target(argv, in_data, in_len, 0); + add_10 = analyze_run_target(argv, in_data, in_len, 0); in_data[i] -= 0x10; /* Classify current behavior. */ @@ -805,61 +805,6 @@ static void usage(u8 *argv0) { } -/* Find binary. */ - -static void find_binary(u8 *fname) { - - u8 * env_path = 0; - struct stat st; - - if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { - - target_path = ck_strdup(fname); - - if (stat(target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || st.st_size < 4) - FATAL("Program '%s' not found or not executable", fname); - - } else { - - while (env_path) { - - u8 *cur_elem, *delim = strchr(env_path, ':'); - - if (delim) { - - cur_elem = ck_alloc(delim - env_path + 1); - memcpy(cur_elem, env_path, delim - env_path); - delim++; - - } else - - cur_elem = ck_strdup(env_path); - - env_path = delim; - - if (cur_elem[0]) - target_path = alloc_printf("%s/%s", cur_elem, fname); - else - target_path = ck_strdup(fname); - - ck_free(cur_elem); - - if (!stat(target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && st.st_size >= 4) - break; - - ck_free(target_path); - target_path = 0; - - } - - if (!target_path) FATAL("Program '%s' not found or not executable", fname); - - } - -} - /* Main entry point */ int main(int argc, char **argv, char **envp) { @@ -902,7 +847,7 @@ int main(int argc, char **argv, char **envp) { if (mem_limit_given) FATAL("Multiple -m options not supported"); mem_limit_given = 1; - if (!optarg) { FATAL("Bad syntax used for -m"); } + if (!optarg) { FATAL("Wrong usage of -m"); } if (!strcmp(optarg, "none")) { @@ -997,7 +942,7 @@ int main(int argc, char **argv, char **envp) { set_up_environment(); - find_binary(argv[optind]); + target_path = find_binary(argv[optind]); detect_file_args(argv + optind, prog_in, &use_stdin); if (qemu_mode) { @@ -1020,7 +965,7 @@ int main(int argc, char **argv, char **envp) { ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", mem_limit, exec_tmout, edges_only ? ", edges only" : ""); - run_target(use_argv, in_data, in_len, 1); + analyze_run_target(use_argv, in_data, in_len, 1); if (child_timed_out) FATAL("Target binary times out (adjusting -t may help)."); @@ -1032,6 +977,8 @@ int main(int argc, char **argv, char **envp) { OKF("We're done here. Have a nice day!\n"); + if (target_path) ck_free(target_path); + afl_shm_deinit(&shm); exit(0); diff --git a/src/afl-common.c b/src/afl-common.c index 1ac1a2f3..ffc32533 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -37,6 +37,10 @@ #include <unistd.h> #endif #include <limits.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> u8 be_quiet = 0; u8 *doc_path = ""; @@ -353,6 +357,68 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } +/* Find binary, used by analyze, showmap, tmin + @returns the path, allocating the string */ + +u8 *find_binary(u8 *fname) { + + // TODO: Merge this function with check_binary of afl-fuzz-init.c + + u8 *env_path = NULL; + u8 *target_path = NULL; + + struct stat st; + + if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { + + target_path = ck_strdup(fname); + + if (stat(target_path, &st) || !S_ISREG(st.st_mode) || + !(st.st_mode & 0111) || st.st_size < 4) + FATAL("Program '%s' not found or not executable", fname); + + } else { + + while (env_path) { + + u8 *cur_elem, *delim = strchr(env_path, ':'); + + if (delim) { + + cur_elem = ck_alloc(delim - env_path + 1); + memcpy(cur_elem, env_path, delim - env_path); + delim++; + + } else + + cur_elem = ck_strdup(env_path); + + env_path = delim; + + if (cur_elem[0]) + target_path = alloc_printf("%s/%s", cur_elem, fname); + else + target_path = ck_strdup(fname); + + ck_free(cur_elem); + + if (!stat(target_path, &st) && S_ISREG(st.st_mode) && + (st.st_mode & 0111) && st.st_size >= 4) + break; + + ck_free(target_path); + target_path = NULL; + + } + + if (!target_path) FATAL("Program '%s' not found or not executable", fname); + + } + + return target_path; + +} + void check_environment_vars(char **envp) { if (be_quiet) return; @@ -414,6 +480,20 @@ char *get_afl_env(char *env) { } +/* Read mask bitmap from file. This is for the -B option. */ + +void read_bitmap(u8 *fname, u8 *map, size_t len) { + + s32 fd = open(fname, O_RDONLY); + + if (fd < 0) PFATAL("Unable to open '%s'", fname); + + ck_read(fd, map, len, fname); + + close(fd); + +} + u64 get_cur_time(void) { struct timeval tv; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9c89a723..006764d9 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -8,7 +8,9 @@ Now maintained by Marc Heuse <mh@mh-sec.de>, Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and - Andrea Fioraldi <andreafioraldi@gmail.com> + Andrea Fioraldi <andreafioraldi@gmail.com> and + Dominik Maier <mail@dmnk.co> + Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. @@ -38,10 +40,12 @@ #include <time.h> #include <errno.h> #include <signal.h> +#include <fcntl.h> #include <sys/time.h> #include <sys/wait.h> #include <sys/resource.h> #include <sys/select.h> +#include <sys/stat.h> /** * The correct fds for reading and writing pipes @@ -64,15 +68,20 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { // this structure needs default so we initialize it if this was not done // already - fsrv->use_stdin = 1; fsrv->out_fd = -1; fsrv->out_dir_fd = -1; fsrv->dev_null_fd = -1; #ifndef HAVE_ARC4RANDOM fsrv->dev_urandom_fd = -1; #endif + /* Settings */ + fsrv->use_stdin = 1; + fsrv->no_unlink = 0; fsrv->exec_tmout = EXEC_TIMEOUT; fsrv->mem_limit = MEM_LIMIT; + fsrv->out_file = NULL; + + /* exec related stuff */ fsrv->child_pid = -1; fsrv->map_size = MAP_SIZE; fsrv->use_fauxsrv = 0; @@ -103,6 +112,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { fsrv_to->child_pid = -1; fsrv_to->use_fauxsrv = 0; fsrv_to->last_run_timed_out = 0; + fsrv_to->out_file = NULL; fsrv_to->init_child_func = fsrv_exec_child; @@ -385,7 +395,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { - if (!be_quiet) + if (!be_quiet && getenv("AFL_DEBUG")) ACTF("Extended forkserver functions received (%08x).", status); if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { @@ -398,13 +408,19 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if ((status & FS_OPT_MAPSIZE) == FS_OPT_MAPSIZE) { fsrv->map_size = FS_OPT_GET_MAPSIZE(status); - if (fsrv->map_size % 8) // should not happen + if (unlikely(fsrv->map_size % 8)) { + + // should not happen + WARNF("Target reported non-aligned map size of %ud", fsrv->map_size); fsrv->map_size = (((fsrv->map_size + 8) >> 3) << 3); + + } + if (!be_quiet) ACTF("Target map size: %u", fsrv->map_size); if (fsrv->map_size > MAP_SIZE) FATAL( "Target's coverage map size of %u is larger than the one this " - "afl++ is compiled with (%u)\n", + "afl++ is compiled with (%u) (change MAP_SIZE and recompile)\n", fsrv->map_size, MAP_SIZE); } @@ -434,7 +450,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, u32 len = status, offset = 0, count = 0; u8 *dict = ck_alloc(len); if (dict == NULL) - FATAL("Could not allocate %u bytes of autodictionary memmory", len); + FATAL("Could not allocate %u bytes of autodictionary memory", len); while (len != 0) { @@ -640,13 +656,53 @@ static void afl_fsrv_kill(afl_forkserver_t *fsrv) { } +/* Delete the current testcase and write the buf to the testcase file */ + +void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { + + s32 fd = fsrv->out_fd; + + if (fsrv->out_file) { + + if (fsrv->no_unlink) { + + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); + + } else { + + unlink(fsrv->out_file); /* Ignore errors. */ + fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); + + } + + if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); + + } else { + + lseek(fd, 0, SEEK_SET); + + } + + ck_write(fd, buf, len, fsrv->out_file); + + if (!fsrv->out_file) { + + if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); + lseek(fd, 0, SEEK_SET); + + } else { + + close(fd); + + } + +} + /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t afl_fsrv_run_target( - afl_forkserver_t *fsrv, u32 timeout, - void(classify_counts_func)(afl_forkserver_t *fsrv), - volatile u8 *stop_soon_p) { +fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, + volatile u8 *stop_soon_p) { s32 res; u32 exec_ms; @@ -675,7 +731,7 @@ fsrv_run_result_t afl_fsrv_run_target( if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { - if (stop_soon_p) return 0; + if (*stop_soon_p) return 0; RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } @@ -732,9 +788,6 @@ fsrv_run_result_t afl_fsrv_run_target( behave very normally and do not have to be treated as volatile. */ MEM_BARRIER(); - u32 tb4 = *(u32 *)fsrv->trace_bits; - - if (likely(classify_counts_func)) classify_counts_func(fsrv); /* Report outcome to caller. */ @@ -759,7 +812,8 @@ fsrv_run_result_t afl_fsrv_run_target( } - if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR; + // Fauxserver should handle this now. + // if (tb4 == EXEC_FAIL_SIG) return FSRV_RUN_ERROR; return FSRV_RUN_OK; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 852e3a7c..be8f504e 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -49,20 +49,6 @@ void write_bitmap(afl_state_t *afl) { } -/* Read bitmap from file. This is for the -B option again. */ - -void read_bitmap(afl_state_t *afl, u8 *fname) { - - s32 fd = open(fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", fname); - - ck_read(fd, afl->virgin_bits, MAP_SIZE, fname); - - close(fd); - -} - /* Check if the current execution path brings anything new to the table. Update virgin bits to reflect the finds. Returns 1 if the only change is the hit-count for a particular tuple; 2 if there are new tuples seen. @@ -88,7 +74,8 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { u32 i = (afl->fsrv.map_size >> 2); #endif /* ^WORD_SIZE_64 */ - if (i == 0) i = 1; + // the map size must be a minimum of 8 bytes. + // for variable/dynamic map sizes this is ensured in the forkserver u8 ret = 0; @@ -98,6 +85,7 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { that have not been already cleared from the virgin map - since this will almost always be the case. */ + // the (*current) is unnecessary but speeds up the overall comparison if (unlikely(*current) && unlikely(*current & *virgin)) { if (likely(ret < 2)) { @@ -110,18 +98,20 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { #ifdef WORD_SIZE_64 - if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || - (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || - (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || - (cur[6] && vir[6] == 0xff) || (cur[7] && vir[7] == 0xff)) + if (*virgin == 0xffffffffffffffff || (cur[0] && vir[0] == 0xff) || + (cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) || + (cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) || + (cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) || + (cur[7] && vir[7] == 0xff)) ret = 2; else ret = 1; #else - if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) || - (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff)) + if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) || + (cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) || + (cur[3] && vir[3] == 0xff)) ret = 2; else ret = 1; @@ -139,7 +129,7 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { } - if (unlikely(ret) && unlikely(virgin_map == afl->virgin_bits)) + if (unlikely(ret) && likely(virgin_map == afl->virgin_bits)) afl->bitmap_changed = 1; return ret; @@ -649,7 +639,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { u8 new_fault; write_to_testcase(afl, mem, len); - new_fault = run_target(afl, &afl->fsrv, afl->hang_tmout); + new_fault = fuzz_run_target(afl, &afl->fsrv, afl->hang_tmout); /* A corner case that one user reported bumping into: increasing the timeout actually uncovers a crash. Make sure we don't discard it if diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index ab93d838..12c814ba 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -62,7 +62,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { write_to_testcase(afl, out_buf, len); - fault = run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); + fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); if (afl->stop_soon) return 1; diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 7bf23e84..434b4673 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -27,9 +27,6 @@ #include "afl-fuzz.h" void load_custom_mutator(afl_state_t *, const char *); -#ifdef USE_PYTHON -void load_custom_mutator_py(afl_state_t *, char *); -#endif void setup_custom_mutator(afl_state_t *afl) { @@ -239,7 +236,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { write_to_testcase(afl, retbuf, retlen); - fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index cc97654a..a4ba739e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -27,7 +27,7 @@ /* MOpt */ -int select_algorithm(afl_state_t *afl) { +static int select_algorithm(afl_state_t *afl) { int i_puppet, j_puppet; @@ -2366,7 +2366,7 @@ abandon_entry: } /* MOpt mode */ -u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { +static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (!MOpt_globals.is_pilot_mode) { diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index 12c3a09d..33f01797 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -41,7 +41,7 @@ it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */ (void **)&((py_mutator_t *)py_mutator)->name##_buf, \ &((py_mutator_t *)py_mutator)->name##_size -size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, +static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, u8 *add_buf, size_t add_buf_size, size_t max_size) { size_t mutated_size; diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 6f2fb144..3e9af088 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -37,7 +37,7 @@ struct range { }; -struct range *add_range(struct range *ranges, u32 start, u32 end) { +static struct range *add_range(struct range *ranges, u32 start, u32 end) { struct range *r = ck_alloc_nozero(sizeof(struct range)); r->start = start; @@ -47,7 +47,7 @@ struct range *add_range(struct range *ranges, u32 start, u32 end) { } -struct range *pop_biggest_range(struct range **ranges) { +static struct range *pop_biggest_range(struct range **ranges) { struct range *r = *ranges; struct range *prev = NULL; diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index c3ed59ef..6ad6444a 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -6,7 +6,8 @@ Now maintained by Marc Heuse <mh@mh-sec.de>, Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and - Andrea Fioraldi <andreafioraldi@gmail.com> + Andrea Fioraldi <andreafioraldi@gmail.com> and + Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. @@ -32,10 +33,13 @@ /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t run_target(afl_state_t *afl, afl_forkserver_t *fsrv, +fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { - return afl_fsrv_run_target(fsrv, timeout, classify_counts, &afl->stop_soon); + fsrv_run_result_t res = afl_fsrv_run_target(fsrv, timeout, &afl->stop_soon); + // TODO: Don't classify for faults? + classify_counts(fsrv); + return res; } @@ -45,13 +49,11 @@ fsrv_run_result_t run_target(afl_state_t *afl, afl_forkserver_t *fsrv, void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { - s32 fd = afl->fsrv.out_fd; - #ifdef _AFL_DOCUMENT_MUTATIONS s32 doc_fd; char fn[PATH_MAX]; - snprintf(fn, PATH_MAX, ("%s/mutations/%09u:%s", afl->out_dir, - afl->document_counter++, describe_op(afl, 0)); + snprintf(fn, PATH_MAX, "%s/mutations/%09u:%s", afl->out_dir, + afl->document_counter++, describe_op(afl, 0)); if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) { @@ -63,25 +65,6 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { #endif - if (afl->fsrv.out_file) { - - if (afl->no_unlink) { - - fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600); - - } else { - - unlink(afl->fsrv.out_file); /* Ignore errors. */ - fd = open(afl->fsrv.out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - - } - - if (fd < 0) PFATAL("Unable to create '%s'", afl->fsrv.out_file); - - } else - - lseek(fd, 0, SEEK_SET); - if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) { u8 *new_buf = NULL; @@ -93,24 +76,15 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size); /* everything as planned. use the new data. */ - ck_write(fd, new_buf, new_size, afl->fsrv.out_file); + afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size); } else { /* boring uncustom. */ - ck_write(fd, mem, len, afl->fsrv.out_file); + afl_fsrv_write_to_testcase(&afl->fsrv, mem, len); } - if (!afl->fsrv.out_file) { - - if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); - lseek(fd, 0, SEEK_SET); - - } else - - close(fd); - } /* The same, but with an adjustable gap. Used for trimming. */ @@ -217,7 +191,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, write_to_testcase(afl, use_mem, q->len); - fault = run_target(afl, &afl->fsrv, use_tmout); + fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, we want to bail out quickly. */ @@ -435,7 +409,7 @@ void sync_fuzzers(afl_state_t *afl) { write_to_testcase(afl, mem, st.st_size); - fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); if (afl->stop_soon) goto close_sync; @@ -522,7 +496,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { write_with_gap(afl, in_buf, q->len, remove_pos, trim_avail); - fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming; @@ -629,7 +603,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { write_to_testcase(afl, out_buf, len); - fault = run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); + fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); if (afl->stop_soon) return 1; diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 9f17b61b..925dbb1a 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -420,6 +420,8 @@ int main(int argc, char **argv_orig, char **envp) { if (mem_limit_given) FATAL("Multiple -m options not supported"); mem_limit_given = 1; + if (!optarg) FATAL("Wrong usage of -m"); + if (!strcmp(optarg, "none")) { afl->fsrv.mem_limit = 0; @@ -474,7 +476,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->in_bitmap) FATAL("Multiple -B options not supported"); afl->in_bitmap = optarg; - read_bitmap(afl, afl->in_bitmap); + read_bitmap(afl->in_bitmap, afl->virgin_bits, MAP_SIZE); break; case 'C': /* crash mode */ diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index 16d6fe41..01ba62aa 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -60,7 +60,7 @@ #include <sys/shm.h> #endif -list_t shm_list = {.element_prealloc_count = 0}; +static list_t shm_list = {.element_prealloc_count = 0}; /* Get rid of shared memory. */ diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 2326d469..61c1754f 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -8,7 +8,8 @@ Now maintained by Marc Heuse <mh@mh-sec.de>, Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and - Andrea Fioraldi <andreafioraldi@gmail.com> + Andrea Fioraldi <andreafioraldi@gmail.com> and + Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. @@ -61,8 +62,8 @@ static char *stdin_file; /* stdin file */ -static u8 *in_dir, /* input folder */ - *at_file = NULL; /* Substitution string for @@ */ +static u8 *in_dir = NULL, /* input folder */ + *out_file = NULL, *at_file = NULL; /* Substitution string for @@ */ static u8 *in_data; /* Input data */ @@ -157,7 +158,7 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { fd = open(outfile, O_WRONLY); - if (fd < 0) PFATAL("Unable to open '%s'", fsrv->out_file); + if (fd < 0) PFATAL("Unable to open '%s'", out_file); } else if (!strcmp(outfile, "-")) { @@ -215,41 +216,22 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { } -/* Write results. */ - -static u32 write_results(afl_forkserver_t *fsrv) { - - return write_results_to_file(fsrv, fsrv->out_file); - -} - -/* Write modified data to file for testing. If use_stdin is clear, the old file - is unlinked and a new one is created. Otherwise, out_fd is rewound and - truncated. */ - -static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) { - - lseek(fsrv->out_fd, 0, SEEK_SET); - ck_write(fsrv->out_fd, mem, len, fsrv->out_file); - if (ftruncate(fsrv->out_fd, len)) PFATAL("ftruncate() failed"); - lseek(fsrv->out_fd, 0, SEEK_SET); - -} - /* Execute target application. */ -void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, +static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len) { - write_to_testcase(fsrv, mem, len); + afl_fsrv_write_to_testcase(fsrv, mem, len); - if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, - &stop_soon) == FSRV_RUN_ERROR) { + if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) == + FSRV_RUN_ERROR) { FATAL("Error running target"); } + classify_counts(fsrv); + if (stop_soon) { SAYF(cRST cLRD "\n+++ afl-showmap folder mode aborted by user +++\n" cRST); @@ -261,7 +243,7 @@ void run_target_forkserver(afl_forkserver_t *fsrv, char **argv, u8 *mem, /* Read initial file. */ -u32 read_file(u8 *in_file) { +static u32 read_file(u8 *in_file) { struct stat st; s32 fd = open(in_file, O_RDONLY); @@ -286,7 +268,7 @@ u32 read_file(u8 *in_file) { /* Execute target application. */ -static void run_target(afl_forkserver_t *fsrv, char **argv) { +static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { static struct itimerval it; int status = 0; @@ -544,62 +526,6 @@ static void usage(u8 *argv0) { } -/* Find binary. */ - -static void find_binary(afl_forkserver_t *fsrv, u8 *fname) { - - u8 * env_path = 0; - struct stat st; - - if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { - - fsrv->target_path = ck_strdup(fname); - - if (stat(fsrv->target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || st.st_size < 4) - FATAL("Program '%s' not found or not executable", fname); - - } else { - - while (env_path) { - - u8 *cur_elem, *delim = strchr(env_path, ':'); - - if (delim) { - - cur_elem = ck_alloc(delim - env_path + 1); - memcpy(cur_elem, env_path, delim - env_path); - delim++; - - } else - - cur_elem = ck_strdup(env_path); - - env_path = delim; - - if (cur_elem[0]) - fsrv->target_path = alloc_printf("%s/%s", cur_elem, fname); - else - fsrv->target_path = ck_strdup(fname); - - ck_free(cur_elem); - - if (!stat(fsrv->target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && st.st_size >= 4) - break; - - ck_free(fsrv->target_path); - fsrv->target_path = NULL; - - } - - if (!fsrv->target_path) - FATAL("Program '%s' not found or not executable", fname); - - } - -} - /* Main entry point */ int main(int argc, char **argv_orig, char **envp) { @@ -632,8 +558,8 @@ int main(int argc, char **argv_orig, char **envp) { case 'o': - if (fsrv->out_file) FATAL("Multiple -o options not supported"); - fsrv->out_file = optarg; + if (out_file) FATAL("Multiple -o options not supported"); + out_file = optarg; break; case 'm': { @@ -643,6 +569,8 @@ int main(int argc, char **argv_orig, char **envp) { if (mem_limit_given) FATAL("Multiple -m options not supported"); mem_limit_given = 1; + if (!optarg) FATAL("Wrong usage of -m"); + if (!strcmp(optarg, "none")) { fsrv->mem_limit = 0; @@ -686,6 +614,8 @@ int main(int argc, char **argv_orig, char **envp) { if (timeout_given) FATAL("Multiple -t options not supported"); timeout_given = 1; + if (!optarg) FATAL("Wrong usage of -t"); + if (strcmp(optarg, "none")) { fsrv->exec_tmout = atoi(optarg); @@ -780,7 +710,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (optind == argc || !fsrv->out_file) usage(argv[0]); + if (optind == argc || !out_file) usage(argv[0]); check_environment_vars(envp); @@ -790,7 +720,7 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv); - find_binary(fsrv, argv[optind]); + fsrv->target_path = find_binary(argv[optind]); if (!quiet_mode) { @@ -831,7 +761,7 @@ int main(int argc, char **argv_orig, char **envp) { DIR * dir_in, *dir_out; struct dirent *dir_ent; int done = 0; - u8 infile[4096], outfile[4096]; + u8 infile[PATH_MAX], outfile[PATH_MAX]; #if !defined(DT_REG) struct stat statbuf; #endif @@ -841,9 +771,9 @@ int main(int argc, char **argv_orig, char **envp) { if (!(dir_in = opendir(in_dir))) PFATAL("cannot open directory %s", in_dir); - if (!(dir_out = opendir(fsrv->out_file))) - if (mkdir(fsrv->out_file, 0700)) - PFATAL("cannot create output directory %s", fsrv->out_file); + if (!(dir_out = opendir(out_file))) + if (mkdir(out_file, 0700)) + PFATAL("cannot create output directory %s", out_file); u8 *use_dir = "."; @@ -858,7 +788,7 @@ int main(int argc, char **argv_orig, char **envp) { unlink(stdin_file); atexit(at_exit_handler); fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); + if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file); if (arg_offset && argv[arg_offset] != stdin_file) { @@ -897,12 +827,11 @@ int main(int argc, char **argv_orig, char **envp) { if (-1 == stat(infile, &statbuf) || !S_ISREG(statbuf.st_mode)) continue; #endif - snprintf(outfile, sizeof(outfile), "%s/%s", fsrv->out_file, - dir_ent->d_name); + snprintf(outfile, sizeof(outfile), "%s/%s", out_file, dir_ent->d_name); if (read_file(infile)) { - run_target_forkserver(fsrv, use_argv, in_data, in_len); + showmap_run_target_forkserver(fsrv, use_argv, in_data, in_len); ck_free(in_data); tcnt = write_results_to_file(fsrv, outfile); @@ -917,8 +846,8 @@ int main(int argc, char **argv_orig, char **envp) { } else { - run_target(fsrv, use_argv); - tcnt = write_results(fsrv); + showmap_run_target(fsrv, use_argv); + tcnt = write_results_to_file(fsrv, out_file); } @@ -926,7 +855,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!tcnt) FATAL("No instrumentation detected" cRST); OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST, - tcnt, highest, total, fsrv->out_file); + tcnt, highest, total, out_file); } diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 84e9a498..431ff0c4 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -8,7 +8,8 @@ Now maintained by Marc Heuse <mh@mh-sec.de>, Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and - Andrea Fioraldi <andreafioraldi@gmail.com> + Andrea Fioraldi <andreafioraldi@gmail.com> and + Dominik Maier <mail@dmnk.co> Copyright 2016, 2017 Google Inc. All rights reserved. Copyright 2019-2020 AFLplusplus Project. All rights reserved. @@ -61,7 +62,7 @@ static u8 *mask_bitmap; /* Mask for trace bits (-B) */ static u8 *in_file, /* Minimizer input test case */ - *output_file; /* Minimizer output file */ + *out_file, *output_file; /* Minimizer output file */ static u8 *in_data; /* Input data for trimming */ @@ -120,8 +121,6 @@ static void apply_mask(u32 *mem, u32 *mask) { static void classify_counts(afl_forkserver_t *fsrv) { - if (hang_mode) return; /* We only want hangs */ - u8 *mem = fsrv->trace_bits; u32 i = MAP_SIZE; @@ -145,8 +144,6 @@ static void classify_counts(afl_forkserver_t *fsrv) { } - apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap); - } /* See if any bytes are set in the bitmap. */ @@ -214,49 +211,16 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { } -/* Write modified data to file for testing. If use_stdin is clear, the old file - is unlinked and a new one is created. Otherwise, out_fd is rewound and - truncated. */ - -static void write_to_testcase(afl_forkserver_t *fsrv, void *mem, u32 len) { - - s32 fd = fsrv->out_fd; - - if (!fsrv->use_stdin) { - - unlink(fsrv->out_file); /* Ignore errors. */ - - fd = open(fsrv->out_file, O_WRONLY | O_CREAT | O_EXCL, 0600); - - if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); - - } else - - lseek(fd, 0, SEEK_SET); - - ck_write(fd, mem, len, fsrv->out_file); - - if (fsrv->use_stdin) { - - if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); - lseek(fd, 0, SEEK_SET); - - } else - - close(fd); - -} - /* Execute target application. Returns 0 if the changes are a dud, or 1 if they should be kept. */ -static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, +static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, u8 first_run) { - write_to_testcase(fsrv, mem, len); + afl_fsrv_write_to_testcase(fsrv, mem, len); fsrv_run_result_t ret = - afl_fsrv_run_target(fsrv, fsrv->exec_tmout, classify_counts, &stop_soon); + afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon); if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child"); @@ -282,6 +246,9 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, } + classify_counts(fsrv); + apply_mask((u32 *)fsrv->trace_bits, (u32 *)mask_bitmap); + if (ret == FSRV_RUN_TMOUT) { missed_hangs++; @@ -369,7 +336,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) { memset(tmp_buf + set_pos, '0', use_len); u8 res; - res = run_target(fsrv, argv, tmp_buf, in_len, 0); + res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); if (res) { @@ -442,7 +409,7 @@ next_del_blksize: /* Tail */ memcpy(tmp_buf + del_pos, in_data + del_pos + del_len, tail_len); - res = run_target(fsrv, argv, tmp_buf, del_pos + tail_len, 0); + res = tmin_run_target(fsrv, argv, tmp_buf, del_pos + tail_len, 0); if (res) { @@ -505,7 +472,7 @@ next_del_blksize: for (r = 0; r < in_len; r++) if (tmp_buf[r] == i) tmp_buf[r] = '0'; - res = run_target(fsrv, argv, tmp_buf, in_len, 0); + res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); if (res) { @@ -541,7 +508,7 @@ next_del_blksize: if (orig == '0') continue; tmp_buf[i] = '0'; - res = run_target(fsrv, argv, tmp_buf, in_len, 0); + res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); if (res) { @@ -613,7 +580,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { fsrv->dev_null_fd = open("/dev/null", O_RDWR); if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null"); - if (!fsrv->out_file) { + if (!out_file) { u8 *use_dir = "."; @@ -624,15 +591,15 @@ static void set_up_environment(afl_forkserver_t *fsrv) { } - fsrv->out_file = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid()); + out_file = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid()); } - unlink(fsrv->out_file); + unlink(out_file); - fsrv->out_fd = open(fsrv->out_file, O_RDWR | O_CREAT | O_EXCL, 0600); + fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); + if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file); /* Set sane defaults... */ @@ -782,76 +749,6 @@ static void usage(u8 *argv0) { } -/* Find binary. */ - -static void find_binary(afl_forkserver_t *fsrv, u8 *fname) { - - u8 * env_path = 0; - struct stat st; - - if (strchr(fname, '/') || !(env_path = getenv("PATH"))) { - - fsrv->target_path = ck_strdup(fname); - - if (stat(fsrv->target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || st.st_size < 4) - FATAL("Program '%s' not found or not executable", fname); - - } else { - - while (env_path) { - - u8 *cur_elem, *delim = strchr(env_path, ':'); - - if (delim) { - - cur_elem = ck_alloc(delim - env_path + 1); - memcpy(cur_elem, env_path, delim - env_path); - delim++; - - } else - - cur_elem = ck_strdup(env_path); - - env_path = delim; - - if (cur_elem[0]) - fsrv->target_path = alloc_printf("%s/%s", cur_elem, fname); - else - fsrv->target_path = ck_strdup(fname); - - ck_free(cur_elem); - - if (!stat(fsrv->target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && st.st_size >= 4) - break; - - ck_free(fsrv->target_path); - fsrv->target_path = NULL; - - } - - if (!fsrv->target_path) - FATAL("Program '%s' not found or not executable", fname); - - } - -} - -/* Read mask bitmap from file. This is for the -B option. */ - -static void read_bitmap(u8 *fname) { - - s32 fd = open(fname, O_RDONLY); - - if (fd < 0) PFATAL("Unable to open '%s'", fname); - - ck_read(fd, mask_bitmap, MAP_SIZE, fname); - - close(fd); - -} - /* Main entry point */ int main(int argc, char **argv_orig, char **envp) { @@ -888,9 +785,9 @@ int main(int argc, char **argv_orig, char **envp) { case 'f': - if (fsrv->out_file) FATAL("Multiple -f options not supported"); + if (out_file) FATAL("Multiple -f options not supported"); fsrv->use_stdin = 0; - fsrv->out_file = optarg; + out_file = optarg; break; case 'e': @@ -914,6 +811,8 @@ int main(int argc, char **argv_orig, char **envp) { if (mem_limit_given) FATAL("Multiple -m options not supported"); mem_limit_given = 1; + if (!optarg) FATAL("Wrong usage of -m"); + if (!strcmp(optarg, "none")) { fsrv->mem_limit = 0; @@ -950,6 +849,8 @@ int main(int argc, char **argv_orig, char **envp) { if (timeout_given) FATAL("Multiple -t options not supported"); timeout_given = 1; + if (!optarg) FATAL("Wrong usage of -t"); + fsrv->exec_tmout = atoi(optarg); if (fsrv->exec_tmout < 10 || optarg[0] == '-') @@ -1010,7 +911,7 @@ int main(int argc, char **argv_orig, char **envp) { if (mask_bitmap) FATAL("Multiple -B options not supported"); mask_bitmap = ck_alloc(MAP_SIZE); - read_bitmap(optarg); + read_bitmap(optarg, mask_bitmap, MAP_SIZE); break; case 'h': @@ -1034,8 +935,8 @@ int main(int argc, char **argv_orig, char **envp) { set_up_environment(fsrv); - find_binary(fsrv, argv[optind]); - detect_file_args(argv + optind, fsrv->out_file, &fsrv->use_stdin); + fsrv->target_path = find_binary(argv[optind]); + detect_file_args(argv + optind, out_file, &fsrv->use_stdin); if (fsrv->qemu_mode) { @@ -1069,7 +970,7 @@ int main(int argc, char **argv_orig, char **envp) { ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...", fsrv->mem_limit, fsrv->exec_tmout, edges_only ? ", edges only" : ""); - run_target(fsrv, use_argv, in_data, in_len, 1); + tmin_run_target(fsrv, use_argv, in_data, in_len, 1); if (hang_mode && !fsrv->last_run_timed_out) FATAL( @@ -1105,9 +1006,9 @@ int main(int argc, char **argv_orig, char **envp) { ACTF("Writing output to '%s'...", output_file); - unlink(fsrv->out_file); - if (fsrv->out_file) ck_free(fsrv->out_file); - fsrv->out_file = NULL; + unlink(out_file); + if (out_file) ck_free(out_file); + out_file = NULL; close(write_to_file(output_file, in_data, in_len)); diff --git a/src/third_party/libradamsa/libradamsa.c b/src/third_party/libradamsa/libradamsa.c index 27cf91bc..4f5515e5 100644 --- a/src/third_party/libradamsa/libradamsa.c +++ b/src/third_party/libradamsa/libradamsa.c @@ -1841,6 +1841,8 @@ static const unsigned char heap[] = {2,3,4,105,111,116,97,2,3,7,112,97,116,116,1 #include <stdio.h> #include <netdb.h> +#include "./radamsa.h" + #ifndef EMULTIHOP #define EMULTIHOP -1 #endif @@ -2155,17 +2157,17 @@ static word *gc(int size, word *regs) { /*** OS Interaction and Helpers ***/ -static void signal_handler(int signal) { - switch (signal) { - case SIGINT: - breaked |= 2; - break; - case SIGPIPE: - break; /* can cause loop when reporting errors */ - default: - breaked |= 4; - } -} +//static void signal_handler(int signal) { +// switch (signal) { +// case SIGINT: +// breaked |= 2; +// break; +// case SIGPIPE: +// break; /* can cause loop when reporting errors */ +// default: +// breaked |= 4; +// } +//} /* list length, no overflow or valid termination checks */ static uint llen(word *ptr) { @@ -2176,7 +2178,7 @@ static uint llen(word *ptr) { } return len; } - +/* static void set_signal_handler(void) { struct sigaction sa; sa.sa_handler = signal_handler; @@ -2185,7 +2187,7 @@ static void set_signal_handler(void) { sigaction(SIGINT, &sa, NULL); sigaction(SIGPIPE, &sa, NULL); } - +*/ static word mkpair(word h, word a, word d) { word *pair; allocate(3, pair); @@ -30683,7 +30685,7 @@ static void heap_metrics(int *rwords, int *rnobjs) { get_obj_metrics(rwords, rnobjs); hp = hp_start; } - +/* static void read_heap(const char *path) { struct stat st; off_t pos = 0; @@ -30703,25 +30705,26 @@ static void read_heap(const char *path) { } while (n && (pos += n) < st.st_size); close(fd); } +*/ /* find a fasl image source to *hp or exit */ -static void find_heap(int *nargs, char ***argv, int *nobjs, int *nwords) { - file_heap = NULL; - if ((word)heap == 0) { +//static void find_heap(int *nargs, char ***argv, int *nobjs, int *nwords) { +// file_heap = NULL; +// if ((word)heap == 0) { /* if no preloaded heap, try to load it from first vm arg */ - if (*nargs < 2) - exit(1); - read_heap(argv[0][1]); - ++*argv; - --*nargs; - hp = file_heap; - if (*hp == '#') - while (*hp++ != '\n'); - } else { - hp = heap; /* builtin heap */ - } - heap_metrics(nwords, nobjs); -} +// if (*nargs < 2) +// exit(1); +// read_heap(argv[0][1]); +// ++*argv; +// --*nargs; +// hp = file_heap; +// if (*hp == '#') +// while (*hp++ != '\n'); +// } else { +// hp = heap; /* builtin heap */ +// } +// heap_metrics(nwords, nobjs); +//} static word *decode_fasl(uint nobjs) { word *ptrs; @@ -30744,7 +30747,7 @@ static word *load_heap(uint nobjs) { free(file_heap); return entry; } - +/* static void setup(int nwords, int nobjs) { tcgetattr(0, &tsettings); state = IFALSE; @@ -30757,7 +30760,7 @@ static void setup(int nwords, int nobjs) { memend = memstart + nwords - MEMPAD; } -int secondary(int nargs, char **argv) { +static int secondary(int nargs, char **argv) { word *prog; int rval, nobjs=0, nwords=0; find_heap(&nargs, &argv, &nobjs, &nwords); @@ -30772,6 +30775,7 @@ int secondary(int nargs, char **argv) { } return 127; } +*/ void radamsa_init(void) { int nobjs=0, nwords=0; @@ -30787,7 +30791,7 @@ void radamsa_init(void) { } /* bvec → value library call test with preserved state */ -word library_call(word val) { +static word library_call(word val) { word program_state = state; word res; state = IFALSE; @@ -30798,7 +30802,8 @@ word library_call(word val) { return res; } -size_t list_length(word lispval) { +/* +static size_t list_length(word lispval) { size_t l = 0; while(lispval != INULL) { lispval = G(lispval, 2); @@ -30806,8 +30811,9 @@ size_t list_length(word lispval) { } return l; } +*/ -size_t copy_list(uint8_t *ptr, word lispval, size_t max) { +static size_t copy_list(uint8_t *ptr, word lispval, size_t max) { size_t n = 0; while(pairp((word)lispval) && max-- && lispval != INULL) { *ptr++ = 255 & immval(G(lispval, 1)); // *ptr++ = car(list) diff --git a/src/third_party/libradamsa/radamsa.h b/src/third_party/libradamsa/radamsa.h index 33cccde4..073599da 100644 --- a/src/third_party/libradamsa/radamsa.h +++ b/src/third_party/libradamsa/radamsa.h @@ -1,13 +1,13 @@ #include <inttypes.h> #include <stddef.h> -extern void radamsa_init(void); +void radamsa_init(void); -extern size_t radamsa(uint8_t *ptr, size_t len, +size_t radamsa(uint8_t *ptr, size_t len, uint8_t *target, size_t max, unsigned int seed); -extern size_t radamsa_inplace(uint8_t *ptr, +size_t radamsa_inplace(uint8_t *ptr, size_t len, size_t max, unsigned int seed); diff --git a/test/unittests/unit_list.c b/test/unittests/unit_list.c index 11d3227c..90700a11 100644 --- a/test/unittests/unit_list.c +++ b/test/unittests/unit_list.c @@ -27,6 +27,7 @@ extern void mock_assert(const int result, const char* const expression, (compile with `--wrap=exit`) */ extern void exit(int status); extern void __real_exit(int status); +void __wrap_exit(int status); void __wrap_exit(int status) { assert(0); } @@ -34,6 +35,7 @@ void __wrap_exit(int status) { /* ignore all printfs */ extern int printf(const char *format, ...); extern int __real_printf(const char *format, ...); +int __wrap_printf(const char *format, ...); int __wrap_printf(const char *format, ...) { return 1; } diff --git a/test/unittests/unit_maybe_alloc.c b/test/unittests/unit_maybe_alloc.c index d9c037a0..8cd8b11a 100644 --- a/test/unittests/unit_maybe_alloc.c +++ b/test/unittests/unit_maybe_alloc.c @@ -22,6 +22,7 @@ extern void mock_assert(const int result, const char* const expression, mock_assert((int)(expression), #expression, __FILE__, __LINE__); #include "alloc-inl.h" +void __wrap_exit(int status); /* remap exit -> assert, then use cmocka's mock_assert (compile with `--wrap=exit`) */ extern void exit(int status); @@ -30,6 +31,7 @@ void __wrap_exit(int status) { assert(0); } +int __wrap_printf(const char *format, ...); /* ignore all printfs */ extern int printf(const char *format, ...); extern int __real_printf(const char *format, ...); diff --git a/test/unittests/unit_preallocable.c b/test/unittests/unit_preallocable.c index 8cd36165..8d619b78 100644 --- a/test/unittests/unit_preallocable.c +++ b/test/unittests/unit_preallocable.c @@ -27,6 +27,7 @@ extern void mock_assert(const int result, const char* const expression, (compile with `--wrap=exit`) */ extern void exit(int status); extern void __real_exit(int status); +void __wrap_exit(int status); void __wrap_exit(int status) { assert(0); } @@ -34,6 +35,7 @@ void __wrap_exit(int status) { /* ignore all printfs */ extern int printf(const char *format, ...); extern int __real_printf(const char *format, ...); +int __wrap_printf(const char *format, ...); int __wrap_printf(const char *format, ...) { return 1; } |