diff options
-rw-r--r-- | .github/workflows/ci.yml | 4 | ||||
-rw-r--r-- | .github/workflows/codeql-analysis.yml | 4 | ||||
-rw-r--r-- | .gitmodules | 2 | ||||
-rw-r--r-- | README.md | 8 | ||||
-rw-r--r-- | docs/Changelog.md | 4 | ||||
-rw-r--r-- | dynamic_list.txt | 21 | ||||
-rw-r--r-- | include/common.h | 4 | ||||
-rw-r--r-- | include/envs.h | 1 | ||||
-rw-r--r-- | instrumentation/README.lto.md | 2 | ||||
-rw-r--r-- | instrumentation/SanitizerCoverageLTO.so.cc | 7 | ||||
-rw-r--r-- | instrumentation/SanitizerCoveragePCGUARD.so.cc | 158 | ||||
-rw-r--r-- | instrumentation/afl-compiler-rt.o.c | 6 | ||||
-rw-r--r-- | instrumentation/afl-llvm-common.cc | 18 | ||||
-rw-r--r-- | src/afl-cc.c | 2 | ||||
-rw-r--r-- | src/afl-common.c | 228 | ||||
-rw-r--r-- | src/afl-fuzz.c | 15 | ||||
-rw-r--r-- | test-instr.c | 4 | ||||
-rw-r--r-- | test/test-dlopen.c | 23 | ||||
-rwxr-xr-x | test/test-llvm.sh | 42 | ||||
-rw-r--r-- | test/travis/bionic/Dockerfile | 45 | ||||
-rw-r--r-- | test/travis/focal/Dockerfile | 45 | ||||
-rw-r--r-- | test/travis/trusty/Dockerfile | 49 | ||||
-rw-r--r-- | test/travis/xenial/Dockerfile | 46 | ||||
-rw-r--r-- | utils/libdislocator/libdislocator.so.c | 12 |
24 files changed, 222 insertions, 528 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8412fcbb..31cfceaf 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -3,8 +3,8 @@ name: CI on: push: branches: [ stable, dev ] -# pull_request: -# branches: [ stable, dev ] + pull_request: + branches: [ stable, dev ] jobs: build: diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index e6c166f2..eda8dfd0 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -3,8 +3,8 @@ name: "CodeQL" on: push: branches: [ stable, dev ] -# pull_request: -# branches: [ stable, dev ] + pull_request: + branches: [ stable, dev ] jobs: analyze: diff --git a/.gitmodules b/.gitmodules index e9f5bb1d..c787ec0e 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,6 @@ [submodule "unicorn_mode/unicornafl"] path = unicorn_mode/unicornafl - url = https://github.com/aflplusplus/unicornafl + url = https://github.com/AFLplusplus/unicornafl [submodule "custom_mutators/grammar_mutator"] path = custom_mutators/grammar_mutator/grammar_mutator url = https://github.com/AFLplusplus/Grammar-Mutator diff --git a/README.md b/README.md index 69e5bb74..2528e1d1 100644 --- a/README.md +++ b/README.md @@ -175,7 +175,13 @@ If you want to build afl++ yourself you have many options. The easiest choice is to build and install everything: ```shell -sudo apt install build-essential python3-dev automake flex bison libglib2.0-dev libpixman-1-dev python3-setuptools clang lld llvm llvm-dev libstdc++-dev +sudo apt-get update +sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools +# try to install llvm 11 and install the distro default if that fails +sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang +sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev +git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus +cd AFLplusplus make distrib sudo make install ``` diff --git a/docs/Changelog.md b/docs/Changelog.md index 8dc218af..166393cb 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,8 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to <afl-users+subscribe@googlegroups.com>. ### Version ++3.12a (dev) + - afl-fuzz: + - better map detection, AFL_MAP_SIZE not needed anymore for most cases - afl-cc: - fix cmplog rtn (rare crash and not being able to gather ptr data) - link runtime not to shared libs @@ -16,6 +18,8 @@ sending a mail to <afl-users+subscribe@googlegroups.com>. - qemu_mode (thanks @realmadsci): - move AFL_PRELOAD and AFL_USE_QASAN logic inside afl-qemu-trace - add AFL_QEMU_CUSTOM_BIN + - unicorn_mode + - accidently removed the subfolder from github, re-added ### Version ++3.11c (release) - afl-fuzz: diff --git a/dynamic_list.txt b/dynamic_list.txt index 4b92d154..f0e54d92 100644 --- a/dynamic_list.txt +++ b/dynamic_list.txt @@ -23,4 +23,25 @@ "__afl_fuzz_ptr"; "__sanitizer_cov_trace_pc_guard"; "__sanitizer_cov_trace_pc_guard_init"; + "__cmplog_ins_hook1"; + "__cmplog_ins_hook2"; + "__cmplog_ins_hook4"; + "__cmplog_ins_hookN"; + "__cmplog_ins_hook16"; + "__sanitizer_cov_trace_cmp1"; + "__sanitizer_cov_trace_const_cmp1"; + "__sanitizer_cov_trace_cmp2"; + "__sanitizer_cov_trace_const_cmp2"; + "__sanitizer_cov_trace_cmp4"; + "__sanitizer_cov_trace_const_cmp4"; + "__sanitizer_cov_trace_cmp8"; + "__sanitizer_cov_trace_const_cmp8"; + "__sanitizer_cov_trace_cmp16"; + "__sanitizer_cov_trace_const_cmp16"; + "__sanitizer_cov_trace_switch"; + "__cmplog_rtn_hook"; + "__cmplog_rtn_gcc_stdstring_cstring"; + "__cmplog_rtn_gcc_stdstring_stdstring"; + "__cmplog_rtn_llvm_stdstring_cstring"; + "__cmplog_rtn_llvm_stdstring_stdstring"; }; diff --git a/include/common.h b/include/common.h index b7adbaec..46585c88 100644 --- a/include/common.h +++ b/include/common.h @@ -57,6 +57,10 @@ extern u8 *doc_path; /* path to documentation dir */ u8 *find_binary(u8 *fname); +/* find an afl binary */ + +u8 *find_afl_binary(u8 *own_loc, u8 *fname); + /* Parses the kill signal environment variable, FATALs on error. If the env is not set, sets the env to default_signal for the signal handlers and returns the default_signal. */ diff --git a/include/envs.h b/include/envs.h index cfd73b68..2ce50be7 100644 --- a/include/envs.h +++ b/include/envs.h @@ -42,6 +42,7 @@ static char *afl_environment_variables[] = { "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DISABLE_TRIM", + "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV", diff --git a/instrumentation/README.lto.md b/instrumentation/README.lto.md index 81c82c4b..39f6465a 100644 --- a/instrumentation/README.lto.md +++ b/instrumentation/README.lto.md @@ -113,7 +113,7 @@ cmake \ -DLLVM_LINK_LLVM_DYLIB="ON" \ -DLLVM_TARGETS_TO_BUILD="host" \ ../llvm/ -cmake --build . --parallel +cmake --build . -j4 export PATH="$(pwd)/bin:$PATH" export LLVM_CONFIG="$(pwd)/bin/llvm-config" export LD_LIBRARY_PATH="$(llvm-config --libdir)${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}" diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 13a5e5fd..28d905a3 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1291,10 +1291,17 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, Constant::getNullValue(ArrayTy), "__sancov_gen_"); +#if LLVM_VERSION_MAJOR > 12 + if (TargetTriple.supportsCOMDAT() && + (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) + if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) + Array->setComdat(Comdat); +#else if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) if (auto Comdat = GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) Array->setComdat(Comdat); +#endif Array->setSection(getSectionName(Section)); Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); GlobalsToAppendToUsed.push_back(Array); diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 9b1351b0..99ead3d6 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// +#include "llvm/Transforms/Instrumentation/SanitizerCoverage.h" #include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/EHPersonalities.h" @@ -34,11 +35,11 @@ #include "llvm/InitializePasses.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" #include "llvm/Support/SpecialCaseList.h" #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) #include "llvm/Support/VirtualFileSystem.h" #endif +#include "llvm/Support/raw_ostream.h" #include "llvm/Transforms/Instrumentation.h" #include "llvm/Transforms/Utils/BasicBlockUtils.h" #include "llvm/Transforms/Utils/ModuleUtils.h" @@ -47,65 +48,6 @@ #include "debug.h" #include "afl-llvm-common.h" -namespace llvm { - -/// This is the ModuleSanitizerCoverage pass used in the new pass manager. The -/// pass instruments functions for coverage, adds initialization calls to the -/// module for trace PC guards and 8bit counters if they are requested, and -/// appends globals to llvm.compiler.used. -class ModuleSanitizerCoveragePass - : public PassInfoMixin<ModuleSanitizerCoveragePass> { - - public: - explicit ModuleSanitizerCoveragePass( - SanitizerCoverageOptions Options = SanitizerCoverageOptions(), - const std::vector<std::string> &AllowlistFiles = - std::vector<std::string>(), - const std::vector<std::string> &BlocklistFiles = - std::vector<std::string>()) - : Options(Options) { - - if (AllowlistFiles.size() > 0) - Allowlist = SpecialCaseList::createOrDie(AllowlistFiles -#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , - *vfs::getRealFileSystem() -#endif - ); - if (BlocklistFiles.size() > 0) - Blocklist = SpecialCaseList::createOrDie(BlocklistFiles -#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , - *vfs::getRealFileSystem() -#endif - ); - - } - - PreservedAnalyses run(Module &M, ModuleAnalysisManager &AM); - static bool isRequired() { - - return true; - - } - - private: - SanitizerCoverageOptions Options; - - std::unique_ptr<SpecialCaseList> Allowlist; - std::unique_ptr<SpecialCaseList> Blocklist; - -}; - -// Insert SanitizerCoverage instrumentation. -ModulePass *createModuleSanitizerCoverageLegacyPassPass( - const SanitizerCoverageOptions &Options = SanitizerCoverageOptions(), - const std::vector<std::string> &AllowlistFiles = std::vector<std::string>(), - const std::vector<std::string> &BlocklistFiles = - std::vector<std::string>()); - -} // namespace llvm - using namespace llvm; #define DEBUG_TYPE "sancov" @@ -156,96 +98,8 @@ static const char *const SanCovLowestStackName = "__sancov_lowest_stack"; static char *skip_nozero; -/* -static cl::opt<int> ClCoverageLevel( - "sanitizer-coverage-level", - cl::desc("Sanitizer Coverage. 0: none, 1: entry block, 2: all blocks, " - "3: all blocks and critical edges"), - cl::Hidden, cl::init(3)); - -static cl::opt<bool> ClTracePC("sanitizer-coverage-trace-pc", - cl::desc("Experimental pc tracing"), cl::Hidden, - cl::init(false)); - -static cl::opt<bool> ClTracePCGuard("sanitizer-coverage-trace-pc-guard", - cl::desc("pc tracing with a guard"), - cl::Hidden, cl::init(true)); - -// If true, we create a global variable that contains PCs of all instrumented -// BBs, put this global into a named section, and pass this section's bounds -// to __sanitizer_cov_pcs_init. -// This way the coverage instrumentation does not need to acquire the PCs -// at run-time. Works with trace-pc-guard, inline-8bit-counters, and -// inline-bool-flag. -static cl::opt<bool> ClCreatePCTable("sanitizer-coverage-pc-table", - cl::desc("create a static PC table"), - cl::Hidden, cl::init(false)); - -static cl::opt<bool> ClInline8bitCounters( - "sanitizer-coverage-inline-8bit-counters", - cl::desc("increments 8-bit counter for every edge"), cl::Hidden, - cl::init(false)); - -static cl::opt<bool> ClInlineBoolFlag( - "sanitizer-coverage-inline-bool-flag", - cl::desc("sets a boolean flag for every edge"), cl::Hidden, - cl::init(false)); - -static cl::opt<bool> ClCMPTracing( - "sanitizer-coverage-trace-compares", - cl::desc("Tracing of CMP and similar instructions"), cl::Hidden, - cl::init(false)); - -static cl::opt<bool> ClDIVTracing("sanitizer-coverage-trace-divs", - cl::desc("Tracing of DIV instructions"), - cl::Hidden, cl::init(false)); - -static cl::opt<bool> ClGEPTracing("sanitizer-coverage-trace-geps", - cl::desc("Tracing of GEP instructions"), - cl::Hidden, cl::init(false)); - -static cl::opt<bool> ClPruneBlocks( - "sanitizer-coverage-prune-blocks", - cl::desc("Reduce the number of instrumented blocks"), cl::Hidden, - cl::init(true)); - -static cl::opt<bool> ClStackDepth("sanitizer-coverage-stack-depth", - cl::desc("max stack depth tracing"), - cl::Hidden, cl::init(false)); -*/ namespace { -/* -SanitizerCoverageOptions getOptions(int LegacyCoverageLevel) { - - SanitizerCoverageOptions Res; - switch (LegacyCoverageLevel) { - - case 0: - Res.CoverageType = SanitizerCoverageOptions::SCK_None; - break; - case 1: - Res.CoverageType = SanitizerCoverageOptions::SCK_Function; - break; - case 2: - Res.CoverageType = SanitizerCoverageOptions::SCK_BB; - break; - case 3: - Res.CoverageType = SanitizerCoverageOptions::SCK_Edge; - break; - case 4: - Res.CoverageType = SanitizerCoverageOptions::SCK_Edge; - Res.IndirectCalls = true; - break; - - } - - return Res; - -} - -*/ - SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { // Sets CoverageType and IndirectCalls. @@ -915,10 +769,18 @@ GlobalVariable *ModuleSanitizerCoverage::CreateFunctionLocalArrayInSection( *CurModule, ArrayTy, false, GlobalVariable::PrivateLinkage, Constant::getNullValue(ArrayTy), "__sancov_gen_"); +#if LLVM_VERSION_MAJOR > 12 + if (TargetTriple.supportsCOMDAT() && + (TargetTriple.isOSBinFormatELF() || !F.isInterposable())) + if (auto Comdat = getOrCreateFunctionComdat(F, TargetTriple)) + Array->setComdat(Comdat); +#else if (TargetTriple.supportsCOMDAT() && !F.isInterposable()) if (auto Comdat = GetOrCreateFunctionComdat(F, TargetTriple, CurModuleUniqueId)) Array->setComdat(Comdat); +#endif + Array->setSection(getSectionName(Section)); #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) Array->setAlignment(Align(DL->getTypeStoreSize(Ty).getFixedSize())); diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index c635ae63..ab1bfb31 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -1676,6 +1676,12 @@ void __sanitizer_cov_trace_cmp16(uint128_t arg1, uint128_t arg2) { } +void __sanitizer_cov_trace_const_cmp16(uint128_t arg1, uint128_t arg2) { + + __cmplog_ins_hook16(arg1, arg2, 0); + +} + #endif void __sanitizer_cov_trace_switch(uint64_t val, uint64_t *cases) { diff --git a/instrumentation/afl-llvm-common.cc b/instrumentation/afl-llvm-common.cc index 17780143..74943fb2 100644 --- a/instrumentation/afl-llvm-common.cc +++ b/instrumentation/afl-llvm-common.cc @@ -96,19 +96,11 @@ bool isIgnoreFunction(const llvm::Function *F) { static const char *ignoreSubstringList[] = { - "__asan", - "__msan", - "__ubsan", - "__lsan", - "__san", - "__sanitize", - "__cxx", - "_GLOBAL__", - "DebugCounter", - "DwarfDebug", - "DebugLoc" - - }; + "__asan", "__msan", "__ubsan", "__lsan", + "__san", "__sanitize", "__cxx", "_GLOBAL__", + "DebugCounter", "DwarfDebug", "DebugLoc" + + }; for (auto const &ignoreListFunc : ignoreSubstringList) { diff --git a/src/afl-cc.c b/src/afl-cc.c index e13f285d..5251465b 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -1040,7 +1040,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } #if !defined(__APPLE__) && !defined(__sun) - if (shared_linking) + if (!shared_linking) cc_params[cc_par_cnt++] = alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path); #endif diff --git a/src/afl-common.c b/src/afl-common.c index 7e56ce3f..04736901 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -158,10 +158,6 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { } - if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } - - u8 *tmp, *cp = NULL, *rsl, *own_copy; - char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } @@ -173,70 +169,8 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { /* Now we need to actually find the QEMU binary to put in argv[0]. */ - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - ck_free(own_copy); - - if (!access(cp, X_OK)) { - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } - - } else { - - ck_free(own_copy); - - } - - if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - - if (cp) { ck_free(cp); } - *target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); - - return new_argv; - - } - - SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the 'afl-qemu-trace' binary. The binary must be " - "built\n" - " separately by following the instructions in " - "qemu_mode/README.md. " - "If you\n" - " already have the binary installed, you may need to specify " - "AFL_PATH in the\n" - " environment.\n\n" - - " Of course, even without QEMU, afl-fuzz can still work with " - "binaries that are\n" - " instrumented at compile time with afl-gcc. It is also possible to " - "use it as a\n" - " traditional non-instrumented fuzzer by specifying '-n' in the " - "command " - "line.\n"); - - FATAL("Failed to locate 'afl-qemu-trace'."); + *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-qemu-trace"); + return new_argv; } @@ -244,10 +178,6 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { - if (!unlikely(own_loc)) { FATAL("BUG: param own_loc is NULL"); } - - u8 *tmp, *cp = NULL, *rsl, *own_copy; - char **new_argv = ck_alloc(sizeof(char *) * (argc + 3)); if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } @@ -258,92 +188,10 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { /* Now we need to actually find the QEMU binary to put in argv[0]. */ - tmp = getenv("AFL_PATH"); - - if (tmp) { - - cp = alloc_printf("%s/afl-qemu-trace", tmp); - - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - - ck_free(cp); - - cp = alloc_printf("%s/afl-wine-trace", tmp); - - if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } - - own_copy = ck_strdup(own_loc); - rsl = strrchr(own_copy, '/'); - - if (rsl) { - - *rsl = 0; - - cp = alloc_printf("%s/afl-qemu-trace", own_copy); - - if (cp && !access(cp, X_OK)) { - - ck_free(cp); - - cp = alloc_printf("%s/afl-wine-trace", own_copy); - - if (!access(cp, X_OK)) { - - *target_path_p = new_argv[0] = cp; - return new_argv; - - } - - } - - ck_free(own_copy); - - } else { - - ck_free(own_copy); - - } - - u8 *ncp = BIN_PATH "/afl-qemu-trace"; - - if (!access(ncp, X_OK)) { - - ncp = BIN_PATH "/afl-wine-trace"; - - if (!access(ncp, X_OK)) { - - *target_path_p = new_argv[0] = ck_strdup(ncp); - return new_argv; - - } - - } - - SAYF("\n" cLRD "[-] " cRST - "Oops, unable to find the '%s' binary. The binary must be " - "built\n" - " separately by following the instructions in " - "qemu_mode/README.md. " - "If you\n" - " already have the binary installed, you may need to specify " - "AFL_PATH in the\n" - " environment.\n\n" - - " Of course, even without QEMU, afl-fuzz can still work with " - "binaries that are\n" - " instrumented at compile time with afl-gcc. It is also possible to " - "use it as a\n" - " traditional non-instrumented fuzzer by specifying '-n' in the " - "command " - "line.\n", - ncp); - - FATAL("Failed to locate '%s'.", ncp); + u8 *tmp = find_afl_binary(own_loc, "afl-qemu-trace"); + ck_free(tmp); + *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-wine-trace"); + return new_argv; } @@ -437,6 +285,70 @@ u8 *find_binary(u8 *fname) { } +u8 *find_afl_binary(u8 *own_loc, u8 *fname) { + + u8 *afl_path = NULL, *target_path, *own_copy; + + if ((afl_path = getenv("AFL_PATH"))) { + + target_path = alloc_printf("%s/%s", afl_path, fname); + if (!access(target_path, X_OK)) { + + return target_path; + + } else { + + ck_free(target_path); + + } + + } + + if (own_loc) { + + own_copy = ck_strdup(own_loc); + u8 *rsl = strrchr(own_copy, '/'); + + if (rsl) { + + *rsl = 0; + + target_path = alloc_printf("%s/%s", own_copy, fname); + ck_free(own_copy); + + if (!access(target_path, X_OK)) { + + return target_path; + + } else { + + ck_free(target_path); + + } + + } else { + + ck_free(own_copy); + + } + + } + + target_path = alloc_printf("%s/%s", BIN_PATH, fname); + if (!access(target_path, X_OK)) { + + return target_path; + + } else { + + ck_free(target_path); + + } + + return find_binary(fname); + +} + /* Parses the kill signal environment variable, FATALs on error. If the env is not set, sets the env to default_signal for the signal handlers and returns the default_signal. */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index ff4c5281..1518a707 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -1540,10 +1540,8 @@ int main(int argc, char **argv_orig, char **envp) { u32 new_map_size = afl_fsrv_get_mapsize( &afl->fsrv, afl->argv, &afl->stop_soon, afl->afl_env.afl_debug_child); - // only reinitialize when it makes sense - if ((map_size < new_map_size /*|| - (new_map_size != MAP_SIZE && new_map_size < map_size && - map_size - new_map_size > MAP_SIZE)*/)) { + // only reinitialize if the map needs to be larger than what we have. + if (map_size < new_map_size) { OKF("Re-initializing maps to %u bytes", new_map_size); @@ -1639,15 +1637,6 @@ int main(int argc, char **argv_orig, char **envp) { } - if (afl->debug) { - - printf("NORMAL %u, CMPLOG %u\n", afl->fsrv.map_size, - afl->cmplog_fsrv.map_size); - fprintf(stderr, "NORMAL %u, CMPLOG %u\n", afl->fsrv.map_size, - afl->cmplog_fsrv.map_size); - - } - load_auto(afl); if (extras_dir_cnt) { diff --git a/test-instr.c b/test-instr.c index 00799103..13d4eb93 100644 --- a/test-instr.c +++ b/test-instr.c @@ -18,6 +18,10 @@ #include <sys/stat.h> #include <fcntl.h> +#ifdef TEST_SHARED_OBJECT + #define main main_exported +#endif + int main(int argc, char **argv) { int fd = 0; diff --git a/test/test-dlopen.c b/test/test-dlopen.c new file mode 100644 index 00000000..d08d9092 --- /dev/null +++ b/test/test-dlopen.c @@ -0,0 +1,23 @@ +#include <stdio.h> +#include <errno.h> +#include <dlfcn.h> +#include <stdlib.h> + +int main(int argc, char **argv) { + + if (!getenv("TEST_DLOPEN_TARGET")) return 1; + void *lib = dlopen(getenv("TEST_DLOPEN_TARGET"), RTLD_LAZY); + if (!lib) { + + perror(dlerror()); + return 2; + + } + + int (*func)(int, char **) = dlsym(lib, "main_exported"); + if (!func) return 3; + + return func(argc, argv); + +} + diff --git a/test/test-llvm.sh b/test/test-llvm.sh index aa36af1b..3ef36b37 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -43,6 +43,48 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { $ECHO "$RED[!] llvm_mode failed" CODE=1 } + ../afl-clang-fast -DTEST_SHARED_OBJECT=1 -z defs -fPIC -shared -o test-instr.so ../test-instr.c > /dev/null 2>&1 + test -e test-instr.so && { + $ECHO "$GREEN[+] llvm_mode shared object with -z defs compilation succeeded" + ../afl-clang-fast -o test-dlopen.plain test-dlopen.c -ldl > /dev/null 2>&1 + test -e test-dlopen.plain && { + $ECHO "$GREEN[+] llvm_mode test-dlopen compilation succeeded" + echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ./test-dlopen.plain > /dev/null 2>&1 + if [ $? -ne 0 ]; then + $ECHO "$RED[!] llvm_mode test-dlopen exits with an error" + CODE=1 + fi + echo 0 | TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.0 -r -- ./test-dlopen.plain > /dev/null 2>&1 + TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o test-dlopen.plain.1 -r -- ./test-dlopen.plain < /dev/null > /dev/null 2>&1 + test -e test-dlopen.plain.0 -a -e test-dlopen.plain.1 && { + diff test-dlopen.plain.0 test-dlopen.plain.1 > /dev/null 2>&1 && { + $ECHO "$RED[!] llvm_mode test-dlopen instrumentation should be different on different input but is not" + CODE=1 + } || { + $ECHO "$GREEN[+] llvm_mode test-dlopen instrumentation present and working correctly" + TUPLES=`echo 0|TEST_DLOPEN_TARGET=./test-instr.so AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-dlopen.plain 2>&1 | grep Captur | awk '{print$3}'` + test "$TUPLES" -gt 3 -a "$TUPLES" -lt 12 && { + $ECHO "$GREEN[+] llvm_mode test-dlopen run reported $TUPLES instrumented locations which is fine" + } || { + $ECHO "$RED[!] llvm_mode test-dlopen instrumentation produces weird numbers: $TUPLES" + CODE=1 + } + test "$TUPLES" -lt 3 && SKIP=1 + true + } + } || { + $ECHO "$RED[!] llvm_mode test-dlopen instrumentation failed" + CODE=1 + } + } || { + $ECHO "$RED[!] llvm_mode test-dlopen compilation failed" + CODE=1 + } + rm -f test-dlopen.plain test-dlopen.plain.0 test-dlopen.plain.1 test-instr.so + } || { + $ECHO "$RED[!] llvm_mode shared object with -z defs compilation failed" + CODE=1 + } test -e test-compcov.harden && test_compcov_binary_functionality ./test-compcov.harden && { grep -Eq$GREPAOPTION 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && { $ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working" diff --git a/test/travis/bionic/Dockerfile b/test/travis/bionic/Dockerfile deleted file mode 100644 index 00ab96f9..00000000 --- a/test/travis/bionic/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# This is the Dockerfile for testing problems in Travis build -# configuration #1. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:bionic -LABEL "about"="travis image 1" -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang \ - flex \ - git \ - python3.7 python3.7-dev \ - python3-setuptools \ - libtool libtool-bin \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-7 gcc-7-plugin-dev libc++-7-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 -ENV LLVM_CONFIG=llvm-config-6.0 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] diff --git a/test/travis/focal/Dockerfile b/test/travis/focal/Dockerfile deleted file mode 100644 index 27d994f2..00000000 --- a/test/travis/focal/Dockerfile +++ /dev/null @@ -1,45 +0,0 @@ -# This is the Dockerfile for testing problems in Travis build -# configuration #1. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:focal -LABEL "about"="travis image 4" -ARG DEBIAN_FRONTEND=noninteractive -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang \ - flex \ - git \ - python3 python3-dev \ - python3-setuptools \ - libtool libtool-bin \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-9 gcc-9-plugin-dev libc++-9-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] diff --git a/test/travis/trusty/Dockerfile b/test/travis/trusty/Dockerfile deleted file mode 100644 index 0a6f1804..00000000 --- a/test/travis/trusty/Dockerfile +++ /dev/null @@ -1,49 +0,0 @@ -# This is the Dockerfile for testing problems in Travis builds -# configuration #3. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:trusty -LABEL "about"="travis image 3" -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang \ - flex \ - git \ - python2.7 python2.7-dev \ - python3-setuptools \ - libtool \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-4.8 gcc-4.8-plugin-dev \ - libc++-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV TERM linux -ENV DEBIAN_FRONTEND noninteractive -ENV LLVM_CONFIG=llvm-config-3.4 -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] - diff --git a/test/travis/xenial/Dockerfile b/test/travis/xenial/Dockerfile deleted file mode 100644 index 6aa4b1d1..00000000 --- a/test/travis/xenial/Dockerfile +++ /dev/null @@ -1,46 +0,0 @@ -# This is the Dockerfile for testing problems in Travis builds -# configuration #2. -# This needs not to be rebuild everytime, most of the time it needs just to -# be build once and then started when debugging issues and execute: -# cd /AFLplusplus/ -# git pull -# make distrib -# -FROM ubuntu:xenial -LABEL "about"="travis image 2" -RUN apt-get update && apt-get -y install \ - automake \ - bison \ - build-essential \ - clang-6.0 \ - flex \ - git \ - python3 python3-dev \ - python3-setuptools \ - libtool libtool-bin \ - libglib2.0-dev \ - python-setuptools \ - wget \ - ca-certificates \ - libpixman-1-dev \ - gcc-5 gcc-5-plugin-dev \ - libc++-dev \ - findutils \ - libcmocka-dev \ - joe nano vim locate \ - && rm -rf /var/lib/apt/lists/* - -ENV LLVM_CONFIG=llvm-config-6.0 -ENV AFL_NO_UI=1 -ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 - -RUN cd / && \ - git clone https://github.com/AFLplusplus/AFLplusplus && \ - cd AFLplusplus && \ - git checkout dev && \ - cd qemu_mode && wget http://download.qemu-project.org/qemu-3.1.1.tar.xz && \ - cd ../unicorn_mode && git submodule init && git submodule update || true && \ - cd /AFLplusplus && ASAN_BUILD=1 make source-only || true - -WORKDIR /AFLplusplus -CMD ["/bin/bash"] diff --git a/utils/libdislocator/libdislocator.so.c b/utils/libdislocator/libdislocator.so.c index c041fec6..1b247c86 100644 --- a/utils/libdislocator/libdislocator.so.c +++ b/utils/libdislocator/libdislocator.so.c @@ -168,7 +168,7 @@ static void *__dislocator_alloc(size_t len) { u8 * ret, *base; size_t tlen; - int flags, fd, sp; + int flags, protflags, fd, sp; if (total_mem + len > max_mem || total_mem + len < total_mem) { @@ -191,8 +191,14 @@ static void *__dislocator_alloc(size_t len) { base = NULL; tlen = (1 + PG_COUNT(rlen + 8)) * PAGE_SIZE; + protflags = PROT_READ | PROT_WRITE; flags = MAP_PRIVATE | MAP_ANONYMOUS; fd = -1; +#if defined(PROT_MAX) + // apply when sysctl vm.imply_prot_max is set to 1 + // no-op otherwise + protflags |= PROT_MAX(PROT_READ | PROT_WRITE); +#endif #if defined(USEHUGEPAGE) sp = (rlen >= SUPER_PAGE_SIZE && !(rlen % SUPER_PAGE_SIZE)); @@ -215,7 +221,7 @@ static void *__dislocator_alloc(size_t len) { (void)sp; #endif - ret = (u8 *)mmap(base, tlen, PROT_READ | PROT_WRITE, flags, fd, 0); + ret = (u8 *)mmap(base, tlen, protflags, flags, fd, 0); #if defined(USEHUGEPAGE) /* We try one more time with regular call */ if (ret == MAP_FAILED) { @@ -229,7 +235,7 @@ static void *__dislocator_alloc(size_t len) { #elif defined(__sun) flags &= -MAP_ALIGN; #endif - ret = (u8 *)mmap(NULL, tlen, PROT_READ | PROT_WRITE, flags, fd, 0); + ret = (u8 *)mmap(NULL, tlen, protflags, flags, fd, 0); } |