From 9adcc73d617f22ffdfaba0491374dc0b7edcf8cd Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 17 Apr 2020 19:39:32 +0200 Subject: v2.64d init --- docs/Changelog.md | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 9d6b5f87..256c9c93 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -9,6 +9,11 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . +### Version ++2.64d (develop): + - ... + + + ### Version ++2.64c (release): - llvm_mode LTO mode: - now requires llvm11 - but compiles all targets! :) -- cgit 1.4.1 From 68f18923abead89db52f4352e44cee1fd8a64cb1 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 18 Apr 2020 11:32:06 +0200 Subject: fix docs typos --- docs/Changelog.md | 2 +- qemu_mode/README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 256c9c93..93820c3b 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -146,7 +146,7 @@ sending a mail to . - AFL_PERSISTENT_HOOK callback module for persistent QEMU (see examples/qemu_persistent_hook) - added qemu_mode/README.persistent.md documentation - - AFL_ENTRYPOINT noew has instruction granularity + - AFL_ENTRYPOINT now has instruction granularity - afl-cmin is now a sh script (invoking awk) instead of bash for portability the original script is still present as afl-cmin.bash - afl-showmap: -i dir option now allows processing multiple inputs using the diff --git a/qemu_mode/README.md b/qemu_mode/README.md index 71a3ada7..76b74e17 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -46,8 +46,8 @@ You can also compile statically-linked binaries by setting STATIC=1. This can be useful when compiling QEMU on a different system than the one you're planning to run the fuzzer on and is most often used with the HOST variable. -Note: when targetting the i386 architecture, on some bianries the forkserver -handshake may fail due to the lack of reversed memory. Fix it with +Note: when targetting the i386 architecture, on some binaries the forkserver +handshake may fail due to the lack of reserved memory. Fix it with export QEMU_RESERVED_VA=0x1000000 -- cgit 1.4.1 From 16a5e6bf16616389d3821414547d0402f3502e73 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 19 Apr 2020 10:15:28 +0200 Subject: update documentation --- docs/Changelog.md | 11 +++++++++-- qemu_mode/README.persistent.md | 12 +++++++----- 2 files changed, 16 insertions(+), 7 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 93820c3b..95adf8ea 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,8 +10,15 @@ sending a mail to . ### Version ++2.64d (develop): - - ... - + - qemu_mode: + - add information on PIE/PIC load addresses for 32 bit + - better dependency checks + - gcc_plugin: + - better dependency checks + - unicorn_mode: + - better submodule handling + - all: + - fix 32 bit build options ### Version ++2.64c (release): diff --git a/qemu_mode/README.persistent.md b/qemu_mode/README.persistent.md index 46077402..b6d5d2d0 100644 --- a/qemu_mode/README.persistent.md +++ b/qemu_mode/README.persistent.md @@ -23,8 +23,10 @@ in 2.2 and 2.3) have to be set. This address (as well as the RET address, see below) has to be defined in hexadecimal with the 0x prefix or as a decimal value. -If the target is compiled with position independant code (PIE/PIC), you must -add 0x4000000000 to that address, because qemu loads to this base address. +*Note:* If the target is compiled with position independant code (PIE/PIC) +qemu loads these to a specific base address. +For 64 bit you have to add 0x4000000000 (9 zeroes) and for 32 bit 0x40000000 +(7 zeroes) to the address. On strange setups the base address set by QEMU for PIE executable may change, you can check it printing the process map using `AFL_QEMU_DEBUG_MAPS=1 afl-qemu-trace TARGET-BINARY` @@ -32,7 +34,7 @@ you can check it printing the process map using If this address is not valid, afl-fuzz will error during startup with the message that the forkserver was not found. -### 2.2) the RET address +### 2.2) The RET address The RET address is the last instruction of the persistent loop. The emulator will emit a jump to START when translating the instruction at RET. @@ -46,7 +48,7 @@ patch the return address (on stack or in the link register) to return to START It is defined by setting AFL_QEMU_PERSISTENT_RET, and too 0x4000000000 has to be set if the target is position independant. -### 2.3) the OFFSET +### 2.3) The OFFSET This option is valid only for x86/x86_64 only, arm/aarch64 do not save the return address on stack. @@ -72,7 +74,7 @@ Now to get this value right here some help: 8. again print the ESP value 9. calculate the difference between the two values - and this is the offset -### 2.4) resetting the register state +### 2.4) Resetting the register state It is very, very likely you need to restore the general purpose registers state when starting a new loop. Because of this you 99% of the time should set -- cgit 1.4.1 From 4c90293e447a6e43129b39e14a72cbad38704522 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 19 Apr 2020 16:48:42 +0200 Subject: clean and deepclean Makefile updates --- GNUmakefile | 40 +++++++++++++++++++++------------------- README.md | 3 ++- docs/Changelog.md | 2 ++ 3 files changed, 25 insertions(+), 20 deletions(-) (limited to 'docs/Changelog.md') diff --git a/GNUmakefile b/GNUmakefile index ce3f0aae..21b5d2a1 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -36,7 +36,6 @@ SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8 ASAN_OPTIONS=detect_leaks=0 -$(info echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test ) ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" "" ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1" CFLAGS_FLTO ?= -flto=full @@ -151,9 +150,12 @@ ifdef NO_PYTHON PYFLAGS= endif -IN_GIT=1 -ifeq "$(shell git status 2>/dev/null)" "" - IN_GIT=0 +IN_REPO=0 +ifeq "$(shell git status >/dev/null 2>&1 && echo 1 || echo 0)" "1" + IN_REPO=1 +endif +ifeq "$(shell svn proplist . 2>/dev/null && echo 1 || echo 0)" "1" + IN_REPO=1 endif ifdef STATIC @@ -220,7 +222,8 @@ help: @echo "distrib: everything (for both binary-only and source code fuzzing)" @echo "man: creates simple man pages from the help option of the programs" @echo "install: installs everything you have compiled with the build option above" - @echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well" + @echo "clean: cleans everything compiled (not downloads when on a checkout)" + @echo "deepclean: cleans everything including downloads" @echo "code-format: format the code, do this before you commit and send a PR please!" @echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem" @echo "unit: perform unit tests (based on cmocka)" @@ -407,21 +410,10 @@ all_done: test_build @if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi @! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null -.NOTPARALLEL: clean - -ifeq "$(IN_GIT)" "1" -# In git, unicornafl is a submodules, clean recursively -clean_unicorn: - $(MAKE) -C unicorn_mode/unicornafl clean || true - -else -# Else we remove the folder -clean_unicorn: - rm -rf unicorn_mode/unicornafl -endif +.NOTPARALLEL: clean all -clean: clean_unicorn - rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable +clean: + rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM -$(MAKE) -C llvm_mode clean -$(MAKE) -C gcc_plugin clean @@ -432,7 +424,17 @@ clean: clean_unicorn $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C src/third_party/libradamsa/ clean + rm -rf qemu_mode/qemu-3.1.1 +ifeq "$(IN_REPO)" "1" + $(MAKE) -C unicorn_mode/unicornafl clean || true +else + rm -rf qemu_mode/qemu-3.1.1.tar.xz + rm -rf unicorn_mode/unicornafl +endif +deepclean: clean + rm -rf qemu_mode/qemu-3.1.1.tar.xz + rm -rf unicorn_mode/unicornafl distrib: all radamsa -$(MAKE) -C llvm_mode diff --git a/README.md b/README.md index 1e9b61f1..49bc35c9 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,8 @@ These build targets exist: * distrib: everything (for both binary-only and source code fuzzing) * man: creates simple man pages from the help option of the programs * install: installs everything you have compiled with the build options above -* clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well +* clean: cleans everything compiled, not downloads (unless not on a checkout) +* deelclean: cleans everything including downloads * code-format: format the code, do this before you commit and send a PR please! * tests: runs test cases to ensure that all features are still working as they should * unit: perform unit tests (based on cmocka) diff --git a/docs/Changelog.md b/docs/Changelog.md index 95adf8ea..30801404 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -19,6 +19,8 @@ sending a mail to . - better submodule handling - all: - fix 32 bit build options + - make clean does not wipe qemu-3.1.1.tar.xz and the unicornafl directory + anymore if in a git/svn checkout unless "deepclean" is used ### Version ++2.64c (release): -- cgit 1.4.1 From 3dbfd18f36ddcc8a64a3ec0e02a364bf83019603 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 20 Apr 2020 21:18:32 +0200 Subject: wording --- docs/Changelog.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 30801404..8f584393 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -19,8 +19,8 @@ sending a mail to . - better submodule handling - all: - fix 32 bit build options - - make clean does not wipe qemu-3.1.1.tar.xz and the unicornafl directory - anymore if in a git/svn checkout unless "deepclean" is used + - make clean now leaves qemu-3.1.1.tar.xz and the unicornafl directory + intact if in a git/svn checkout - unless "deepclean" is used ### Version ++2.64c (release): -- cgit 1.4.1 From b120ca27f86c332854687bb67c4c18d2e6b74ac9 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 23 Apr 2020 12:20:58 +0200 Subject: add documentation for LTO fixed map address feature --- docs/Changelog.md | 4 +++ docs/env_variables.md | 5 +++ llvm_mode/NOTES | 88 ------------------------------------------------- llvm_mode/README.lto.md | 12 +++++++ 4 files changed, 21 insertions(+), 88 deletions(-) delete mode 100644 llvm_mode/NOTES (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index 8f584393..ea669eed 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -17,6 +17,10 @@ sending a mail to . - better dependency checks - unicorn_mode: - better submodule handling + - llvm_mode: + - if LLVM 11 is installed the posix shm_open+mmap is used and a fixed + address for the shared memory map is used as this increases the + fuzzing speed - all: - fix 32 bit build options - make clean now leaves qemu-3.1.1.tar.xz and the unicornafl directory diff --git a/docs/env_variables.md b/docs/env_variables.md index 21bf9fad..f6f14dd2 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -123,6 +123,11 @@ Then there are a few specific features that are only available in llvm_mode: These are used if several seperated instrumentation are performed which are then later combined. + + - AFL_LLVM_MAP_ADDR sets the fixed map address to a different address than + the default 0x10000. A value of 0 or empty sets the map address to be + dynamic (the original afl way, which is slower) + - AFL_LLVM_MAP_DYNAMIC sets the shared memory address to be dynamic - AFL_LLVM_LTO_STARTID sets the starting location ID for the instrumentation. This defaults to 1 - AFL_LLVM_LTO_DONTWRITEID prevents that the highest location ID written diff --git a/llvm_mode/NOTES b/llvm_mode/NOTES deleted file mode 100644 index 9aee7f46..00000000 --- a/llvm_mode/NOTES +++ /dev/null @@ -1,88 +0,0 @@ - -markNodes - -> - -whitelist: - set meta information/context to functions? ask llvm-dev - setAttribute/hasAttribute? - -afl-ld: - handle(=instrument) .a archives on the cmdline - -afl-pass-lto-instrument.so: - either a or b: - a) use instrim - b) start in main() or _init() and first otherwise (warn!) - keep list of done functions - final: go through function list and instrument those missing - - - ---------------------------- - - - -for (auto &module : Ctx.getModules()) { - auto &functionList = module->getModule()->getFunctionList(); - for (auto &function : functionList) { - for (auto &bb : function) { - for (auto &instruction : bb) { - if (CallInst *callInst = dyn_cast(&instruction)) { - if (Function *calledFunction = callInst->getCalledFunction()) { - if (calledFunction->getName().startswith("llvm.dbg.declare")) { - - -for (auto &U : F.getUsers()) { <- unbekannt - if (auto CS = CallSite(U)) { - if (CS->getCalledFunction() == F) - -getCalledValue()->stripPointerCasts() - -> for indirect calls - - -CallGraph(M) - - - -#include "llvm/IR/CallSite.h" - -unsigned int indirect_call_cnt = 0; - - printf("Function: %s\n", F.getName().str().c_str()); - int cnt=0; - for (auto *U : F.users()) { -// auto *I = dyn_cast(U); -// if (I) { -// if (cast(I)->getCalledFunction()->getName() == F.getName()) { -// printf("DIRECT CALL %s->%s->%s\n", cast(I)->getParent()->getParent()->getName().str().c_str(), cast(I)->getCalledFunction()->getName().str().c_str(), F.getName().str().c_str()); -// } -printf("Callsite #%d\n", ++cnt); - CallSite CS(U); - auto *I = CS.getInstruction(); - if (I) { - Value *called = CS.getCalledValue()->stripPointerCasts(); - Function* f = dyn_cast(called); - if (f->getName().size() > 0) { - printf("test %s->%s->%s\n", cast(I)->getParent()->getParent()->getName().str().c_str(), f->getName().str().c_str(), F.getName().str().c_str()); - if (f->getName() == F.getName()) { - printf("CALL %s->%s->%s\n", cast(I)->getParent()->getParent()->getName().str().c_str(), f->getName().str().c_str(), F.getName().str().c_str()); - } - } else - printf("FOO %s->...->%s\n", cast(I)->getParent()->getParent()->getName().str().c_str(), F.getName().str().c_str()); - if (cast(I)->getCalledFunction()->getName() == F.getName()) { - printf("DIRECT %s->%s->%s\n", cast(I)->getParent()->getParent()->getName().str().c_str(), cast(I)->getCalledFunction()->getName().str().c_str(), F.getName().str().c_str()); - } - } else { - printf("WE MISSED SOMETHING HERE!!\n"); - indirect_call_cnt++; - } - } - -oder: - for (auto *U : F.users()) { - if (auto CS = CallSite(U->getUser())) { - if (CS->isCallee(&U)) { - // foo - } - } - } diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 9af9ffff..49407727 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -95,6 +95,18 @@ target binary based on string compare and memory compare functions. afl-fuzz will automatically get these transmitted when starting to fuzz. This improves coverage on a lot of targets. +## Fixed memory map + +To sped 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. +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 (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). + ## Potential issues ### compiling libraries fails -- cgit 1.4.1 From 766085293da050f84a397161e7a84384620956a2 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 24 Apr 2020 12:09:25 +0200 Subject: variable map size fix, error reporting through forkserver, code format --- docs/Changelog.md | 12 ++- include/config.h | 16 +++- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 22 ++--- llvm_mode/afl-llvm-rt.o.c | 122 +++++++++++++++++++-------- src/afl-common.c | 3 +- src/afl-forkserver.c | 53 ++++++++++-- src/afl-fuzz-state.c | 10 ++- src/afl-gcc.c | 17 ++-- test/test-compcov.c | 2 +- 9 files changed, 192 insertions(+), 65 deletions(-) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index ea669eed..e1ca4a10 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -10,6 +10,13 @@ sending a mail to . ### Version ++2.64d (develop): + - afl-fuzz: + - AFL_MAP_SIZE was not working correctly + - llvm_mode: + - if LLVM 11 is installed the posix shm_open+mmap is used and a fixed + address for the shared memory map is used as this increases the + fuzzing speed + - fixes to LTO mode if instrumented edges > MAP_SIZE - qemu_mode: - add information on PIE/PIC load addresses for 32 bit - better dependency checks @@ -17,11 +24,8 @@ sending a mail to . - better dependency checks - unicorn_mode: - better submodule handling - - llvm_mode: - - if LLVM 11 is installed the posix shm_open+mmap is used and a fixed - address for the shared memory map is used as this increases the - fuzzing speed - all: + - forkserver communication now also used for error reporting - fix 32 bit build options - make clean now leaves qemu-3.1.1.tar.xz and the unicornafl directory intact if in a git/svn checkout - unless "deepclean" is used diff --git a/include/config.h b/include/config.h index f11ac919..dca5a8f0 100644 --- a/include/config.h +++ b/include/config.h @@ -402,12 +402,26 @@ /* Extended forkserver option values */ +/* Reporting errors */ +#define FS_OPT_ERROR 0xf800008f +#define FS_OPT_GET_ERROR(x) ((x & 0x00ffff00) >> 8) +#define FS_OPT_SET_ERROR(x) ((x & 0x0000ffff) << 8) +#define FS_ERROR_MAP_SIZE 1 +#define FS_ERROR_MAP_ADDR 2 +#define FS_ERROR_SHM_OPEN 4 +#define FS_ERROR_SHMAT 8 +#define FS_ERROR_MMAP 16 + +/* Reporting options */ #define FS_OPT_ENABLED 0x8f000001 #define FS_OPT_MAPSIZE 0x40000000 #define FS_OPT_SNAPSHOT 0x20000000 #define FS_OPT_AUTODICT 0x10000000 +// FS_OPT_MAX_MAPSIZE is 8388608 = 0x800000 = 2^23 = 1 << 22 +#define FS_OPT_MAX_MAPSIZE ((0x00fffffe >> 1) + 1) #define FS_OPT_GET_MAPSIZE(x) (((x & 0x00fffffe) >> 1) + 1) -#define FS_OPT_SET_MAPSIZE(x) (x <= 1 || x > 0x1000000 ? 0 : ((x - 1) << 1)) +#define FS_OPT_SET_MAPSIZE(x) \ + (x <= 1 || x > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) #endif /* ! _HAVE_CONFIG_H */ diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index dbd4a26e..eefac629 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -679,7 +679,8 @@ bool AFLLTOPass::runOnModule(Module &M) { // save highest location ID to global variable // do this after each function to fail faster - if (!be_quiet && afl_global_id > MAP_SIZE) { + if (!be_quiet && afl_global_id > MAP_SIZE && + afl_global_id > FS_OPT_MAX_MAPSIZE) { uint32_t pow2map = 1, map = afl_global_id; while ((map = map >> 1)) @@ -741,18 +742,13 @@ bool AFLLTOPass::runOnModule(Module &M) { if (afl_global_id % 8) write_loc = (((afl_global_id + 8) >> 3) << 3); - if (write_loc <= MAP_SIZE && write_loc <= 0x800000) { - - GlobalVariable *AFLFinalLoc = new GlobalVariable( - M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, - "__afl_final_loc", 0, GlobalVariable::GeneralDynamicTLSModel, 0, - false); - ConstantInt *const_loc = ConstantInt::get(Int32Ty, write_loc); - StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); - StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(C, None)); - - } + GlobalVariable *AFLFinalLoc = new GlobalVariable( + M, Int32Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_final_loc", + 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); + ConstantInt *const_loc = ConstantInt::get(Int32Ty, write_loc); + StoreInst * StoreFinalLoc = IRB.CreateStore(const_loc, AFLFinalLoc); + StoreFinalLoc->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); } diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 6da41192..8867ae36 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -52,9 +52,9 @@ #define CONST_PRIO 5 -//#ifndef MAP_FIXED_NOREPLACE -//#define MAP_FIXED_NOREPLACE MAP_FIXED -//#endif +#ifndef MAP_FIXED_NOREPLACE +#define MAP_FIXED_NOREPLACE MAP_FIXED +#endif #include #include @@ -73,6 +73,7 @@ u32 __afl_final_loc; u32 __afl_prev_ctx; u32 __afl_cmp_counter; u32 __afl_dictionary_len; +u32 __afl_map_size = MAP_SIZE; u64 __afl_map_addr; #else __thread PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; @@ -80,6 +81,7 @@ __thread u32 __afl_final_loc; __thread u32 __afl_prev_ctx; __thread u32 __afl_cmp_counter; __thread u32 __afl_dictionary_len; +__thread u32 __afl_map_size = MAP_SIZE; __thread u64 __afl_map_addr; #endif @@ -89,20 +91,72 @@ struct cmp_map *__afl_cmp_map; static u8 is_persistent; +/* Error reporting to forkserver controller */ + +void send_forkserver_error(int error) { + + u32 status; + if (!error || error > 0xffff) return; + status = (FS_OPT_ERROR | FS_OPT_SET_ERROR(error)); + if (write(FORKSRV_FD + 1, (char *)&status, 4) != 4) return; + +} + /* SHM setup. */ static void __afl_map_shm(void) { - u8 * id_str = getenv(SHM_ENV_VAR); - unsigned int map_size = MAP_SIZE; + char *id_str = getenv(SHM_ENV_VAR); + + if (__afl_final_loc) { + + __afl_map_size = __afl_final_loc; + if (__afl_final_loc > MAP_SIZE) { + + char *ptr; + u32 val = 0; + if ((ptr = getenv("AFL_MAP_SIZE")) != NULL) val = atoi(ptr); + if (val < __afl_final_loc) { + + if (__afl_final_loc > FS_OPT_MAX_MAPSIZE) { + + fprintf(stderr, + "Error: AFL++ tools *require* to set AFL_MAP_SIZE to %u to " + "be able to run this instrumented program!\n", + __afl_final_loc); + if (id_str) { + + send_forkserver_error(FS_ERROR_MAP_SIZE); + exit(-1); + + } + + } else { + + fprintf(stderr, + "Warning: AFL++ tools will need to set AFL_MAP_SIZE to %u to " + "be able to run this instrumented program!\n", + __afl_final_loc); + + } + + } + + } - if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) - map_size = __afl_final_loc; + } /* If we're running under AFL, attach to the appropriate region, replacing the early-stage __afl_area_initial region that is needed to allow some really hacky .init code to work correctly in projects such as OpenSSL. */ + if (getenv("AFL_DEBUG")) + fprintf(stderr, + "DEBUG: id_str %s, __afl_map_addr 0x%x, MAP_SIZE %u, " + "__afl_final_loc %u, max_size_forkserver %u/0x%x\n", + id_str == NULL ? "" : id_str, __afl_map_addr, MAP_SIZE, + __afl_final_loc, FS_OPT_MAX_MAPSIZE, FS_OPT_MAX_MAPSIZE); + if (id_str) { #ifdef USEMMAP @@ -115,6 +169,7 @@ static void __afl_map_shm(void) { if (shm_fd == -1) { fprintf(stderr, "shm_open() failed\n"); + send_forkserver_error(FS_ERROR_SHM_OPEN); exit(1); } @@ -122,13 +177,14 @@ static void __afl_map_shm(void) { /* map the shared memory segment to the address space of the process */ if (__afl_map_addr) { - shm_base = mmap((void *)__afl_map_addr, map_size, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_SHARED, shm_fd, 0); + shm_base = + mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0); } else { - shm_base = - mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + shm_base = mmap(0, __afl_map_size, PROT_READ | PROT_WRITE, MAP_SHARED, + shm_fd, 0); } @@ -138,6 +194,10 @@ static void __afl_map_shm(void) { shm_fd = -1; fprintf(stderr, "mmap() failed\n"); + if (__afl_map_addr) + send_forkserver_error(FS_ERROR_MAP_ADDR); + else + send_forkserver_error(FS_ERROR_MMAP); exit(2); } @@ -152,7 +212,15 @@ static void __afl_map_shm(void) { /* Whooooops. */ - if (__afl_area_ptr == (void *)-1) _exit(1); + if (__afl_area_ptr == (void *)-1) { + + if (__afl_map_addr) + send_forkserver_error(FS_ERROR_MAP_ADDR); + else + send_forkserver_error(FS_ERROR_SHMAT); + _exit(1); + + } /* Write something into the bitmap so that even with low AFL_INST_RATIO, our parent doesn't give up on us. */ @@ -162,8 +230,8 @@ static void __afl_map_shm(void) { } else if (__afl_map_addr) { __afl_area_ptr = - mmap((void *)__afl_map_addr, map_size, PROT_READ | PROT_WRITE, - MAP_FIXED | MAP_SHARED | MAP_ANONYMOUS, -1, 0); + mmap((void *)__afl_map_addr, __afl_map_size, PROT_READ | PROT_WRITE, + MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); if (__afl_area_ptr == MAP_FAILED) { fprintf(stderr, "can not aquire mmap for address %p\n", @@ -224,13 +292,9 @@ static void __afl_start_snapshots(void) { static u8 tmp[4] = {0, 0, 0, 0}; s32 child_pid; u32 status = 0; - u32 map_size = MAP_SIZE; u32 already_read_first = 0; u32 was_killed; - if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) - map_size = __afl_final_loc; - u8 child_stopped = 0; void (*old_sigchld_handler)(int) = 0; // = signal(SIGCHLD, SIG_DFL); @@ -239,8 +303,8 @@ static void __afl_start_snapshots(void) { assume we're not running in forkserver mode and just execute program. */ status |= (FS_OPT_ENABLED | FS_OPT_SNAPSHOT); - if (map_size <= 0x800000) - status |= (FS_OPT_SET_MAPSIZE(map_size) | FS_OPT_MAPSIZE); + if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) + status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT; memcpy(tmp, &status, 4); @@ -393,19 +457,15 @@ static void __afl_start_forkserver(void) { u8 tmp[4] = {0, 0, 0, 0}; s32 child_pid; u32 status = 0; - u32 map_size = MAP_SIZE; u32 already_read_first = 0; u32 was_killed; - if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) - map_size = __afl_final_loc; - u8 child_stopped = 0; void (*old_sigchld_handler)(int) = 0; // = signal(SIGCHLD, SIG_DFL); - if (map_size <= 0x800000) - status |= (FS_OPT_SET_MAPSIZE(map_size) | FS_OPT_MAPSIZE); + if (__afl_map_size <= FS_OPT_MAX_MAPSIZE) + status |= (FS_OPT_SET_MAPSIZE(__afl_map_size) | FS_OPT_MAPSIZE); if (__afl_dictionary_len > 0 && __afl_dictionary) status |= FS_OPT_AUTODICT; if (status) status |= (FS_OPT_ENABLED); memcpy(tmp, &status, 4); @@ -543,12 +603,8 @@ static void __afl_start_forkserver(void) { int __afl_persistent_loop(unsigned int max_cnt) { - static u8 first_pass = 1; - static u32 cycle_cnt; - unsigned int map_size = MAP_SIZE; - - if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) - map_size = __afl_final_loc; + static u8 first_pass = 1; + static u32 cycle_cnt; if (first_pass) { @@ -559,7 +615,7 @@ int __afl_persistent_loop(unsigned int max_cnt) { if (is_persistent) { - memset(__afl_area_ptr, 0, map_size); + memset(__afl_area_ptr, 0, __afl_map_size); __afl_area_ptr[0] = 1; memset(__afl_prev_loc, 0, NGRAM_SIZE_MAX * sizeof(PREV_LOC_T)); diff --git a/src/afl-common.c b/src/afl-common.c index 8d444876..8ae03113 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -928,7 +928,8 @@ u32 get_map_size() { map_size = atoi(ptr); if (map_size < 8 || map_size > (1 << 29)) { - FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size); + FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 8, + 1 << 29); } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 0c795f9c..555b82a4 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -55,6 +55,8 @@ list_t fsrv_list = {.element_prealloc_count = 0}; +void report_error_and_exit(int error); + static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { execv(fsrv->target_path, argv); @@ -67,7 +69,6 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { // this structure needs default so we initialize it if this was not done // already - fsrv->out_fd = -1; fsrv->out_dir_fd = -1; fsrv->dev_null_fd = -1; @@ -83,7 +84,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) { /* exec related stuff */ fsrv->child_pid = -1; - fsrv->map_size = MAP_SIZE; + fsrv->map_size = get_map_size(); fsrv->use_fauxsrv = 0; fsrv->last_run_timed_out = 0; @@ -201,6 +202,44 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { } +/* Report on the error received via the forkserver controller and exit */ +void report_error_and_exit(int error) { + + switch (error) { + + case FS_ERROR_MAP_SIZE: + FATAL( + "AFL_MAP_SIZE is not set and fuzzing target reports that the " + "required size is very large. Solution: Run the fuzzing target " + "stand-alone with the environment variable AFL_DEBUG=1 set and set " + "the value for __afl_final_loc in the AFL_MAP_SIZE environment " + "variable for afl-fuzz."); + break; + case FS_ERROR_MAP_ADDR: + 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."); + break; + case FS_ERROR_SHM_OPEN: + FATAL("the fuzzing target reports that the shm_open() call failed."); + break; + case FS_ERROR_SHMAT: + FATAL("the fuzzing target reports that the shmat() call failed."); + break; + case FS_ERROR_MMAP: + FATAL( + "the fuzzing target reports that the mmap() call to the share memory " + "failed."); + break; + default: + FATAL("unknown error code %u from fuzzing target!", error); + + } + +} + /* Spins up fork server (instrumented mode only). The idea is explained here: http://lcamtuf.blogspot.com/2014/10/fuzzing-binaries-without-execve.html @@ -400,6 +439,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (!be_quiet) { OKF("All right - fork server is up."); } + if ((status & FS_OPT_ERROR) == FS_OPT_ERROR) + report_error_and_exit(FS_OPT_GET_ERROR(status)); + if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { if (!be_quiet && getenv("AFL_DEBUG")) { @@ -434,9 +476,10 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, FATAL( "Target's coverage map size of %u is larger than the one this " - "afl++ is set with (%u) (change MAP_SIZE_POW2 in config.h and " - "recompile or set AFL_MAP_SIZE)\n", - tmp_map_size, fsrv->map_size); + "afl++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart " + " afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile " + "afl-fuzz", + tmp_map_size, fsrv->map_size, tmp_map_size); } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index b38c9ec5..9f48182b 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -81,7 +81,15 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { and out_size are NULL/0 by default. */ memset(afl, 0, sizeof(afl_state_t)); - if (!map_size) { afl->shm.map_size = MAP_SIZE; } + if (!map_size) { + + afl->shm.map_size = MAP_SIZE; + + } else { + + afl->shm.map_size = map_size; + + } afl->w_init = 0.9; afl->w_end = 0.3; diff --git a/src/afl-gcc.c b/src/afl-gcc.c index ac6fdd62..7eb01c0c 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -157,8 +157,7 @@ static void edit_params(u32 argc, char **argv) { } else { fprintf(stderr, "Name of the binary: %s\n", argv[0]); - FATAL( - "Name of the binary is not a known name, expected afl-clang(++)"); + FATAL("Name of the binary is not a known name, expected afl-clang(++)"); } @@ -173,15 +172,22 @@ static void edit_params(u32 argc, char **argv) { #ifdef __APPLE__ if (!strcmp(name, "afl-g++")) { + cc_params[0] = getenv("AFL_CXX"); + } else if (!strcmp(name, "afl-gcj")) { + cc_params[0] = getenv("AFL_GCJ"); + } else if (!strcmp(name, "afl-gcc")) { + cc_params[0] = getenv("AFL_CC"); + } else { + fprintf(stderr, "Name of the binary: %s\n", argv[0]); - FATAL( - "Name of the binary is not a known name, expected afl-gcc/g++/gcj"); + FATAL("Name of the binary is not a known name, expected afl-gcc/g++/gcj"); + } if (!cc_params[0]) { @@ -218,8 +224,7 @@ static void edit_params(u32 argc, char **argv) { } else { fprintf(stderr, "Name of the binary: %s\n", argv[0]); - FATAL( - "Name of the binary is not a known name, expected afl-gcc/g++/gcj"); + FATAL("Name of the binary is not a known name, expected afl-gcc/g++/gcj"); } diff --git a/test/test-compcov.c b/test/test-compcov.c index 5278af93..c8dd674e 100644 --- a/test/test-compcov.c +++ b/test/test-compcov.c @@ -25,7 +25,7 @@ int main(int argc, char **argv) { printf("your string was bugmenot\n"); else if (strcmp(input, "BUFFEROVERFLOW") == 0) { - buf = (char*)malloc(16); + buf = (char *)malloc(16); strcpy(buf, "TEST"); strcat(buf, input); printf("This will only crash with libdislocator: %s\n", buf); -- cgit 1.4.1 From 07db922024a1faf5543f9d83ce683024e99526ce Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 13:09:27 +0200 Subject: add to changelog --- docs/Changelog.md | 1 + 1 file changed, 1 insertion(+) (limited to 'docs/Changelog.md') diff --git a/docs/Changelog.md b/docs/Changelog.md index e1ca4a10..71de0984 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -12,6 +12,7 @@ sending a mail to . ### Version ++2.64d (develop): - afl-fuzz: - AFL_MAP_SIZE was not working correctly + - better python detection - llvm_mode: - if LLVM 11 is installed the posix shm_open+mmap is used and a fixed address for the shared memory map is used as this increases the -- cgit 1.4.1