diff --git a/Makefile b/Makefile index e4072def..44d1ffa2 100644 --- a/Makefile +++ b/Makefile @@ -123,7 +123,11 @@ install: all install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH) rm -f $${DESTDIR}$(BIN_PATH)/afl-as if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi +ifndef AFL_TRACE_PC if [ -f afl-clang-fast -a -f afl-llvm-pass.so -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-pass.so afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi +else + if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi +endif if [ -f afl-llvm-rt-32.o ]; then set -e; install -m 755 afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi if [ -f afl-llvm-rt-64.o ]; then set -e; install -m 755 afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/$$i; done diff --git a/afl-tmin.c b/afl-tmin.c index 73d4bac2..c1abbe7c 100644 --- a/afl-tmin.c +++ b/afl-tmin.c @@ -1075,6 +1075,7 @@ int main(int argc, char** argv) { The option may be extended and made more official if it proves to be useful. */ + if (mask_bitmap) FATAL("Multiple -B options not supported"); mask_bitmap = ck_alloc(MAP_SIZE); read_bitmap(optarg); break; diff --git a/config.h b/config.h index a5880b68..0f700bb1 100644 --- a/config.h +++ b/config.h @@ -21,7 +21,7 @@ /* Version string: */ -#define VERSION "2.36b" +#define VERSION "2.37b" /****************************************************** * * diff --git a/docs/ChangeLog b/docs/ChangeLog index fa776bc2..873cd6db 100644 --- a/docs/ChangeLog +++ b/docs/ChangeLog @@ -16,6 +16,22 @@ Not sure if you should upgrade? The lowest currently recommended version is 2.31b. If you're stuck on an earlier release, it's strongly advisable to get on with the times. +-------------- +Version 2.37b: +-------------- + + - Fixed a typo. Spotted by Jakub Wilk. + + - Fixed support for make install when using trace-pc. Spotted by + Kurt Roeckx. + + - Switched trace-pc to trace-pc-guard, which should be considerably + faster and is less quirky. Kudos to Konstantin Serebryany (and sorry + for dragging my feet). + + Note that for some reason, this mode doesn't perform as well as + "vanilla" afl-clang-fast / afl-clang. + -------------- Version 2.36b: -------------- diff --git a/llvm_mode/README.llvm b/llvm_mode/README.llvm index f7d48c91..d96d8c31 100644 --- a/llvm_mode/README.llvm +++ b/llvm_mode/README.llvm @@ -166,14 +166,14 @@ PS. Because there are task switches still involved, the mode isn't as fast as faster than the normal fork() model, and compared to in-process fuzzing, should be a lot more robust. -6) Bonus feature #3: new 'trace-pc' mode ----------------------------------------- +6) Bonus feature #3: new 'trace-pc-guard' mode +---------------------------------------------- Recent versions of LLVM are shipping with a built-in execution tracing feature -that is fairly usable for AFL, without the need to post-process the assembly -or install any compiler plugins. See: +that provides AFL with the necessary tracing data without the need to +post-process the assembly or install any compiler plugins. See: - http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs + http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards As of this writing, the feature is only available on SVN trunk, and is yet to make it to an official release of LLVM. Nevertheless, if you have a @@ -182,10 +182,7 @@ this way: AFL_TRACE_PC=1 make clean all -Since a form of 'trace-pc' is also supported in GCC, this mode may become a -longer-term solution to all our needs. +Note that this mode is currently about 20-30% slower than "vanilla" +afl-clang-fast, and about 5-10% slower than afl-clang. I am not entirely sure +why. -Note that this mode supports AFL_INST_RATIO at run time, not at compilation -time. This is somewhat similar to the behavior of the QEMU mode. Because of -the need to support it at run time, the mode is also a tad slower than the -plugin-based approach. diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 0bb233db..75db30cf 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -114,13 +114,13 @@ static void edit_params(u32 argc, char** argv) { /* There are two ways to compile afl-clang-fast. In the traditional mode, we use afl-llvm-pass.so to inject instrumentation. In the experimental - 'trace-pc' mode, we use native LLVM instrumentation callbacks instead. - The latter is a very recent addition - see: + 'trace-pc-guard' mode, we use native LLVM instrumentation callbacks + instead. The latter is a very recent addition - see: - http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs */ + http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards */ #ifdef USE_TRACE_PC - cc_params[cc_par_cnt++] = "-fsanitize-coverage=bb,trace-pc"; + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; #else cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = "-load"; diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index ad040e88..44d9e16e 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -49,10 +49,6 @@ namespace { bool runOnModule(Module &M) override; - /* Ugh, the return type changed in recent versions of LLVM - (const char* -> StringRef). Commenting out until the situation - stabilizes, since we don't strictly need this anyway. */ - // StringRef getPassName() const override { // return "American Fuzzy Lop Instrumentation"; // } diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index e2ef1516..bacbcd9e 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -34,6 +34,12 @@ #include #include +#ifdef USE_TRACE_PC +# define CONST_PRIO 5 +#else +# define CONST_PRIO 0 +#endif /* ^USE_TRACE_PC */ + /* Globals needed by the injected instrumentation. The __afl_area_initial region is used for instrumentation output before __afl_map_shm() has a chance to run. @@ -234,17 +240,12 @@ void __afl_manual_init(void) { } -static void __afl_trace_pc_init(void); - - /* Proper initialization routine. */ -__attribute__((constructor(0))) void __afl_auto_init(void) { +__attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { is_persistent = !!getenv(PERSIST_ENV_VAR); - __afl_trace_pc_init(); - if (getenv(DEFER_ENV_VAR)) return; __afl_manual_init(); @@ -252,63 +253,42 @@ __attribute__((constructor(0))) void __afl_auto_init(void) { } -/* The following stuff deals with support for -fsanitize-coverage=bb,trace-pc. +/* The following stuff deals with supporting -fsanitize-coverage=trace-pc-guard. It remains non-operational in the traditional, plugin-backed LLVM mode. - For more info about 'trace-pc', see README.llvm. - - The first function (__sanitizer_cov_trace_pc) is called back on every - basic block. Since LLVM is not giving us any stable IDs for the blocks, - we use 12 least significant bits of the return address (which should be - stable even with ASLR; more significant bits may vary across runs). - - Since MAP_SIZE is usually larger than 12 bits, we "pad" it by combining - left-shifted __afl_prev_loc. This gives us a theoretical maximum of 24 - bits, although instruction alignment likely reduces this somewhat. */ - - -static u32 inst_ratio_scaled = MIN(4096, MAP_SIZE); + For more info about 'trace-pc-guard', see README.llvm. -void __sanitizer_cov_trace_pc(void) { + The first function (__sanitizer_cov_trace_pc_guard) is called back on every + edge (as opposed to every basic block). */ - u32 cur = ((u32)__builtin_return_address(0)) & MIN(4095, MAP_SIZE - 1); - - if (cur > inst_ratio_scaled) return; - - __afl_area_ptr[cur ^ __afl_prev_loc]++; - -#if MAP_SIZE_POW2 > 12 - __afl_prev_loc = cur << (MAP_SIZE_POW2 - 12); -#else - __afl_prev_loc = cur >> 1; -#endif /* ^MAP_SIZE_POW2 > 12 */ +void __sanitizer_cov_trace_pc_guard(uint32_t* guard) { + __afl_area_ptr[*guard]++; } -/* Init callback. Unfortunately, LLVM does not support compile-time - instrumentation density scaling, at least not just yet. This means - taking some performance hit by checking inst_ratio_scaled at runtime. */ - -static void __afl_trace_pc_init(void) { +/* Init callback. Populates instrumentation IDs. Note that we're using + ID of 0 as a special value to indicate non-instrumented bits. */ - u8* x = getenv("AFL_INST_RATIO"); +void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop) { - if (!x) return; + u32 inst_ratio = 100; + u8* x; - inst_ratio_scaled = atoi(x); + x = getenv("AFL_INST_RATIO"); + if (x) inst_ratio = atoi(x); - if (!inst_ratio_scaled || inst_ratio_scaled > 100) { + if (!inst_ratio || inst_ratio > 100) { fprintf(stderr, "[-] ERROR: Invalid AFL_INST_RATIO (must be 1-100).\n"); abort(); } - inst_ratio_scaled = inst_ratio_scaled * MIN(4096, MAP_SIZE) / 100; - -} + while (start < stop) { + if (R(100) < inst_ratio) *start = R(MAP_SIZE - 1) + 1; + else *start = 0; -/* Work around a short-lived bug in LLVM with -fsanitize-coverage=trace-pc. */ + start++; -void __sanitizer_cov_module_init(void) __attribute__((weak)); -void __sanitizer_cov_module_init(void) { } + } +} diff --git a/qemu_mode/README.qemu b/qemu_mode/README.qemu index c27b2557..f9dce996 100644 --- a/qemu_mode/README.qemu +++ b/qemu_mode/README.qemu @@ -100,7 +100,7 @@ somehow need to fuzz an untrusted binary, put everything in a sandbox first. QEMU does not necessarily support all CPU or hardware features that your target program may be utilizing. In particular, it does not appear to have -full support for AVX2 / FMA3. Using binaries for older CPUs, or recompling them +full support for AVX2 / FMA3. Using binaries for older CPUs, or recompiling them with -march=core2, can help. Beyond that, this is an early-stage mechanism, so fields reports are welcome.