From 6d364dd2cb0ac31797b52e590b57bf9c10cc2302 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 5 Aug 2020 01:13:51 +0200 Subject: add sancov-like allow/denylist instrument feature --- docs/Changelog.md | 4 ++++ docs/FAQ.md | 2 +- docs/env_variables.md | 11 ++++++----- docs/perf_tips.md | 2 +- 4 files changed, 12 insertions(+), 7 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index ae7377f2..f98f8b9b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -22,6 +22,10 @@ sending a mail to . - fixed a bug in redqueen for strings - llvm_mode: - now supports llvm 12! + - support for AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST (previous + AFL_LLVM_WHITELIST and AFL_LLVM_INSTRUMENT_FILE are deprecated and + are matched to AFL_LLVM_ALLOWLIST). The format is compatible to llvm + sancov, and also supports function matching! - fixes for laf-intel float splitting (thanks to mark-griffin for reporting) - LTO: autodictionary mode is a default diff --git a/docs/FAQ.md b/docs/FAQ.md index c15cd484..33ce49e6 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -117,7 +117,7 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation! Identify which source code files contain the functions that you need to remove from instrumentation. - Simply follow this document on how to do this: [llvm_mode/README.instrument_file.md](llvm_mode/README.instrument_file.md) + Simply follow this document on how to do this: [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md) If PCGUARD is used, then you need to follow this guide (needs llvm 12+!): [http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation](http://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation) diff --git a/docs/env_variables.md b/docs/env_variables.md index 811c5658..f0ae0b6c 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -202,14 +202,15 @@ Then there are a few specific features that are only available in llvm_mode: See llvm_mode/README.laf-intel.md for more information. -### INSTRUMENT_FILE +### INSTRUMENT LIST (selectively instrument files and functions) This feature allows selectively instrumentation of the source - - Setting AFL_LLVM_INSTRUMENT_FILE with a filename will only instrument those - files that match the names listed in this file. + - Setting AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST with a filenames and/or + function will only instrument (or skip) those files that match the names + listed in the specified file. - See llvm_mode/README.instrument_file.md for more information. + See llvm_mode/README.instrument_list.md for more information. ### NOT_ZERO @@ -241,7 +242,7 @@ Then there are a few specific features that are only available in the gcc_plugin - Setting AFL_GCC_INSTRUMENT_FILE with a filename will only instrument those files that match the names listed in this file (one filename per line). - See gcc_plugin/README.instrument_file.md for more information. + See gcc_plugin/README.instrument_list.md for more information. ## 3) Settings for afl-fuzz diff --git a/docs/perf_tips.md b/docs/perf_tips.md index 7a690b77..731dc238 100644 --- a/docs/perf_tips.md +++ b/docs/perf_tips.md @@ -67,7 +67,7 @@ to get to the important parts in the code. If you are only interested in specific parts of the code being fuzzed, you can instrument_files the files that are actually relevant. This improves the speed and -accuracy of afl. See llvm_mode/README.instrument_file.md +accuracy of afl. See llvm_mode/README.instrument_list.md Also use the InsTrim mode on larger binaries, this improves performance and coverage a lot. -- cgit 1.4.1 From 3d8f05458041d6007617e383453c7ad66b345144 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 5 Aug 2020 01:19:31 +0200 Subject: readme fix --- docs/FAQ.md | 5 ++- gcc_plugin/README.instrument_file.md | 73 ------------------------------------ gcc_plugin/README.instrument_list.md | 73 ++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 75 deletions(-) delete mode 100644 gcc_plugin/README.instrument_file.md create mode 100644 gcc_plugin/README.instrument_list.md (limited to 'docs') diff --git a/docs/FAQ.md b/docs/FAQ.md index 33ce49e6..e690635a 100644 --- a/docs/FAQ.md +++ b/docs/FAQ.md @@ -112,10 +112,11 @@ afl-clang-fast PCGUARD and afl-clang-lto LTO instrumentation! on start, check to which memory address the edge ID value is written and set a write breakpoint to that address (`watch 0x.....`). - 3. Third step: create a text file with the filenames + 3. Third step: create a text file with the filenames/functions Identify which source code files contain the functions that you need to - remove from instrumentation. + remove from instrumentation, or just specify the functions you want to + skip instrumenting. Note that optimization might inline functions! Simply follow this document on how to do this: [llvm_mode/README.instrument_list.md](llvm_mode/README.instrument_list.md) If PCGUARD is used, then you need to follow this guide (needs llvm 12+!): diff --git a/gcc_plugin/README.instrument_file.md b/gcc_plugin/README.instrument_file.md deleted file mode 100644 index d0eaf6ff..00000000 --- a/gcc_plugin/README.instrument_file.md +++ /dev/null @@ -1,73 +0,0 @@ -======================================== -Using afl++ with partial instrumentation -======================================== - - This file describes how you can selectively instrument only the source files - that are interesting to you using the gcc instrumentation provided by - afl++. - - Plugin by hexcoder-. - - -## 1) Description and purpose - -When building and testing complex programs where only a part of the program is -the fuzzing target, it often helps to only instrument the necessary parts of -the program, leaving the rest uninstrumented. This helps to focus the fuzzer -on the important parts of the program, avoiding undesired noise and -disturbance by uninteresting code being exercised. - -For this purpose, I have added a "partial instrumentation" support to the gcc -plugin of AFLFuzz that allows you to specify on a source file level which files -should be compiled with or without instrumentation. - - -## 2) Building the gcc plugin - -The new code is part of the existing afl++ gcc plugin in the gcc_plugin/ -subdirectory. There is nothing specifically to do :) - - -## 3) How to use the partial instrumentation mode - -In order to build with partial instrumentation, you need to build with -afl-gcc-fast and afl-g++-fast respectively. The only required change is -that you need to set the environment variable AFL_GCC_INSTRUMENT_FILE when calling -the compiler. - -The environment variable must point to a file containing all the filenames -that should be instrumented. For matching, the filename that is being compiled -must end in the filename entry contained in this instrument list (to avoid breaking -the matching when absolute paths are used during compilation). - -For example if your source tree looks like this: - -``` -project/ -project/feature_a/a1.cpp -project/feature_a/a2.cpp -project/feature_b/b1.cpp -project/feature_b/b2.cpp -``` - -and you only want to test feature_a, then create a instrument list file containing: - -``` -feature_a/a1.cpp -feature_a/a2.cpp -``` - -However if the instrument list file contains only this, it works as well: - -``` -a1.cpp -a2.cpp -``` - -but it might lead to files being unwantedly instrumented if the same filename -exists somewhere else in the project directories. - -The created instrument list file is then set to AFL_GCC_INSTRUMENT_FILE when you compile -your program. For each file that didn't match the instrument list, the compiler will -issue a warning at the end stating that no blocks were instrumented. If you -didn't intend to instrument that file, then you can safely ignore that warning. diff --git a/gcc_plugin/README.instrument_list.md b/gcc_plugin/README.instrument_list.md new file mode 100644 index 00000000..d0eaf6ff --- /dev/null +++ b/gcc_plugin/README.instrument_list.md @@ -0,0 +1,73 @@ +======================================== +Using afl++ with partial instrumentation +======================================== + + This file describes how you can selectively instrument only the source files + that are interesting to you using the gcc instrumentation provided by + afl++. + + Plugin by hexcoder-. + + +## 1) Description and purpose + +When building and testing complex programs where only a part of the program is +the fuzzing target, it often helps to only instrument the necessary parts of +the program, leaving the rest uninstrumented. This helps to focus the fuzzer +on the important parts of the program, avoiding undesired noise and +disturbance by uninteresting code being exercised. + +For this purpose, I have added a "partial instrumentation" support to the gcc +plugin of AFLFuzz that allows you to specify on a source file level which files +should be compiled with or without instrumentation. + + +## 2) Building the gcc plugin + +The new code is part of the existing afl++ gcc plugin in the gcc_plugin/ +subdirectory. There is nothing specifically to do :) + + +## 3) How to use the partial instrumentation mode + +In order to build with partial instrumentation, you need to build with +afl-gcc-fast and afl-g++-fast respectively. The only required change is +that you need to set the environment variable AFL_GCC_INSTRUMENT_FILE when calling +the compiler. + +The environment variable must point to a file containing all the filenames +that should be instrumented. For matching, the filename that is being compiled +must end in the filename entry contained in this instrument list (to avoid breaking +the matching when absolute paths are used during compilation). + +For example if your source tree looks like this: + +``` +project/ +project/feature_a/a1.cpp +project/feature_a/a2.cpp +project/feature_b/b1.cpp +project/feature_b/b2.cpp +``` + +and you only want to test feature_a, then create a instrument list file containing: + +``` +feature_a/a1.cpp +feature_a/a2.cpp +``` + +However if the instrument list file contains only this, it works as well: + +``` +a1.cpp +a2.cpp +``` + +but it might lead to files being unwantedly instrumented if the same filename +exists somewhere else in the project directories. + +The created instrument list file is then set to AFL_GCC_INSTRUMENT_FILE when you compile +your program. For each file that didn't match the instrument list, the compiler will +issue a warning at the end stating that no blocks were instrumented. If you +didn't intend to instrument that file, then you can safely ignore that warning. -- cgit 1.4.1 From 4a6d66d8c5dcbec8b5014ff0445d9292b3958e1d Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 7 Aug 2020 14:43:17 +0200 Subject: fix typos --- docs/Changelog.md | 1 + llvm_mode/README.instrument_list.md | 2 +- llvm_mode/README.persistent_mode.md | 3 ++- 3 files changed, 4 insertions(+), 2 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index f98f8b9b..f8742b1c 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -37,6 +37,7 @@ sending a mail to . - LTO: AFL_LLVM_SKIP_NEVERZERO behaviour was inversed, fixed - setting AFL_LLVM_LAF_SPLIT_FLOATS now activates AFL_LLVM_LAF_SPLIT_COMPARES + - support for -E and -shared compilation runs - added honggfuzz mangle as a custom mutator in custom_mutators/honggfuzz - added afl-frida gum solution to examples/afl_frida (mostly imported from https://github.com/meme/hotwax/) diff --git a/llvm_mode/README.instrument_list.md b/llvm_mode/README.instrument_list.md index b0e0cc1e..d4739dda 100644 --- a/llvm_mode/README.instrument_list.md +++ b/llvm_mode/README.instrument_list.md @@ -71,7 +71,7 @@ must be mangled to match! afl++ is intelligent to identify if an entry is a filename or a function. However if you want to be sure (and compliant to the sancov allow/blocklist -format), you can file entries like this: +format), you can specify source file entries like this: ``` src: *malloc.c ``` diff --git a/llvm_mode/README.persistent_mode.md b/llvm_mode/README.persistent_mode.md index 5ed59a58..7d2fd93b 100644 --- a/llvm_mode/README.persistent_mode.md +++ b/llvm_mode/README.persistent_mode.md @@ -125,7 +125,7 @@ Add after the includes: extern unsigned char *__afl_area_ptr; #define MAX_DUMMY_SIZE 256000 -__attribute__((constructor(10))) void __afl_protect(void) { +__attribute__((constructor(1))) void __afl_protect(void) { #ifdef MAP_FIXED_NOREPLACE __afl_area_ptr = (unsigned char*) mmap((void *)0x10000, MAX_DUMMY_SIZE, PROT_READ | PROT_WRITE, MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); if ((uint64_t)__afl_area_ptr == -1) @@ -139,6 +139,7 @@ __attribute__((constructor(10))) void __afl_protect(void) { and just before `__AFL_INIT()`: ``` munmap(__afl_area_ptr, MAX_DUMMY_SIZE); + __afl_area_ptr = NULL; ``` ## 4) persistent mode -- cgit 1.4.1 From 701fb95d24cd754e9c116d81502b6057a29eb2bd Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 10 Aug 2020 23:42:33 +0200 Subject: LTO: make dynamic map the default --- docs/Changelog.md | 2 ++ llvm_mode/README.lto.md | 20 ++++------------- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 33 +++++++++++++++++++++++----- src/afl-forkserver.c | 13 +++++------ 4 files changed, 40 insertions(+), 28 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index f8742b1c..182a15b8 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -28,6 +28,8 @@ sending a mail to . sancov, and also supports function matching! - fixes for laf-intel float splitting (thanks to mark-griffin for reporting) + - LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR + for a fixed map address (eg. 0x10000) - LTO: autodictionary mode is a default - LTO: instrim instrumentation disabled, only classic support used as it is always better diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 4d643324..9046c5a8 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -17,9 +17,6 @@ This version requires a current llvm 11+ compiled from the github master. 5. If any problems arise be sure to set `AR=llvm-ar RANLIB=llvm-ranlib`. Some targets might need `LD=afl-clang-lto` and others `LD=afl-ld-lto`. -6. If a target uses _init functions or early constructors then additionally - set `AFL_LLVM_MAP_DYNAMIC=1` as your target will crash otherwise! - ## Introduction and problem description A big issue with how afl/afl++ works is that the basic block IDs that are @@ -128,14 +125,14 @@ on start. This improves coverage statistically by 5-10% :) ## Fixed memory map -To speed up fuzzing, the shared memory map is hard set to a specific address, -by default 0x10000. In most cases this will work without any problems. +To speed up fuzzing, it is possible to set a fixed shared memory map. +Recommened is the value 0x10000. +In most cases this will work without any problems. However if a target uses +early constructors, ifuncs or a deferred forkserver this can crash the target. On unusual operating systems/processors/kernels or weird libraries this might fail so to change the fixed address at compile time set AFL_LLVM_MAP_ADDR with a better value (a value of 0 or empty sets the map address to be dynamic - the original afl way, which is slower). -AFL_LLVM_MAP_DYNAMIC can be set so the shared memory address is dynamic (which -is safer but also slower). ## Document edge IDs @@ -262,15 +259,6 @@ If this succeeeds then there is an issue with afl-clang-lto. Please report at Even some targets where clang-12 fails can be build if the fail is just in `./configure`, see `Solving difficult targets` above. -### Target crashes immediately - -If the target is using early constructors (priority values smaller than 6) -or have their own _init/.init functions and these are instrumented then the -target will likely crash when started. This can be avoided by compiling with -`AFL_LLVM_MAP_DYNAMIC=1` . - -This can e.g. happen with OpenSSL. - ## History This was originally envisioned by hexcoder- in Summer 2019, however we saw no diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index 38c3f202..ddfcb400 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -49,6 +49,7 @@ #include "llvm/Analysis/MemorySSAUpdater.h" #include "llvm/Analysis/ValueTracking.h" #include "llvm/Pass.h" +#include "llvm/IR/Constants.h" #include "afl-llvm-common.h" @@ -135,7 +136,10 @@ bool AFLLTOPass::runOnModule(Module &M) { if (getenv("AFL_LLVM_LTO_AUTODICTIONARY")) autodictionary = 1; - if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0; + // we make this the default as the fixed map has problems with + // defered forkserver, early constructors, ifuncs and maybe more + /*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/ + map_addr = 0; if (getenv("AFL_LLVM_SKIPSINGLEBLOCK")) function_minimum_size = 2; @@ -196,7 +200,8 @@ bool AFLLTOPass::runOnModule(Module &M) { ConstantInt *Zero = ConstantInt::get(Int8Ty, 0); ConstantInt *One = ConstantInt::get(Int8Ty, 1); - /* This dumps all inialized global strings - might be useful in the future + // This dumps all inialized global strings - might be useful in the future + /* for (auto G=M.getGlobalList().begin(); G!=M.getGlobalList().end(); G++) { GlobalVariable &GV=*G; @@ -212,7 +217,21 @@ bool AFLLTOPass::runOnModule(Module &M) { } - */ + */ + + if (map_addr) + for (GlobalIFunc &IF : M.ifuncs()) { + + // No clue how to follow these up and find the resolver function. + // If we would know that resolver function name we could just skip + // instrumenting it and everything would be fine :-( + // StringRef ifunc_name = IF.getName(); + // Constant *r = IF.getResolver(); + FATAL( + "Target uses ifunc attribute, dynamic map cannot be used, remove " + "AFL_LLVM_MAP_DYNAMIC"); + + } /* Instrument all the things! */ @@ -220,8 +239,12 @@ bool AFLLTOPass::runOnModule(Module &M) { for (auto &F : M) { - // fprintf(stderr, "DEBUG: Module %s Function %s\n", - // M.getName().str().c_str(), F.getName().str().c_str()); + /*For debugging + AttributeSet X = F.getAttributes().getFnAttributes(); + fprintf(stderr, "DEBUG: Module %s Function %s attributes %u\n", + M.getName().str().c_str(), F.getName().str().c_str(), + X.getNumAttributes()); + */ if (F.size() < function_minimum_size) continue; if (isIgnoreFunction(&F)) continue; diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 752641d7..1ececf27 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -293,8 +293,8 @@ static void report_error_and_exit(int error) { FATAL( "the fuzzing target reports that hardcoded map address might be the " "reason the mmap of the shared memory failed. Solution: recompile " - "the target with either afl-clang-lto and the environment variable " - "AFL_LLVM_MAP_DYNAMIC set or recompile with afl-clang-fast."); + "the target with either afl-clang-lto and do not set " + "AFL_LLVM_MAP_ADDR or recompile with afl-clang-fast."); break; case FS_ERROR_SHM_OPEN: FATAL("the fuzzing target reports that the shm_open() call failed."); @@ -828,8 +828,8 @@ 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" - "If the target was compiled with afl-clang-lto then recompiling with" - " AFL_LLVM_MAP_DYNAMIC might solve your problem.\n" + "If the target was compiled with afl-clang-lto and AFL_LLVM_MAP_ADDR" + " then recompiling without this parameter.\n" "Otherwise there is a horrible bug in the fuzzer.\n" "Poke for troubleshooting tips.\n"); @@ -860,9 +860,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, " - the target was compiled with afl-clang-lto and a constructor " "was\n" - " instrumented, recompiling with AFL_LLVM_MAP_DYNAMIC might solve " - "your\n" - " problem\n\n" + " instrumented, recompiling without AFL_LLVM_MAP_ADDR might solve " + "your problem\n\n" " - Less likely, there is a horrible bug in the fuzzer. If other " "options\n" -- cgit 1.4.1 From 50e76fce123f01ec83024f3bbd3190f2e1a6d387 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Tue, 11 Aug 2020 02:05:39 +0200 Subject: adding ctor function skipping in LTO fixed map mode --- docs/Changelog.md | 1 + include/debug.h | 52 +++++++++---------- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 76 +++++++++++++++++++++++----- 3 files changed, 90 insertions(+), 39 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 182a15b8..25c7a761 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -30,6 +30,7 @@ sending a mail to . reporting) - LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR for a fixed map address (eg. 0x10000) + - LTO: skipping ctors and ifuncs in fix map address instrumentation - LTO: autodictionary mode is a default - LTO: instrim instrumentation disabled, only classic support used as it is always better diff --git a/include/debug.h b/include/debug.h index 6cc26ec2..f9ebce58 100644 --- a/include/debug.h +++ b/include/debug.h @@ -218,43 +218,43 @@ /* Die with a verbose non-OS fatal error message. */ -#define FATAL(x...) \ - do { \ - \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] PROGRAM ABORT : " cRST x); \ +#define FATAL(x...) \ + do { \ + \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ + "\n[-] PROGRAM ABORT : " cRST x); \ SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \ - __FILE__, __LINE__); \ - exit(1); \ - \ + __FILE__, __LINE__); \ + exit(1); \ + \ } while (0) /* Die by calling abort() to provide a core dump. */ -#define ABORT(x...) \ - do { \ - \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] PROGRAM ABORT : " cRST x); \ +#define ABORT(x...) \ + do { \ + \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ + "\n[-] PROGRAM ABORT : " cRST x); \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \ - __FILE__, __LINE__); \ - abort(); \ - \ + __FILE__, __LINE__); \ + abort(); \ + \ } while (0) /* Die while also including the output of perror(). */ -#define PFATAL(x...) \ - do { \ - \ - fflush(stdout); \ - SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ - "\n[-] SYSTEM ERROR : " cRST x); \ +#define PFATAL(x...) \ + do { \ + \ + fflush(stdout); \ + SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \ + "\n[-] SYSTEM ERROR : " cRST x); \ SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \ - __FILE__, __LINE__); \ - SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ - exit(1); \ - \ + __FILE__, __LINE__); \ + SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \ + exit(1); \ + \ } while (0) /* Die with FATAL() or PFATAL() depending on the value of res (used to diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index abc836aa..fd8e48a7 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -224,22 +224,70 @@ bool AFLLTOPass::runOnModule(Module &M) { if (map_addr) { for (GlobalIFunc &IF : M.ifuncs()) { - + StringRef ifunc_name = IF.getName(); Constant *r = IF.getResolver(); StringRef r_name = cast(r->getOperand(0))->getName(); if (!be_quiet) - fprintf(stderr, "Found an ifunc with name %s that points to resolver function %s, we cannot instrument this, putting it into a block list.\n", + fprintf(stderr, + "Warning: Found an ifunc with name %s that points to resolver " + "function %s, we cannot instrument this, putting it into a " + "block list.\n", ifunc_name.str().c_str(), r_name.str().c_str()); - module_block_list.push_back(r_name.str()); } - // next up: ctors run before __afl_init() - - // TODO + GlobalVariable *GV = M.getNamedGlobal("llvm.global_ctors"); + if (GV && !GV->isDeclaration() && !GV->hasLocalLinkage()) { + + ConstantArray *InitList = dyn_cast(GV->getInitializer()); + + if (InitList) { + + for (unsigned i = 0, e = InitList->getNumOperands(); i != e; ++i) { + + if (ConstantStruct *CS = + dyn_cast(InitList->getOperand(i))) { + + if (CS->getNumOperands() >= 2) { + if (CS->getOperand(1)->isNullValue()) + break; // Found a null terminator, stop here. + + ConstantInt *CI = dyn_cast(CS->getOperand(0)); + int Priority = CI ? CI->getSExtValue() : 0; + + Constant *FP = CS->getOperand(1); + if (ConstantExpr *CE = dyn_cast(FP)) + if (CE->isCast()) FP = CE->getOperand(0); + if (Function *F = dyn_cast(FP)) { + + if (!F->isDeclaration() && + strncmp(F->getName().str().c_str(), "__afl", 5) != 0 && + Priority <= 5) { + + if (!be_quiet) + fprintf(stderr, + "Warning: Found constructor function %s with prio " + "%u, we cannot instrument this, putting it into a " + "block list.\n", + F->getName().str().c_str(), Priority); + module_block_list.push_back(F->getName().str()); + + } + + } + + } + + } + + } + + } + + } } @@ -260,21 +308,23 @@ bool AFLLTOPass::runOnModule(Module &M) { if (isIgnoreFunction(&F)) continue; if (module_block_list.size()) { - + for (auto bname : module_block_list) { std::string fname = F.getName().str(); if (fname.compare(bname) == 0) { - + if (!be_quiet) - WARNF("Skipping instrumentation of ifunc resolver function %s", - fname.c_str()); - + WARNF( + "Skipping instrumentation of dangerous early running function " + "%s", + fname.c_str()); + } - + } - + } // the instrument file list check -- cgit 1.4.1 From 132b57cf030fd206bc54d6c810868c48b17445bb Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 12 Aug 2020 10:41:09 +0200 Subject: nozero for llvm pcguard --- docs/Changelog.md | 1 + llvm_mode/afl-llvm-rt.o.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index 25c7a761..eda57a1a 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,6 +26,7 @@ sending a mail to . AFL_LLVM_WHITELIST and AFL_LLVM_INSTRUMENT_FILE are deprecated and are matched to AFL_LLVM_ALLOWLIST). The format is compatible to llvm sancov, and also supports function matching! + - added nozero counting to trace-pc/pcgard - fixes for laf-intel float splitting (thanks to mark-griffin for reporting) - LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 623e3a20..8a073318 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -904,7 +904,7 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) { */ - __afl_area_ptr[*guard]++; + __afl_area_ptr[*guard] = __afl_area_ptr[*guard] + 1 + (__afl_area_ptr[*guard] == 255 ? 1 : 0); } -- cgit 1.4.1 From b38837f4ff8f2e52597b7908b9226500e5c61933 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 12 Aug 2020 14:14:44 +0200 Subject: setting attribute hot intelligently gives 0.5% speed --- docs/Changelog.md | 2 +- src/afl-forkserver.c | 4 ++-- src/afl-fuzz-bitmap.c | 8 ++++---- src/afl-fuzz-run.c | 6 +++--- 4 files changed, 10 insertions(+), 10 deletions(-) (limited to 'docs') diff --git a/docs/Changelog.md b/docs/Changelog.md index eda57a1a..edcdac58 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -26,7 +26,7 @@ sending a mail to . AFL_LLVM_WHITELIST and AFL_LLVM_INSTRUMENT_FILE are deprecated and are matched to AFL_LLVM_ALLOWLIST). The format is compatible to llvm sancov, and also supports function matching! - - added nozero counting to trace-pc/pcgard + - added neverzero counting to trace-pc/pcgard - fixes for laf-intel float splitting (thanks to mark-griffin for reporting) - LTO: switch default to the dynamic memory map, set AFL_LLVM_MAP_ADDR diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 1ececf27..6819fc8a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -122,7 +122,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) { Returns the time passed to read. If the wait times out, returns timeout_ms + 1; Returns 0 if an error occurred (fd closed, signal, ...); */ -static u32 read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, +static u32 __attribute__ ((hot)) read_s32_timed(s32 fd, s32 *buf, u32 timeout_ms, volatile u8 *stop_soon_p) { fd_set readfds; @@ -322,7 +322,7 @@ static void report_error_and_exit(int error) { cloning a stopped child. So, we just execute once, and then send commands through a pipe. The other part of this logic is in afl-as.h / llvm_mode */ -void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, +void __attribute__ ((hot)) afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, volatile u8 *stop_soon_p, u8 debug_child_output) { int st_pipe[2], ctl_pipe[2]; diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index aa8d5a18..f6389c06 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -57,7 +57,7 @@ void write_bitmap(afl_state_t *afl) { This function is called after every exec() on a fairly large buffer, so it needs to be fast. We do this in 32-bit and 64-bit flavors. */ -u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { +u8 __attribute__ ((hot)) has_new_bits(afl_state_t *afl, u8 *virgin_map) { #ifdef WORD_SIZE_64 @@ -347,7 +347,7 @@ void init_count_class16(void) { #ifdef WORD_SIZE_64 -void classify_counts(afl_forkserver_t *fsrv) { +void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) { u64 *mem = (u64 *)fsrv->trace_bits; @@ -376,7 +376,7 @@ void classify_counts(afl_forkserver_t *fsrv) { #else -void classify_counts(afl_forkserver_t *fsrv) { +void __attribute__ ((hot)) classify_counts(afl_forkserver_t *fsrv) { u32 *mem = (u32 *)fsrv->trace_bits; @@ -534,7 +534,7 @@ static void write_crash_readme(afl_state_t *afl) { save or queue the input test case for further analysis if so. Returns 1 if entry is saved, 0 otherwise. */ -u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { +u8 __attribute__ ((hot)) save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (unlikely(len == 0)) { return 0; } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index e69e9791..97fcb3c8 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -38,7 +38,7 @@ u64 time_spent_working = 0; /* Execute target application, monitoring for timeouts. Return status information. The called program will update afl->fsrv->trace_bits. */ -fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, +fsrv_run_result_t __attribute__ ((hot)) fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) { #ifdef PROFILING @@ -72,7 +72,7 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, old file is unlinked and a new one is created. Otherwise, afl->fsrv.out_fd is rewound and truncated. */ -void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { +void __attribute__ ((hot)) write_to_testcase(afl_state_t *afl, void *mem, u32 len) { #ifdef _AFL_DOCUMENT_MUTATIONS s32 doc_fd; @@ -858,7 +858,7 @@ abort_trimming: error conditions, returning 1 if it's time to bail out. This is a helper function for fuzz_one(). */ -u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { +u8 __attribute__ ((hot)) common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { u8 fault; -- cgit 1.4.1