From 705d24fb3ad80af5544b43ade6927d24a9367a69 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Thu, 14 Oct 2021 20:59:27 +0200 Subject: [PATCH 01/10] Initial commit for compiler, preload and userspace tools --- config.h | 2 + llvm_mode/Makefile | 20 +++------ llvm_mode/afl-llvm-pass.so.cc | 3 +- llvm_mode/afl-llvm-rt.o.c | 83 ++++++++++++++++++++++++++++++++--- 4 files changed, 87 insertions(+), 21 deletions(-) diff --git a/config.h b/config.h index ea6aac4..b21298d 100644 --- a/config.h +++ b/config.h @@ -328,6 +328,8 @@ #define MAP_SIZE_POW2 16 #define MAP_SIZE (1 << MAP_SIZE_POW2) +#define STATE_STR_LEN 12 + /* Maximum allocator request size (keep well under INT_MAX): */ #define MAX_ALLOC 0x40000000 diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 7617f91..823e959 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -23,6 +23,7 @@ BIN_PATH = $(PREFIX)/bin VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2) LLVM_CONFIG ?= llvm-config +LLVM_BINPATH = $(shell $(LLVM_CONFIG) --bindir) CFLAGS ?= -O3 -funroll-loops CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ @@ -51,8 +52,8 @@ endif # probably better. ifeq "$(origin CC)" "default" - CC = clang - CXX = clang++ + CC = $(LLVM_BINPATH)/clang + CXX = $(LLVM_BINPATH)/clang++ endif ifndef AFL_TRACE_PC @@ -61,7 +62,7 @@ else PROGS = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o endif -all: test_deps $(PROGS) test_build all_done +all: test_deps $(PROGS) all_done test_deps: ifndef AFL_TRACE_PC @@ -94,18 +95,7 @@ endif @printf "[*] Building 64-bit variant of the runtime (-m64)... " @$(CC) $(CFLAGS) -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi -test_build: $(PROGS) - @echo "[*] Testing the CC wrapper and instrumentation output..." - unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) -# Use /dev/null to avoid problems with optimization messing up expected -# branches. See https://github.com/google/AFL/issues/30. - ../afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null - echo 1 | ../afl-showmap -m none -q -o .test-instr1 ./test-instr - @rm -f test-instr - @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping to troubleshoot the issue."; echo; exit 1; fi - @echo "[+] All right, the instrumentation seems to be working!" - -all_done: test_build +all_done: @echo "[+] All done! You can now use '../afl-clang-fast' to compile programs." .NOTPARALLEL: clean diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 154a5db..0bfbfdf 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -105,7 +105,8 @@ bool AFLCoverage::runOnModule(Module &M) { GlobalVariable *AFLMapPtr = new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, - GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); + GlobalVariable::ExternalLinkage, 0, "__afl_area_ptr", + 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); GlobalVariable *AFLPrevLoc = new GlobalVariable( M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 60475c9..536adb9 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -41,6 +41,10 @@ #include #include #include +#include + +#define gettid() ((pid_t)syscall(SYS_gettid)) + /* This is a somewhat ugly hack for the experimental 'trace-pc-guard' mode. Basically, we need to make sure that the forkserver is initialized after @@ -53,12 +57,23 @@ #endif /* ^USE_TRACE_PC */ +void enable_afl_tracing(void); +void disable_afl_tracing(void); +void init_afl_tracing(void); + + /* 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. It will end up as .comm, so it shouldn't be too wasteful. */ +#define FIREFOX_CONTROL_AREA_ADDR 0x100000 + +u8*** __firefox_afl_control_areas = NULL; + u8 __afl_area_initial[MAP_SIZE]; -u8* __afl_area_ptr = __afl_area_initial; +__thread u8* __afl_area_ptr = __afl_area_initial; + +u8* __afl_area_ptr_pre = __afl_area_initial; __thread u32 __afl_prev_loc; @@ -82,17 +97,15 @@ static void __afl_map_shm(void) { u32 shm_id = atoi(id_str); - __afl_area_ptr = shmat(shm_id, NULL, 0); + __afl_area_ptr_pre = shmat(shm_id, NULL, 0); /* Whooooops. */ - if (__afl_area_ptr == (void *)-1) _exit(1); + if (__afl_area_ptr_pre == (void *)-1) _exit(1); /* Write something into the bitmap so that even with low AFL_INST_RATIO, our parent doesn't give up on us. */ - __afl_area_ptr[0] = 1; - } } @@ -256,6 +269,16 @@ void __afl_manual_init(void) { __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { + __firefox_afl_control_areas = mmap((void*)FIREFOX_CONTROL_AREA_ADDR, 0x1000, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED , 0, 0); + if(__firefox_afl_control_areas == (void*)-1){ + exit(1); + } + + __firefox_afl_control_areas[0] = (u8**) enable_afl_tracing; + __firefox_afl_control_areas[1] = (u8**) disable_afl_tracing; + __firefox_afl_control_areas[2] = (u8**) init_afl_tracing; + __firefox_afl_control_areas[3] = (u8**) 1337; + is_persistent = !!getenv(PERSIST_ENV_VAR); if (getenv(DEFER_ENV_VAR)) return; @@ -310,5 +333,55 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t* start, uint32_t* stop) { start++; } +} + +void enable_afl_tracing(void){ + if(__afl_area_ptr == __afl_area_initial && __afl_area_ptr_pre != __afl_area_initial){ + __afl_area_ptr = __afl_area_ptr_pre; + } +} + +void disable_afl_tracing(void){ + if(__afl_area_ptr != __afl_area_initial){ + __afl_area_ptr = __afl_area_initial; + } +} + +void init_afl_tracing(){ + __afl_area_ptr_pre[0] = 1; +} + +void print_afl_bitmap(void){ + if(__afl_area_ptr_pre == __afl_area_initial){ + return; + } + void* data = __afl_area_ptr_pre; + int size = 2 << 15; + char ascii[17]; + size_t i, j; + ascii[16] = '\0'; + for (i = 0; i < size; ++i) { + printf("%02X ", ((unsigned char*)data)[i]); + if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') { + ascii[i % 16] = ((unsigned char*)data)[i]; + } else { + ascii[i % 16] = '.'; + } + if ((i+1) % 8 == 0 || i+1 == size) { + printf(" "); + if ((i+1) % 16 == 0) { + printf("| %s \n", ascii); + } else if (i+1 == size) { + ascii[(i+1) % 16] = '\0'; + if ((i+1) % 16 <= 8) { + printf(" "); + } + for (j = (i+1) % 16; j < 16; ++j) { + printf(" "); + } + printf("| %s \n", ascii); + } + } + } } -- 2.37.1 From 003221dd9fec462177445040c7fa57c09397c684 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Fri, 15 Oct 2021 11:55:02 +0200 Subject: [PATCH 02/10] [compiler] Add selective instrumentation through AFL_INST_FILTER --- llvm_mode/afl-clang-fast.c | 57 +++++++++++++++++++++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index c154e01..b5aa521 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -29,6 +29,9 @@ */ #define AFL_MAIN +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif #include "../config.h" #include "../types.h" @@ -39,6 +42,7 @@ #include #include #include +#include static u8* obj_path; /* Path to runtime libraries */ static u8** cc_params; /* Parameters passed to the real CC */ @@ -119,13 +123,63 @@ static void edit_params(u32 argc, char** argv) { cc_params[0] = alt_cc ? alt_cc : (u8*)"clang"; } +#define CPP_SUFF ".cpp" +#define CPP_SLEN (sizeof(CPP_SUFF)-1) +#define C_SUFF ".c" +#define C_SLEN (sizeof(C_SUFF)-1) + u8 should_instrument = 1; + + u8* instfilter = getenv("AFL_INST_FILTER"); + + if (instfilter) { + + should_instrument = 0; + + char cwd [PATH_MAX]; + getcwd(cwd, sizeof(cwd)); + + for (u32 argi = 0; argi < argc; ++argi) { + u8 is_source = 0; + u32 arglen = strlen(argv[argi]); + //SAYF("Checking: %s\n", argv[argi]); + if (arglen > CPP_SLEN) { + if (!memcmp(argv[argi] + arglen - CPP_SLEN, CPP_SUFF, CPP_SLEN)) { + is_source = 1; + } + } + + if (!is_source && arglen > C_SLEN) { + if (!memcmp(argv[argi] + arglen - C_SLEN, C_SUFF, C_SLEN)) { + is_source = 1; + } + } + + if (is_source) { + //SAYF("This is a source file: %s\n", argv[argi]); + char relpath [PATH_MAX]; + strcat(relpath, cwd); + strcat(relpath, "/"); + strcat(relpath, argv[argi]); + char abspath [PATH_MAX]; + if (realpath(relpath, abspath)) { + if (strcasestr(abspath, instfilter)) { + should_instrument = 1; + SAYF("Instrumenting file %s\n", argv[argi]); + break; + } + } + } + } + + } + /* 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-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-with-guards */ - +if (should_instrument) { #ifdef USE_TRACE_PC cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; cc_params[cc_par_cnt++] = "-mllvm"; @@ -136,6 +190,7 @@ static void edit_params(u32 argc, char** argv) { cc_params[cc_par_cnt++] = "-Xclang"; cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); #endif /* ^USE_TRACE_PC */ +} cc_params[cc_par_cnt++] = "-Qunused-arguments"; -- 2.37.1 From 3e126e0f9bf21c32cb650d49f5f088b213538854 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Tue, 22 Feb 2022 16:44:27 +0100 Subject: [PATCH 03/10] Fix AFL compiler to ignore wasm-compiled code --- llvm_mode/afl-clang-fast.c | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 226ee36..6d4171c 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -213,6 +213,7 @@ if (should_instrument) { if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; if (!strcmp(cur, "-shared")) maybe_linking = 0; + if (!strcmp(cur, "--target=wasm32-wasi")) maybe_linking = 0; if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined")) continue; -- 2.37.1 From e2e269e9d00b47cc6a139045688f32b26d30fc85 Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Thu, 9 Jun 2022 10:20:34 +0200 Subject: [PATCH 04/10] Update IRBuilder calls to LLVM 14 API --- llvm_mode/afl-llvm-pass.so.cc | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 0bfbfdf..203cffa 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -38,12 +38,14 @@ #include #include +#include "llvm/Pass.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" #include "llvm/Support/Debug.h" #include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/Passes/OptimizationLevel.h" using namespace llvm; @@ -132,20 +134,20 @@ bool AFLCoverage::runOnModule(Module &M) { /* Load prev_loc */ - LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc); + LoadInst *PrevLoc = IRB.CreateLoad(IRB.getInt32Ty(), AFLPrevLoc); PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Value *PrevLocCasted = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty()); /* Load SHM pointer */ - LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + LoadInst *MapPtr = IRB.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr); MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Value *MapPtrIdx = - IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocCasted, CurLoc)); + IRB.CreateGEP(Int8Ty, MapPtr, IRB.CreateXor(PrevLocCasted, CurLoc)); /* Update bitmap */ - LoadInst *Counter = IRB.CreateLoad(MapPtrIdx); + LoadInst *Counter = IRB.CreateLoad(IRB.getInt8Ty(), MapPtrIdx); Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None)); Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1)); IRB.CreateStore(Incr, MapPtrIdx) -- 2.37.1 From be3f79c5b472e5a8a06266d7a74ebb162b3d8cba Mon Sep 17 00:00:00 2001 From: "Christian Holler (:decoder)" Date: Thu, 9 Jun 2022 11:37:44 +0200 Subject: [PATCH 05/10] Switch AFLCoverage pass to new pass manager --- llvm_mode/afl-clang-fast.c | 7 ++--- llvm_mode/afl-llvm-pass.so.cc | 58 +++++++++++++++++------------------ 2 files changed, 31 insertions(+), 34 deletions(-) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 6d4171c..5e00286 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -178,14 +178,12 @@ static void edit_params(u32 argc, char** argv) { http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards */ if (should_instrument) { #ifdef USE_TRACE_PC + #error "unsupported" cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; cc_params[cc_par_cnt++] = "-mllvm"; cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; #else - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-pass.so", obj_path); + cc_params[cc_par_cnt++] = alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); #endif /* ^USE_TRACE_PC */ } diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 203cffa..1483943 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -41,44 +41,57 @@ #include "llvm/Pass.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" -#include "llvm/IR/LegacyPassManager.h" #include "llvm/IR/Module.h" -#include "llvm/Support/Debug.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/IR/PassManager.h" #include "llvm/Passes/OptimizationLevel.h" +#include "llvm/Passes/PassPlugin.h" +#include "llvm/Passes/PassBuilder.h" +#include "llvm/Support/Debug.h" using namespace llvm; namespace { - class AFLCoverage : public ModulePass { + class AFLCoverage : public PassInfoMixin { public: - static char ID; - AFLCoverage() : ModulePass(ID) { } - - bool runOnModule(Module &M) override; - - // StringRef getPassName() const override { - // return "American Fuzzy Lop Instrumentation"; - // } + AFLCoverage() { } + PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM); }; } +extern "C" ::llvm::PassPluginLibraryInfo LLVM_ATTRIBUTE_WEAK +llvmGetPassPluginInfo() { + + return {LLVM_PLUGIN_API_VERSION, "AFLCoverage", "v0.1", + /* lambda to insert our pass into the pass pipeline. */ + [](PassBuilder &PB) { -char AFLCoverage::ID = 0; + #if LLVM_VERSION_MAJOR <= 13 + using OptimizationLevel = typename PassBuilder::OptimizationLevel; + #endif + PB.registerOptimizerLastEPCallback( + [](ModulePassManager &MPM, OptimizationLevel OL) { + MPM.addPass(AFLCoverage()); -bool AFLCoverage::runOnModule(Module &M) { + }); + }}; + +} + +PreservedAnalyses AFLCoverage::run(Module &M, ModuleAnalysisManager &MAM) { LLVMContext &C = M.getContext(); IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int32Ty = IntegerType::getInt32Ty(C); + auto PA = PreservedAnalyses::all(); + /* Show a banner */ char be_quiet = 0; @@ -175,21 +188,6 @@ bool AFLCoverage::runOnModule(Module &M) { } - return true; + return PA; } - - -static void registerAFLPass(const PassManagerBuilder &, - legacy::PassManagerBase &PM) { - - PM.add(new AFLCoverage()); - -} - - -static RegisterStandardPasses RegisterAFLPass( - PassManagerBuilder::EP_ModuleOptimizerEarly, registerAFLPass); - -static RegisterStandardPasses RegisterAFLPass0( - PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass); -- 2.37.1 From bd47b9066e616fdfdad1808ec0365992a4962ff2 Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Tue, 9 Aug 2022 17:18:15 -0400 Subject: [PATCH 06/10] Add install step for afl-clang-fast only --- llvm_mode/Makefile | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index 823e959..b155eb5 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -103,3 +103,13 @@ all_done: clean: rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 rm -f $(PROGS) ../afl-clang-fast++ + +install: all + mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) +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 -- 2.37.1 From 11f8b04786239bc8daa2c7a207b5e19f5c19ec6e Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Thu, 11 Aug 2022 11:39:37 -0400 Subject: [PATCH 07/10] Reenable instrumentation tests --- config.h | 4 ++++ llvm_mode/Makefile | 15 +++++++++++++-- llvm_mode/afl-llvm-rt.o.c | 1 + 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/config.h b/config.h index b21298d..c035af2 100644 --- a/config.h +++ b/config.h @@ -285,6 +285,10 @@ #define PERSIST_ENV_VAR "__AFL_PERSISTENT" #define DEFER_ENV_VAR "__AFL_DEFER_FORKSRV" +/* Enable tracing by default at startup */ + +#define TRACE_ENV_VAR "__AFL_ENABLE_TRACE" + /* In-code signatures for deferred and persistent mode. */ #define PERSIST_SIG "##SIG_AFL_PERSISTENT##" diff --git a/llvm_mode/Makefile b/llvm_mode/Makefile index b155eb5..4f460ff 100644 --- a/llvm_mode/Makefile +++ b/llvm_mode/Makefile @@ -62,7 +62,7 @@ else PROGS = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o endif -all: test_deps $(PROGS) all_done +all: test_deps $(PROGS) test_build all_done test_deps: ifndef AFL_TRACE_PC @@ -95,7 +95,18 @@ endif @printf "[*] Building 64-bit variant of the runtime (-m64)... " @$(CC) $(CFLAGS) -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi -all_done: +test_build: $(PROGS) + @echo "[*] Testing the CC wrapper and instrumentation output..." + unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) ../afl-clang-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS) +# Use /dev/null to avoid problems with optimization messing up expected +# branches. See https://github.com/google/AFL/issues/30. + __AFL_ENABLE_TRACE=1 ../afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null + echo 1 | __AFL_ENABLE_TRACE=1 ../afl-showmap -m none -q -o .test-instr1 ./test-instr + @rm -f test-instr + @cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please ping to troubleshoot the issue."; echo; exit 1; fi + @echo "[+] All right, the instrumentation seems to be working!" + +all_done: test_build @echo "[+] All done! You can now use '../afl-clang-fast' to compile programs." .NOTPARALLEL: clean diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 536adb9..c3b710f 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -285,6 +285,7 @@ __attribute__((constructor(CONST_PRIO))) void __afl_auto_init(void) { __afl_manual_init(); + if (getenv(TRACE_ENV_VAR)) enable_afl_tracing(); } -- 2.37.1 From dd1050393281f2ea4c9b6521f5e48bec365b0a8a Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Thu, 11 Aug 2022 13:17:34 -0400 Subject: [PATCH 08/10] Add search in HELPER_PATH for libraries. --- llvm_mode/afl-clang-fast.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 5e00286..70b6af2 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -85,6 +85,16 @@ static void find_obj(u8* argv0) { return; } + ck_free(tmp); + tmp = alloc_printf("%s/../lib/afl/afl-llvm-rt.o", dir); + + if (!access(tmp, R_OK)) { + ck_free(tmp); + obj_path = alloc_printf("%s/../lib/afl", dir); + ck_free(dir); + return; + } + ck_free(tmp); ck_free(dir); -- 2.37.1 From 9eb9eaf26d473bb8479df380f918a1bf83250029 Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Thu, 11 Aug 2022 19:16:36 -0400 Subject: [PATCH 09/10] Don't instrument at all for wasm --- llvm_mode/afl-clang-fast.c | 41 ++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 70b6af2..0d1e76b 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -180,23 +180,6 @@ 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-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-with-guards */ -if (should_instrument) { -#ifdef USE_TRACE_PC - #error "unsupported" - cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; - cc_params[cc_par_cnt++] = "-mllvm"; - cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; -#else - cc_params[cc_par_cnt++] = alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); -#endif /* ^USE_TRACE_PC */ -} - cc_params[cc_par_cnt++] = "-Qunused-arguments"; /* Detect stray -v calls from ./configure scripts. */ @@ -222,7 +204,10 @@ if (should_instrument) { if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; if (!strcmp(cur, "-shared")) maybe_linking = 0; - if (!strcmp(cur, "--target=wasm32-wasi")) maybe_linking = 0; + if (!strcmp(cur, "--target=wasm32-wasi")) { + maybe_linking = 0; + should_instrument = 0; + } if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined")) continue; @@ -231,6 +216,23 @@ if (should_instrument) { } + /* 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-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-with-guards */ + if (should_instrument) { +#ifdef USE_TRACE_PC + #error "unsupported" + cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard"; + cc_params[cc_par_cnt++] = "-mllvm"; + cc_params[cc_par_cnt++] = "-sanitizer-coverage-block-threshold=0"; +#else + cc_params[cc_par_cnt++] = alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path); +#endif /* ^USE_TRACE_PC */ + } + if (getenv("AFL_HARDEN")) { cc_params[cc_par_cnt++] = "-fstack-protector-all"; -- 2.37.1 From 6ea1771e95d6f4c19453047996b0fc4ffa3fdeda Mon Sep 17 00:00:00 2001 From: Jesse Schwartzentruber Date: Wed, 20 Apr 2022 15:39:28 -0400 Subject: [PATCH 10/10] fix instrumentation for -Werror,-Wunused-but-set-variable `used` is so it isn't optimized out. `unused` is to avoid the warning. --- llvm_mode/afl-clang-fast.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 0d1e76b..3bc0daa 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -321,7 +321,7 @@ static void edit_params(u32 argc, char** argv) { */ cc_params[cc_par_cnt++] = "-D__AFL_LOOP(_A)=" - "({ static volatile char *_B __attribute__((used)); " + "({ static volatile char *_B __attribute__((used,unused)); " " _B = (char*)\"" PERSIST_SIG "\"; " #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " @@ -333,7 +333,7 @@ static void edit_params(u32 argc, char** argv) { "_L(_A); })"; cc_params[cc_par_cnt++] = "-D__AFL_INIT()=" - "do { static volatile char *_A __attribute__((used)); " + "do { static volatile char *_A __attribute__((used,unused)); " " _A = (char*)\"" DEFER_SIG "\"; " #ifdef __APPLE__ "__attribute__((visibility(\"default\"))) " -- 2.37.1 From 0884906de0cdd007b28b15aae35cee484d1bc31d Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 6 Sep 2022 11:08:55 +0900 Subject: [PATCH] Fix build failures with clang 15 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 5e800db..c875f2d 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ ifndef AFL_NO_X86 test_x86: @echo "[*] Checking for the ability to compile x86 code..." - @echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 ) + @echo 'int main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 ) @rm -f .test @echo "[+] Everything seems to be working, ready to compile." -- 2.37.1.1.g659da70093 From 0544d02715a26a032f109984d5f70360b80f3875 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Wed, 14 Dec 2022 16:25:53 +0900 Subject: [PATCH] Add missing include --- llvm_mode/afl-llvm-pass.so.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 1483943..0a7c37a 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -39,6 +39,7 @@ #include #include "llvm/Pass.h" +#include "llvm/ADT/None.h" #include "llvm/ADT/Statistic.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Module.h" -- 2.38.1.1.g6d9df9d320