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 +++++ include/config.h | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) 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! :) diff --git a/include/config.h b/include/config.h index 1de9973b..f11ac919 100644 --- a/include/config.h +++ b/include/config.h @@ -28,7 +28,7 @@ /* Version string: */ // c = release, d = volatile github dev, e = experimental branch -#define VERSION "++2.64c" +#define VERSION "++2.64d" /****************************************************** * * -- cgit 1.4.1 From 6e753f8f0f91448c3890cbc7b238f4b48d35c009 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Fri, 17 Apr 2020 19:42:03 +0200 Subject: examples Makefiles: silence errors when there is no 32-bit support installed --- examples/argv_fuzzing/Makefile | 4 ++-- examples/socket_fuzzing/Makefile | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/examples/argv_fuzzing/Makefile b/examples/argv_fuzzing/Makefile index cd8ebdbb..5a0ac6e6 100644 --- a/examples/argv_fuzzing/Makefile +++ b/examples/argv_fuzzing/Makefile @@ -44,10 +44,10 @@ M32FLAG=$(___M32FLAG) all: argvfuzz32.so argvfuzz64.so argvfuzz32.so: argvfuzz.c - -$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)" + -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz32 build failure (that's fine)" argvfuzz64.so: argvfuzz.c - -$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz64 build failure (that's fine)" + -@$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "argvfuzz64 build failure (that's fine)" install: argvfuzz32.so argvfuzz64.so install -d -m 755 $(DESTDIR)$(HELPER_PATH)/ diff --git a/examples/socket_fuzzing/Makefile b/examples/socket_fuzzing/Makefile index 03146001..9476e2d5 100644 --- a/examples/socket_fuzzing/Makefile +++ b/examples/socket_fuzzing/Makefile @@ -47,10 +47,10 @@ M32FLAG=$(___M32FLAG) all: socketfuzz32.so socketfuzz64.so socketfuzz32.so: socketfuzz.c - -$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)" + -@$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "socketfuzz32 build failure (that's fine)" socketfuzz64.so: socketfuzz.c - -$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz64 build failure (that's fine)" + -@$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ 2>/dev/null || echo "socketfuzz64 build failure (that's fine)" install: socketfuzz32.so socketfuzz64.so install -d -m 755 $(DESTDIR)$(HELPER_PATH)/ -- cgit 1.4.1 From 269050aee31dc8b349104da11e26de1f615ab668 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 17 Apr 2020 17:49:22 +0200 Subject: submodule --- .gitignore | 1 - .gitmodules | 3 +++ unicorn_mode/build_unicorn_support.sh | 33 ++++++++++++++++++++++----------- unicorn_mode/unicornafl | 1 + 4 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 .gitmodules create mode 160000 unicorn_mode/unicornafl diff --git a/.gitignore b/.gitignore index c8a92b7d..5a7f9408 100644 --- a/.gitignore +++ b/.gitignore @@ -42,7 +42,6 @@ qemu_mode/libcompcov/compcovtest as ld qemu_mode/qemu-* -unicorn_mode/unicornafl/ unicorn_mode/samples/*/\.test-* unicorn_mode/samples/*/output/ core\.* diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..2292a6df --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "unicorn_mode/unicornafl"] + path = unicorn_mode/unicornafl + url = git@github.com:AFLplusplus/unicornafl.git diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 8297e13f..0c84c07b 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -33,7 +33,7 @@ # You must make sure that Unicorn Engine is not already installed before # running this script. If it is, please uninstall it first. -UNICORNAFL_VERSION='afl++2.64c' +UNICORNAFL_VERSION="$(cat ./UNICORNAFL_VERSION)" echo "=================================================" echo "UnicornAFL build script" @@ -146,21 +146,32 @@ fi echo "[+] All checks passed!" echo "[*] Making sure unicornafl is checked out" -rm -rf unicornafl # workaround for travis ... sadly ... -#test -d unicorn && { cd unicorn && { git stash ; git pull ; cd .. ; } } -test -d unicornafl || { - CNT=1 - while [ '!' -d unicornafl -a "$CNT" -lt 4 ]; do - echo "Trying to clone unicornafl (attempt $CNT/3)" - git clone https://github.com/AFLplusplus/unicornafl - CNT=`expr "$CNT" + 1` - done -} + +git status 1>/dev/null 2>/dev/null +if [ $? -eq 0 ]; then + echo "[*] initializing unicornafl submodule" + git submodule init || exit 1 + git submodule update 2>/dev/null # ignore errors +else + echo "[*] cloning unicornafl" + rm -rf unicornafl # workaround for travis ... sadly ... + #test -d unicorn && { cd unicorn && { git stash ; git pull ; cd .. ; } } + test -d unicornafl || { + CNT=1 + while [ '!' -d unicornafl -a "$CNT" -lt 4 ]; do + echo "Trying to clone unicornafl (attempt $CNT/3)" + git clone https://github.com/AFLplusplus/unicornafl + CNT=`expr "$CNT" + 1` + done + } +fi + test -d unicornafl || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; } echo "[+] Got unicornafl." cd "unicornafl" || exit 1 echo "[*] Checking out $UNICORNAFL_VERSION" +sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null git checkout "$UNICORNAFL_VERSION" || exit 1 echo "[*] making sure config.h matches" diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl new file mode 160000 index 00000000..89fd1f66 --- /dev/null +++ b/unicorn_mode/unicornafl @@ -0,0 +1 @@ +Subproject commit 89fd1f66912c8e0918ba0658b16bda204607e44a -- cgit 1.4.1 From 3b8cd9652af2dbfa1cf40cb5f9a7230777339f8f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 17 Apr 2020 17:50:06 +0200 Subject: added version --- unicorn_mode/UNICORNAFL_VERSION | 1 + unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 unicorn_mode/UNICORNAFL_VERSION diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION new file mode 100644 index 00000000..2367cc00 --- /dev/null +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -0,0 +1 @@ +afl++2.64c diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 89fd1f66..214c526e 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 89fd1f66912c8e0918ba0658b16bda204607e44a +Subproject commit 214c526e4ca3adf867057858c909500e0678a789 -- cgit 1.4.1 From 8ffed4b85996cbe07d1d8f4b31f926cfbb842579 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 17 Apr 2020 21:43:42 +0200 Subject: latest unicornafl --- unicorn_mode/unicornafl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 214c526e..89fd1f66 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 214c526e4ca3adf867057858c909500e0678a789 +Subproject commit 89fd1f66912c8e0918ba0658b16bda204607e44a -- cgit 1.4.1 From 46854b439a6ae0e110aaa5c7d455fe1788c0c51b Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 17 Apr 2020 21:44:33 +0200 Subject: unicornafl updaetd --- unicorn_mode/unicornafl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 89fd1f66..4c2bff41 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 89fd1f66912c8e0918ba0658b16bda204607e44a +Subproject commit 4c2bff41deae2701fc3ebc2bba7a16c5f1957130 -- cgit 1.4.1 From 0b5b888f824a41efa61b035d4d4695bc56c5bfc1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Fri, 17 Apr 2020 21:52:57 +0200 Subject: submodule path changed --- .gitmodules | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitmodules b/.gitmodules index 2292a6df..80752342 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "unicorn_mode/unicornafl"] path = unicorn_mode/unicornafl - url = git@github.com:AFLplusplus/unicornafl.git + url = https://github.com/AFLplusplus/unicornafl.git -- cgit 1.4.1 From 9e74a7dfe13b401a07f41719555c287649916d6d Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 18 Apr 2020 10:48:24 +0200 Subject: small portability fix (32-bit) for warning (size_t %lu -> %zu) --- qemu_mode/libcompcov/libcompcov.so.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qemu_mode/libcompcov/libcompcov.so.c b/qemu_mode/libcompcov/libcompcov.so.c index 619bcc50..bffdd5d8 100644 --- a/qemu_mode/libcompcov/libcompcov.so.c +++ b/qemu_mode/libcompcov/libcompcov.so.c @@ -166,7 +166,7 @@ static void __compcov_trace(u64 cur_loc, const u8 *v0, const u8 *v1, size_t n) { if (debug_fd != 1) { char debugbuf[4096]; - snprintf(debugbuf, sizeof(debugbuf), "0x%llx %s %s %lu\n", cur_loc, + snprintf(debugbuf, sizeof(debugbuf), "0x%llx %s %s %zu\n", cur_loc, v0 == NULL ? "(null)" : (char *)v0, v1 == NULL ? "(null)" : (char *)v1, n); write(debug_fd, debugbuf, strlen(debugbuf)); -- 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(-) 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 d9cd600c1bc2292de6d26d0687eb065bf9c138af Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 18 Apr 2020 18:39:03 +0200 Subject: better detection of intel cpu on 32-bit Linux --- GNUmakefile | 2 +- unicorn_mode/unicornafl | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) delete mode 160000 unicorn_mode/unicornafl diff --git a/GNUmakefile b/GNUmakefile index 11dfa803..7c20a172 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -59,7 +59,7 @@ ifneq "$(shell uname)" "Darwin" endif ifneq "$(shell uname -m)" "x86_64" - ifneq "$(shell uname -m)" "i386" + ifneq "$(patsubst i%86,i386,$(shell uname -m))" "i386" ifneq "$(shell uname -m)" "amd64" ifneq "$(shell uname -m)" "i86pc" AFL_NO_X86=1 diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl deleted file mode 160000 index 4c2bff41..00000000 --- a/unicorn_mode/unicornafl +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 4c2bff41deae2701fc3ebc2bba7a16c5f1957130 -- cgit 1.4.1 From 8ed3126f283aefc7cff10add1a5f2432bcdaa2cc Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sat, 18 Apr 2020 20:07:12 +0200 Subject: fix compilation on Debian 32-bit (thanks to Marc) --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 7c20a172..1a694ff3 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -316,7 +316,7 @@ afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) $(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS) afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86 - $(CC) $(CFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS) + $(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS) # document all mutations and only do one run (use with only one input file!) -- cgit 1.4.1 From 2874565b3613caef7490f6e9344cf6d811c0a536 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 18 Apr 2020 21:28:35 +0200 Subject: git for travis? --- .travis.yml | 4 ++-- GNUmakefile | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index e6c6affa..89d72c34 100644 --- a/.travis.yml +++ b/.travis.yml @@ -41,8 +41,8 @@ before_install: # export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE} - echo Testing on $NAME - if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi - - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi - - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi + - if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y git libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi + - if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y git libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi script: - gcc -v diff --git a/GNUmakefile b/GNUmakefile index 1a694ff3..30c37478 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -36,6 +36,7 @@ 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 -- cgit 1.4.1 From 0827a447d3f65b9dca4eba415d068800e6e75b7f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 18 Apr 2020 22:10:30 +0200 Subject: fix submodule --- unicorn_mode/unicornafl | 1 + 1 file changed, 1 insertion(+) create mode 160000 unicorn_mode/unicornafl diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl new file mode 160000 index 00000000..4c2bff41 --- /dev/null +++ b/unicorn_mode/unicornafl @@ -0,0 +1 @@ +Subproject commit 4c2bff41deae2701fc3ebc2bba7a16c5f1957130 -- cgit 1.4.1 From c1d9e00044732c4f51bd87c34308fdc8a7383ff2 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 18 Apr 2020 22:31:21 +0200 Subject: clean no longer deletes unicornafl folder --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 30c37478..c8af3e47 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -416,7 +416,7 @@ clean: $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C src/third_party/libradamsa/ clean - -rm -rf unicorn_mode/unicornafl + $(MAKE) -C unicorn_mode/unicornafl clean distrib: all radamsa -$(MAKE) -C llvm_mode -- cgit 1.4.1 From 8aa86d063a1dcf5762e3a3ee60a2e1f201d9d5ce Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 18 Apr 2020 22:33:56 +0200 Subject: clean doesn't fail without unicornafl --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index c8af3e47..8c71f0e6 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -416,7 +416,7 @@ clean: $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C src/third_party/libradamsa/ clean - $(MAKE) -C unicorn_mode/unicornafl clean + $(MAKE) -C unicorn_mode/unicornafl clean || true distrib: all radamsa -$(MAKE) -C llvm_mode -- cgit 1.4.1 From e4670d3abc25e28cd1bb3fd291ec8f728e47ad5e Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sat, 18 Apr 2020 23:16:00 +0200 Subject: no need to rm folder --- unicorn_mode/build_unicorn_support.sh | 2 -- unicorn_mode/unicornafl | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 0c84c07b..b2ac48f9 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -154,8 +154,6 @@ if [ $? -eq 0 ]; then git submodule update 2>/dev/null # ignore errors else echo "[*] cloning unicornafl" - rm -rf unicornafl # workaround for travis ... sadly ... - #test -d unicorn && { cd unicorn && { git stash ; git pull ; cd .. ; } } test -d unicornafl || { CNT=1 while [ '!' -d unicornafl -a "$CNT" -lt 4 ]; do diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 4c2bff41..89fd1f66 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 4c2bff41deae2701fc3ebc2bba7a16c5f1957130 +Subproject commit 89fd1f66912c8e0918ba0658b16bda204607e44a -- cgit 1.4.1 From 724d4ec3de2e8452ebc36b13747013575c49ca21 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sun, 19 Apr 2020 00:37:23 +0200 Subject: fix some gcc dependencies and build problems on debian 32-Bit, adapted qemu_mode AFL_ENTRYPOINT test case for 32 bit --- qemu_mode/build_qemu_support.sh | 9 ++++++++- qemu_mode/unsigaction/Makefile | 4 ++-- test/test.sh | 24 ++++++++++++++++++++---- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index b34a149b..1b6690c6 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -83,6 +83,13 @@ if [ ! -d "/usr/include/glib-2.0/" -a ! -d "/usr/local/include/glib-2.0/" ]; the fi +if [ ! -d "/usr/include/pixman-1/" -a ! -d "/usr/local/include/pixman-1/" ]; then + + echo "[-] Error: devel version of 'pixman-1' not found, please install first." + PREREQ_NOTFOUND=1 + +fi + if echo "$CC" | grep -qF /afl-; then echo "[-] Error: do not use afl-gcc or afl-clang to compile this tool." @@ -230,7 +237,7 @@ if [ "$ORIG_CPU_TARGET" = "" ]; then make >/dev/null || exit 1 - gcc test-instr.c -o test-instr || exit 1 + cc test-instr.c -o test-instr || exit 1 unset AFL_INST_RATIO export ASAN_OPTIONS=detect_leaks=0 diff --git a/qemu_mode/unsigaction/Makefile b/qemu_mode/unsigaction/Makefile index d5063dab..206a8f07 100644 --- a/qemu_mode/unsigaction/Makefile +++ b/qemu_mode/unsigaction/Makefile @@ -25,10 +25,10 @@ all: $(TARGETS) @if [ "$(AFL_NO_X86)" != "" ]; then echo "[!] Note: skipping compilation of unsigaction (AFL_NO_X86 set)."; fi unsigaction32.so: - @$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi + @if $(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi unsigaction64.so: - $(CC) -m64 -fPIC -shared unsigaction.c -o unsigaction64.so + @if $(CC) -m64 -fPIC -shared unsigaction.c -o unsigaction64.so 2>/dev/null ; then echo "unsigaction64 build success"; else echo "unsigaction64 build failure (that's fine)"; fi clean: rm -f unsigaction32.so unsigaction64.so diff --git a/test/test.sh b/test/test.sh index 9a53825b..5af35ec3 100755 --- a/test/test.sh +++ b/test/test.sh @@ -81,6 +81,8 @@ test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && { } || { AFL_GCC=afl-gcc } +command -v gcc || AFL_GCC=afl-clang + SYS=`uname -m` GREY="\\033[1;90m" @@ -666,8 +668,8 @@ test -z "$AFL_CC" && { $ECHO "$BLUE[*] Testing: qemu_mode" test -e ../afl-qemu-trace && { - gcc -pie -fPIE -o test-instr ../test-instr.c - gcc -o test-compcov test-compcov.c + cc -pie -fPIE -o test-instr ../test-instr.c + cc -o test-compcov test-compcov.c test -e test-instr -a -e test-compcov && { { mkdir -p in @@ -691,7 +693,14 @@ test -e ../afl-qemu-trace && { $ECHO "$GREY[*] running afl-fuzz for qemu_mode AFL_ENTRYPOINT, this will take approx 6 seconds" { { - export AFL_ENTRYPOINT=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//' )` + if file test-instr | grep -q "32-bit"; then + # for 32-bit reduce 8 nibbles to the lower 7 nibbles + ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'` + else + # for 64-bit reduce 16 nibbles to the lower 9 nibbles + ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'` + fi + export AFL_ENTRYPOINT=`expr 0x4${ADDR_LOWER_PART}` $ECHO AFL_ENTRYPOINT=$AFL_ENTRYPOINT - $(nm test-instr | grep "T main") - $(file ./test-instr) ../afl-fuzz -m ${MEM_LIMIT} -V2 -Q -i in -o out -- ./test-instr unset AFL_ENTRYPOINT @@ -759,7 +768,14 @@ test -e ../afl-qemu-trace && { test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && { $ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds" { - export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//' )` + if file test-instr | grep -q "32-bit"; then + # for 32-bit reduce 8 nibbles to the lower 7 nibbles + ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.//'` + else + # for 64-bit reduce 16 nibbles to the lower 9 nibbles + ADDR_LOWER_PART=`nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//'` + fi + export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4${ADDR_LOWER_PART}` export AFL_QEMU_PERSISTENT_GPR=1 $ECHO "Info: AFL_QEMU_PERSISTENT_ADDR=$AFL_QEMU_PERSISTENT_ADDR <= $(nm test-instr | grep "T main" | awk '{print $1}')" env|grep AFL_|sort -- 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(-) 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 baec99079f5bb47b762c4facc0e881a63658a385 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 19 Apr 2020 12:30:58 +0200 Subject: make clean removes unicornafl dir if not in git --- GNUmakefile | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 8c71f0e6..ce3f0aae 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -151,6 +151,11 @@ ifdef NO_PYTHON PYFLAGS= endif +IN_GIT=1 +ifeq "$(shell git status 2>/dev/null)" "" + IN_GIT=0 +endif + ifdef STATIC $(info Compiling static version of binaries) # Disable python for static compilation to simplify things @@ -404,7 +409,18 @@ all_done: test_build .NOTPARALLEL: clean -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 + +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 rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM -$(MAKE) -C llvm_mode clean @@ -416,7 +432,7 @@ clean: $(MAKE) -C qemu_mode/unsigaction clean $(MAKE) -C qemu_mode/libcompcov clean $(MAKE) -C src/third_party/libradamsa/ clean - $(MAKE) -C unicorn_mode/unicornafl clean || true + distrib: all radamsa -$(MAKE) -C llvm_mode -- cgit 1.4.1 From 8197e9b2e44158e65fd778149919e7229c7099c1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 19 Apr 2020 16:42:40 +0200 Subject: clang-tidy readability-braces (#323) --- .clang-format | 2 +- examples/qemu_persistent_hook/test.c | 3 +- include/afl-fuzz.h | 8 +- include/alloc-inl.h | 28 +- include/android-ashmem.h | 2 + include/forkserver.h | 1 + include/list.h | 2 +- libtokencap/libtokencap.so.c | 3 +- llvm_mode/cmplog-instructions-pass.cc | 19 +- llvm_mode/split-compares-pass.so.cc | 41 +- qbdi_mode/demo-so.c | 4 +- qemu_mode/libcompcov/compcovtest.cc | 6 +- qemu_mode/patches/afl-qemu-cpu-translate-inl.h | 34 +- src/afl-analyze.c | 274 +++++++--- src/afl-as.c | 110 ++-- src/afl-common.c | 55 +- src/afl-forkserver.c | 120 +++-- src/afl-fuzz-bitmap.c | 109 ++-- src/afl-fuzz-cmplog.c | 13 +- src/afl-fuzz-extras.c | 180 +++++-- src/afl-fuzz-init.c | 440 +++++++++++----- src/afl-fuzz-mutators.c | 119 ++++- src/afl-fuzz-one.c | 683 +++++++++++++++++-------- src/afl-fuzz-python.c | 66 ++- src/afl-fuzz-queue.c | 207 ++++++-- src/afl-fuzz-redqueen.c | 243 ++++++--- src/afl-fuzz-run.c | 118 +++-- src/afl-fuzz-state.c | 32 +- src/afl-fuzz-stats.c | 220 +++++--- src/afl-fuzz.c | 423 ++++++++++----- src/afl-gcc.c | 59 ++- src/afl-gotcpu.c | 20 +- src/afl-sharedmem.c | 18 +- src/afl-showmap.c | 252 ++++++--- src/afl-tmin.c | 260 ++++++---- 35 files changed, 2909 insertions(+), 1265 deletions(-) diff --git a/.clang-format b/.clang-format index dcf2a476..fd5d9a41 100644 --- a/.clang-format +++ b/.clang-format @@ -10,7 +10,7 @@ AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: true AllowShortBlocksOnASingleLine: true -AllowShortCaseLabelsOnASingleLine: true +AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: false AllowShortIfStatementsOnASingleLine: true AllowShortLoopsOnASingleLine: false diff --git a/examples/qemu_persistent_hook/test.c b/examples/qemu_persistent_hook/test.c index f6672027..afeff202 100644 --- a/examples/qemu_persistent_hook/test.c +++ b/examples/qemu_persistent_hook/test.c @@ -16,7 +16,8 @@ int target_func(unsigned char *buf, int size) { } break; - default: break; + default: + break; } diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 87e6dcff..6c349ea7 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -956,7 +956,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) { static inline u32 get_rand_seed(afl_state_t *afl) { - if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed; + if (unlikely(afl->fixed_seed)) { return (u32)afl->init_seed; } return afl->rand_seed[0]; } @@ -967,8 +967,12 @@ static inline u32 get_rand_seed(afl_state_t *afl) { static inline u64 next_p2(u64 val) { u64 ret = 1; - while (val > ret) + while (val > ret) { + ret <<= 1; + + } + return ret; } diff --git a/include/alloc-inl.h b/include/alloc-inl.h index d16e84bb..e5547fe0 100644 --- a/include/alloc-inl.h +++ b/include/alloc-inl.h @@ -87,7 +87,7 @@ static inline void *DFL_ck_alloc_nozero(u32 size) { void *ret; - if (!size) return NULL; + if (!size) { return NULL; } ALLOC_CHECK_SIZE(size); ret = malloc(size); @@ -103,7 +103,7 @@ static inline void *DFL_ck_alloc(u32 size) { void *mem; - if (!size) return NULL; + if (!size) { return NULL; } mem = DFL_ck_alloc_nozero(size); return memset(mem, 0, size); @@ -115,7 +115,7 @@ static inline void *DFL_ck_alloc(u32 size) { static inline void DFL_ck_free(void *mem) { - if (!mem) return; + if (!mem) { return; } free(mem); @@ -165,7 +165,7 @@ static inline u8 *DFL_ck_strdup(u8 *str) { u8 *ret; u32 size; - if (!str) return NULL; + if (!str) { return NULL; } size = strlen((char *)str) + 1; @@ -184,7 +184,7 @@ static inline void *DFL_ck_memdup(void *mem, u32 size) { void *ret; - if (!mem || !size) return NULL; + if (!mem || !size) { return NULL; } ALLOC_CHECK_SIZE(size); ret = malloc(size); @@ -201,7 +201,7 @@ static inline u8 *DFL_ck_memdup_str(u8 *mem, u32 size) { u8 *ret; - if (!mem || !size) return NULL; + if (!mem || !size) { return NULL; } ALLOC_CHECK_SIZE(size); ret = malloc(size + 1); @@ -772,8 +772,12 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func, */ static inline size_t next_pow2(size_t in) { - if (in == 0 || in > (size_t)-1) + if (in == 0 || in > (size_t)-1) { + return 0; /* avoid undefined behaviour under-/overflow */ + + } + size_t out = in - 1; out |= out >> 1; out |= out >> 2; @@ -794,10 +798,10 @@ static inline size_t next_pow2(size_t in) { static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) { /* No need to realloc */ - if (likely(size_needed && *size >= size_needed)) return *buf; + if (likely(size_needed && *size >= size_needed)) { return *buf; } /* No initial size was set */ - if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + if (size_needed < INITIAL_GROWTH_SIZE) { size_needed = INITIAL_GROWTH_SIZE; } /* grow exponentially */ size_t next_size = next_pow2(size_needed); @@ -824,13 +828,13 @@ static inline void *ck_maybe_grow(void **buf, size_t *size, size_t size_needed) { /* Oops. found a bug? */ - if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size"); + if (unlikely(size_needed < 1)) { FATAL("cannot grow to non-positive size"); } /* No need to realloc */ - if (likely(*size >= size_needed)) return *buf; + if (likely(*size >= size_needed)) { return *buf; } /* No initial size was set */ - if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE; + if (size_needed < INITIAL_GROWTH_SIZE) { size_needed = INITIAL_GROWTH_SIZE; } /* grow exponentially */ size_t next_size = next_pow2(size_needed); diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 6fdcb1ba..5d99dd48 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -109,3 +109,5 @@ static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) { #endif +#endif + diff --git a/include/forkserver.h b/include/forkserver.h index 18a287ad..f07c5104 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -30,6 +30,7 @@ #include #include +#include "types.h" #include "types.h" typedef struct afl_forkserver { diff --git a/include/list.h b/include/list.h index bb985c4f..88cbe062 100644 --- a/include/list.h +++ b/include/list.h @@ -83,7 +83,7 @@ static inline void list_append(list_t *list, void *el) { element_t *el_box = NULL; PRE_ALLOC(el_box, list->element_prealloc_buf, LIST_PREALLOC_SIZE, list->element_prealloc_count); - if (!el_box) FATAL("failed to allocate list element"); + if (!el_box) { FATAL("failed to allocate list element"); } el_box->data = el; el_box->next = head; el_box->prev = head->prev; diff --git a/libtokencap/libtokencap.so.c b/libtokencap/libtokencap.so.c index 758af9c0..1588239c 100644 --- a/libtokencap/libtokencap.so.c +++ b/libtokencap/libtokencap.so.c @@ -274,7 +274,8 @@ static void __tokencap_dump(const u8 *ptr, size_t len, u8 is_text) { pos += 4; break; - default: buf[pos++] = ptr[i]; + default: + buf[pos++] = ptr[i]; } diff --git a/llvm_mode/cmplog-instructions-pass.cc b/llvm_mode/cmplog-instructions-pass.cc index dc72a3e4..b0ab475d 100644 --- a/llvm_mode/cmplog-instructions-pass.cc +++ b/llvm_mode/cmplog-instructions-pass.cc @@ -360,11 +360,20 @@ bool CmpLogInstructions::hookInstrs(Module &M) { switch (max_size) { - case 8: IRB.CreateCall(cmplogHookIns1, args, "tmp"); break; - case 16: IRB.CreateCall(cmplogHookIns2, args, "tmp"); break; - case 32: IRB.CreateCall(cmplogHookIns4, args, "tmp"); break; - case 64: IRB.CreateCall(cmplogHookIns8, args, "tmp"); break; - default: break; + case 8: + IRB.CreateCall(cmplogHookIns1, args, "tmp"); + break; + case 16: + IRB.CreateCall(cmplogHookIns2, args, "tmp"); + break; + case 32: + IRB.CreateCall(cmplogHookIns4, args, "tmp"); + break; + case 64: + IRB.CreateCall(cmplogHookIns8, args, "tmp"); + break; + default: + break; } diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index f0615f85..7c657ebf 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -318,10 +318,18 @@ bool SplitComparesTransform::simplifyCompares(Module &M) { CmpInst::Predicate new_pred; switch (pred) { - case CmpInst::ICMP_UGE: new_pred = CmpInst::ICMP_UGT; break; - case CmpInst::ICMP_SGE: new_pred = CmpInst::ICMP_SGT; break; - case CmpInst::ICMP_ULE: new_pred = CmpInst::ICMP_ULT; break; - case CmpInst::ICMP_SLE: new_pred = CmpInst::ICMP_SLT; break; + case CmpInst::ICMP_UGE: + new_pred = CmpInst::ICMP_UGT; + break; + case CmpInst::ICMP_SGE: + new_pred = CmpInst::ICMP_SGT; + break; + case CmpInst::ICMP_ULE: + new_pred = CmpInst::ICMP_ULT; + break; + case CmpInst::ICMP_SLE: + new_pred = CmpInst::ICMP_SLT; + break; default: // keep the compiler happy continue; @@ -384,10 +392,18 @@ bool SplitComparesTransform::simplifyCompares(Module &M) { CmpInst::Predicate new_pred; switch (pred) { - case CmpInst::FCMP_UGE: new_pred = CmpInst::FCMP_UGT; break; - case CmpInst::FCMP_OGE: new_pred = CmpInst::FCMP_OGT; break; - case CmpInst::FCMP_ULE: new_pred = CmpInst::FCMP_ULT; break; - case CmpInst::FCMP_OLE: new_pred = CmpInst::FCMP_OLT; break; + case CmpInst::FCMP_UGE: + new_pred = CmpInst::FCMP_UGT; + break; + case CmpInst::FCMP_OGE: + new_pred = CmpInst::FCMP_OGT; + break; + case CmpInst::FCMP_ULE: + new_pred = CmpInst::FCMP_ULT; + break; + case CmpInst::FCMP_OLE: + new_pred = CmpInst::FCMP_OLT; + break; default: // keep the compiler happy continue; @@ -855,7 +871,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_exponent_result = BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0); break; - default: continue; + default: + continue; } @@ -958,7 +975,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { icmp_fraction_result = BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0); break; - default: continue; + default: + continue; } @@ -1004,7 +1022,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) { PN->addIncoming(icmp_exponent_result, signequal_bb); PN->addIncoming(icmp_fraction_result, middle_bb); break; - default: continue; + default: + continue; } diff --git a/qbdi_mode/demo-so.c b/qbdi_mode/demo-so.c index dbb7b714..dd367036 100755 --- a/qbdi_mode/demo-so.c +++ b/qbdi_mode/demo-so.c @@ -29,7 +29,9 @@ int target_func(char *buf, int size) { } break; - default: puts("default action"); break; + default: + puts("default action"); + break; } diff --git a/qemu_mode/libcompcov/compcovtest.cc b/qemu_mode/libcompcov/compcovtest.cc index faea75e5..d70bba91 100644 --- a/qemu_mode/libcompcov/compcovtest.cc +++ b/qemu_mode/libcompcov/compcovtest.cc @@ -51,9 +51,11 @@ int main() { switch (z) { - case 0xBEEF: break; + case 0xBEEF: + break; - default: return 4; + default: + return 4; } diff --git a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h index 1abec477..014471ca 100644 --- a/qemu_mode/patches/afl-qemu-cpu-translate-inl.h +++ b/qemu_mode/patches/afl-qemu-cpu-translate-inl.h @@ -55,11 +55,20 @@ static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2, switch (ot & MO_SIZE) { - case MO_64: gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2); break; - case MO_32: gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2); break; - case MO_16: gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2); break; - case MO_8: gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2); break; - default: break; + case MO_64: + gen_helper_afl_cmplog_64(cur_loc_v, arg1, arg2); + break; + case MO_32: + gen_helper_afl_cmplog_32(cur_loc_v, arg1, arg2); + break; + case MO_16: + gen_helper_afl_cmplog_16(cur_loc_v, arg1, arg2); + break; + case MO_8: + gen_helper_afl_cmplog_8(cur_loc_v, arg1, arg2); + break; + default: + break; } @@ -78,10 +87,17 @@ static void afl_gen_compcov(target_ulong cur_loc, TCGv arg1, TCGv arg2, switch (ot & MO_SIZE) { - case MO_64: gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2); break; - case MO_32: gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2); break; - case MO_16: gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2); break; - default: break; + case MO_64: + gen_helper_afl_compcov_64(cur_loc_v, arg1, arg2); + break; + case MO_32: + gen_helper_afl_compcov_32(cur_loc_v, arg1, arg2); + break; + case MO_16: + gen_helper_afl_compcov_16(cur_loc_v, arg1, arg2); + break; + default: + break; } diff --git a/src/afl-analyze.c b/src/afl-analyze.c index b2c0f841..8f48b1d0 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -122,7 +122,7 @@ static void classify_counts(u8 *mem) { while (i--) { - if (*mem) *mem = 1; + if (*mem) { *mem = 1; } mem++; } @@ -147,8 +147,11 @@ static inline u8 anything_set(void) { u32 *ptr = (u32 *)trace_bits; u32 i = (map_size >> 2); - while (i--) - if (*(ptr++)) return 1; + while (i--) { + + if (*(ptr++)) { return 1; } + + } return 0; @@ -169,13 +172,16 @@ static void read_initial_file(void) { struct stat st; s32 fd = open(in_file, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", in_file); + if (fd < 0) { PFATAL("Unable to open '%s'", in_file); } + + if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); } - if (fstat(fd, &st) || !st.st_size) FATAL("Zero-sized input file."); + if (st.st_size >= TMIN_MAX_FILE) { - if (st.st_size >= TMIN_MAX_FILE) FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024); + } + in_len = st.st_size; in_data = ck_alloc_nozero(in_len); @@ -197,7 +203,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); - if (ret < 0) PFATAL("Unable to create '%s'", path); + if (ret < 0) { PFATAL("Unable to create '%s'", path); } ck_write(ret, mem, len, path); @@ -225,7 +231,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { child_pid = fork(); - if (child_pid < 0) PFATAL("fork() failed"); + if (child_pid < 0) { PFATAL("fork() failed"); } if (!child_pid) { @@ -278,7 +284,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { setitimer(ITIMER_REAL, &it, NULL); - if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); + if (waitpid(child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); } child_pid = 0; it.it_value.tv_sec = 0; @@ -290,9 +296,12 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { /* Clean up bitmap, analyze exit condition, etc. */ - if (*(u32 *)trace_bits == EXEC_FAIL_SIG) + if (*(u32 *)trace_bits == EXEC_FAIL_SIG) { + FATAL("Unable to execute '%s'", argv[0]); + } + classify_counts(trace_bits); total_execs++; @@ -325,7 +334,7 @@ static u32 analyze_run_target(char **argv, u8 *mem, u32 len, u8 first_run) { } - if (first_run) orig_cksum = cksum; + if (first_run) { orig_cksum = cksum; } return cksum; @@ -340,9 +349,12 @@ static void show_char(u8 val) { switch (val) { case 0 ... 32: - case 127 ... 255: SAYF("#%02x", val); break; + case 127 ... 255: + SAYF("#%02x", val); + break; - default: SAYF(" %c ", val); + default: + SAYF(" %c ", val); } @@ -387,7 +399,12 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) { while (i + rlen < len && (b_data[i] >> 7) == (b_data[i + rlen] >> 7)) { - if (rtype < (b_data[i + rlen] & 0x0f)) rtype = b_data[i + rlen] & 0x0f; + if (rtype < (b_data[i + rlen] & 0x0f)) { + + rtype = b_data[i + rlen] & 0x0f; + + } + rlen++; } @@ -454,9 +471,11 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) { case 1: case 3: - case 5 ... MAX_AUTO_EXTRA - 1: break; + case 5 ... MAX_AUTO_EXTRA - 1: + break; - default: rtype = RESP_SUSPECT; + default: + rtype = RESP_SUSPECT; } @@ -472,34 +491,58 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) { if (!((i + off) % 16)) { - if (off) SAYF(cRST cLCY ">"); + if (off) { SAYF(cRST cLCY ">"); } + + if (use_hex_offsets) { - if (use_hex_offsets) SAYF(cRST cGRA "%s[%06x] " cRST, (i + off) ? "\n" : "", i + off); - else + + } else { + SAYF(cRST cGRA "%s[%06u] " cRST, (i + off) ? "\n" : "", i + off); + } + } switch (rtype) { - case RESP_NONE: SAYF(cLGR bgGRA); break; - case RESP_MINOR: SAYF(cBRI bgGRA); break; - case RESP_VARIABLE: SAYF(cBLK bgCYA); break; - case RESP_FIXED: SAYF(cBLK bgMGN); break; - case RESP_LEN: SAYF(cBLK bgLGN); break; - case RESP_CKSUM: SAYF(cBLK bgYEL); break; - case RESP_SUSPECT: SAYF(cBLK bgLRD); break; + case RESP_NONE: + SAYF(cLGR bgGRA); + break; + case RESP_MINOR: + SAYF(cBRI bgGRA); + break; + case RESP_VARIABLE: + SAYF(cBLK bgCYA); + break; + case RESP_FIXED: + SAYF(cBLK bgMGN); + break; + case RESP_LEN: + SAYF(cBLK bgLGN); + break; + case RESP_CKSUM: + SAYF(cBLK bgYEL); + break; + case RESP_SUSPECT: + SAYF(cBLK bgLRD); + break; } show_char(in_data[i + off]); - if (off != rlen - 1 && (i + off + 1) % 16) + if (off != rlen - 1 && (i + off + 1) % 16) { + SAYF(" "); - else + + } else { + SAYF(cRST " "); + } + } #else @@ -511,13 +554,27 @@ static void dump_hex(u8 *buf, u32 len, u8 *b_data) { switch (rtype) { - case RESP_NONE: SAYF("no-op block\n"); break; - case RESP_MINOR: SAYF("superficial content\n"); break; - case RESP_VARIABLE: SAYF("critical stream\n"); break; - case RESP_FIXED: SAYF("\"magic value\" section\n"); break; - case RESP_LEN: SAYF("suspected length field\n"); break; - case RESP_CKSUM: SAYF("suspected cksum or magic int\n"); break; - case RESP_SUSPECT: SAYF("suspected checksummed block\n"); break; + case RESP_NONE: + SAYF("no-op block\n"); + break; + case RESP_MINOR: + SAYF("superficial content\n"); + break; + case RESP_VARIABLE: + SAYF("critical stream\n"); + break; + case RESP_FIXED: + SAYF("\"magic value\" section\n"); + break; + case RESP_LEN: + SAYF("suspected length field\n"); + break; + case RESP_CKSUM: + SAYF("suspected cksum or magic int\n"); + break; + case RESP_SUSPECT: + SAYF("suspected checksummed block\n"); + break; } @@ -594,16 +651,21 @@ static void analyze(char **argv) { b_data[i] = RESP_FIXED; - } else + } else { b_data[i] = RESP_VARIABLE; + } + /* When all checksums change, flip most significant bit of b_data. */ if (prev_xff != xor_ff && prev_x01 != xor_01 && prev_s10 != sub_10 && - prev_a10 != add_10) + prev_a10 != add_10) { + seq_byte ^= 0x80; + } + b_data[i] |= seq_byte; prev_xff = xor_ff; @@ -620,10 +682,13 @@ static void analyze(char **argv) { OKF("Analysis complete. Interesting bits: %0.02f%% of the input file.", 100.0 - ((double)boring_len * 100) / in_len); - if (exec_hangs) + if (exec_hangs) { + WARNF(cLRD "Encountered %u timeouts - results may be skewed." cRST, exec_hangs); + } + ck_free(b_data); } @@ -634,7 +699,7 @@ static void handle_stop_sig(int sig) { stop_soon = 1; - if (child_pid > 0) kill(child_pid, SIGKILL); + if (child_pid > 0) { kill(child_pid, SIGKILL); } } @@ -645,7 +710,7 @@ static void set_up_environment(void) { u8 *x; dev_null_fd = open("/dev/null", O_RDWR); - if (dev_null_fd < 0) PFATAL("Unable to open /dev/null"); + if (dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } if (!prog_in) { @@ -654,7 +719,7 @@ static void set_up_environment(void) { if (access(use_dir, R_OK | W_OK | X_OK)) { use_dir = get_afl_env("TMPDIR"); - if (!use_dir) use_dir = "/tmp"; + if (!use_dir) { use_dir = "/tmp"; } } @@ -668,25 +733,37 @@ static void set_up_environment(void) { if (x) { - if (!strstr(x, "abort_on_error=1")) + if (!strstr(x, "abort_on_error=1")) { + FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - if (!strstr(x, "symbolize=0")) + } + + if (!strstr(x, "symbolize=0")) { + FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); + } + } x = get_afl_env("MSAN_OPTIONS"); if (x) { - if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) + if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) { + FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY( MSAN_ERROR) " - please fix!"); - if (!strstr(x, "symbolize=0")) + } + + if (!strstr(x, "symbolize=0")) { + FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); + } + } setenv("ASAN_OPTIONS", @@ -713,20 +790,28 @@ static void set_up_environment(void) { s32 i, afl_preload_size = strlen(afl_preload); for (i = 0; i < afl_preload_size; ++i) { - if (afl_preload[i] == ',') + if (afl_preload[i] == ',') { + PFATAL( "Comma (',') is not allowed in AFL_PRELOAD when -Q is " "specified!"); + } + } - if (qemu_preload) + if (qemu_preload) { + buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", qemu_preload, afl_preload, afl_preload); - else + + } else { + buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", afl_preload, afl_preload); + } + setenv("QEMU_SET_ENV", buf, 1); ck_free(buf); @@ -820,26 +905,26 @@ int main(int argc, char **argv, char **envp) { SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n"); - while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) + while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0) { switch (opt) { case 'i': - if (in_file) FATAL("Multiple -i options not supported"); + if (in_file) { FATAL("Multiple -i options not supported"); } in_file = optarg; break; case 'f': - if (prog_in) FATAL("Multiple -f options not supported"); + if (prog_in) { FATAL("Multiple -f options not supported"); } use_stdin = 0; prog_in = optarg; break; case 'e': - if (edges_only) FATAL("Multiple -e options not supported"); + if (edges_only) { FATAL("Multiple -e options not supported"); } edges_only = 1; break; @@ -847,7 +932,7 @@ int main(int argc, char **argv, char **envp) { u8 suffix = 'M'; - if (mem_limit_given) FATAL("Multiple -m options not supported"); + if (mem_limit_given) { FATAL("Multiple -m options not supported"); } mem_limit_given = 1; if (!optarg) { FATAL("Wrong usage of -m"); } @@ -860,66 +945,83 @@ int main(int argc, char **argv, char **envp) { } if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 || - optarg[0] == '-') + optarg[0] == '-') { + FATAL("Bad syntax used for -m"); + } + switch (suffix) { - case 'T': mem_limit *= 1024 * 1024; break; - case 'G': mem_limit *= 1024; break; - case 'k': mem_limit /= 1024; break; - case 'M': break; + case 'T': + mem_limit *= 1024 * 1024; + break; + case 'G': + mem_limit *= 1024; + break; + case 'k': + mem_limit /= 1024; + break; + case 'M': + break; - default: FATAL("Unsupported suffix or bad syntax for -m"); + default: + FATAL("Unsupported suffix or bad syntax for -m"); } - if (mem_limit < 5) FATAL("Dangerously low value of -m"); + if (mem_limit < 5) { FATAL("Dangerously low value of -m"); } + + if (sizeof(rlim_t) == 4 && mem_limit > 2000) { - if (sizeof(rlim_t) == 4 && mem_limit > 2000) FATAL("Value of -m out of range on 32-bit systems"); + } + } break; case 't': - if (timeout_given) FATAL("Multiple -t options not supported"); + if (timeout_given) { FATAL("Multiple -t options not supported"); } timeout_given = 1; - if (!optarg) FATAL("Wrong usage of -t"); + if (!optarg) { FATAL("Wrong usage of -t"); } exec_tmout = atoi(optarg); - if (exec_tmout < 10 || optarg[0] == '-') + if (exec_tmout < 10 || optarg[0] == '-') { + FATAL("Dangerously low value of -t"); + } + break; case 'Q': - if (qemu_mode) FATAL("Multiple -Q options not supported"); - if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU; + if (qemu_mode) { FATAL("Multiple -Q options not supported"); } + if (!mem_limit_given) { mem_limit = MEM_LIMIT_QEMU; } qemu_mode = 1; break; case 'U': - if (unicorn_mode) FATAL("Multiple -U options not supported"); - if (!mem_limit_given) mem_limit = MEM_LIMIT_UNICORN; + if (unicorn_mode) { FATAL("Multiple -U options not supported"); } + if (!mem_limit_given) { mem_limit = MEM_LIMIT_UNICORN; } unicorn_mode = 1; break; case 'W': /* Wine+QEMU mode */ - if (use_wine) FATAL("Multiple -W options not supported"); + if (use_wine) { FATAL("Multiple -W options not supported"); } qemu_mode = 1; use_wine = 1; - if (!mem_limit_given) mem_limit = 0; + if (!mem_limit_given) { mem_limit = 0; } break; @@ -928,11 +1030,14 @@ int main(int argc, char **argv, char **envp) { return -1; break; - default: usage(argv[0]); + default: + usage(argv[0]); } - if (optind == argc || !in_file) usage(argv[0]); + } + + if (optind == argc || !in_file) { usage(argv[0]); } map_size = get_map_size(); @@ -952,17 +1057,24 @@ int main(int argc, char **argv, char **envp) { if (qemu_mode) { - if (use_wine) + if (use_wine) { + use_argv = get_wine_argv(argv[0], &target_path, argc - optind, argv + optind); - else + + } else { + use_argv = get_qemu_argv(argv[0], &target_path, argc - optind, argv + optind); - } else + } + + } else { use_argv = argv + optind; + } + SAYF("\n"); read_initial_file(); @@ -972,17 +1084,23 @@ int main(int argc, char **argv, char **envp) { analyze_run_target(use_argv, in_data, in_len, 1); - if (child_timed_out) + if (child_timed_out) { + FATAL("Target binary times out (adjusting -t may help)."); - if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) + } + + if (get_afl_env("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) { + FATAL("No instrumentation detected."); + } + analyze(use_argv); OKF("We're done here. Have a nice day!\n"); - if (target_path) ck_free(target_path); + if (target_path) { ck_free(target_path); } afl_shm_deinit(&shm); diff --git a/src/afl-as.c b/src/afl-as.c index d0b61ac1..486a6afa 100644 --- a/src/afl-as.c +++ b/src/afl-as.c @@ -126,9 +126,9 @@ static void edit_params(int argc, char **argv) { is not set. We need to check these non-standard variables to properly handle the pass_thru logic later on. */ - if (!tmp_dir) tmp_dir = getenv("TEMP"); - if (!tmp_dir) tmp_dir = getenv("TMP"); - if (!tmp_dir) tmp_dir = "/tmp"; + if (!tmp_dir) { tmp_dir = getenv("TEMP"); } + if (!tmp_dir) { tmp_dir = getenv("TMP"); } + if (!tmp_dir) { tmp_dir = "/tmp"; } as_params = ck_alloc((argc + 32) * sizeof(u8 *)); @@ -138,11 +138,16 @@ static void edit_params(int argc, char **argv) { for (i = 1; i < argc - 1; i++) { - if (!strcmp(argv[i], "--64")) + if (!strcmp(argv[i], "--64")) { + use_64bit = 1; - else if (!strcmp(argv[i], "--32")) + + } else if (!strcmp(argv[i], "--32")) { + use_64bit = 0; + } + #ifdef __APPLE__ /* The Apple case is a bit different... */ @@ -195,11 +200,16 @@ static void edit_params(int argc, char **argv) { } - if (input_file[1]) + if (input_file[1]) { + FATAL("Incorrect use (not called through afl-gcc?)"); - else + + } else { + input_file = NULL; + } + } else { /* Check if this looks like a standard invocation as a part of an attempt @@ -210,11 +220,16 @@ static void edit_params(int argc, char **argv) { if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) && strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/tmp/", 5) && - getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) + getenv("AFL_AS_FORCE_INSTRUMENT") == NULL) { + pass_thru = 1; - else if (getenv("AFL_AS_FORCE_INSTRUMENT")) + + } else if (getenv("AFL_AS_FORCE_INSTRUMENT")) { + unsetenv("AFL_AS_FORCE_INSTRUMENT"); + } + } modified_file = @@ -251,19 +266,21 @@ static void add_instrumentation(void) { if (input_file) { inf = fopen(input_file, "r"); - if (!inf) PFATAL("Unable to read '%s'", input_file); + if (!inf) { PFATAL("Unable to read '%s'", input_file); } - } else + } else { inf = stdin; + } + outfd = open(modified_file, O_WRONLY | O_EXCL | O_CREAT, 0600); - if (outfd < 0) PFATAL("Unable to write to '%s'", modified_file); + if (outfd < 0) { PFATAL("Unable to write to '%s'", modified_file); } outf = fdopen(outfd, "w"); - if (!outf) PFATAL("fdopen() failed"); + if (!outf) { PFATAL("fdopen() failed"); } while (fgets(line, MAX_LINE, inf)) { @@ -287,7 +304,7 @@ static void add_instrumentation(void) { fputs(line, outf); - if (pass_thru) continue; + if (pass_thru) { continue; } /* All right, this is where the actual fun begins. For one, we only want to instrument the .text section. So, let's keep track of that in processed @@ -300,9 +317,12 @@ static void add_instrumentation(void) { around them, so we use that as a signal. */ if (!clang_mode && instr_ok && !strncmp(line + 2, "p2align ", 8) && - isdigit(line[10]) && line[11] == '\n') + isdigit(line[10]) && line[11] == '\n') { + skip_next_label = 1; + } + if (!strncmp(line + 2, "text\n", 5) || !strncmp(line + 2, "section\t.text", 13) || !strncmp(line + 2, "section\t__TEXT,__text", 21) || @@ -330,23 +350,23 @@ static void add_instrumentation(void) { if (strstr(line, ".code")) { - if (strstr(line, ".code32")) skip_csect = use_64bit; - if (strstr(line, ".code64")) skip_csect = !use_64bit; + if (strstr(line, ".code32")) { skip_csect = use_64bit; } + if (strstr(line, ".code64")) { skip_csect = !use_64bit; } } /* Detect syntax changes, as could happen with hand-written assembly. Skip Intel blocks, resume instrumentation when back to AT&T. */ - if (strstr(line, ".intel_syntax")) skip_intel = 1; - if (strstr(line, ".att_syntax")) skip_intel = 0; + if (strstr(line, ".intel_syntax")) { skip_intel = 1; } + if (strstr(line, ".att_syntax")) { skip_intel = 0; } /* Detect and skip ad-hoc __asm__ blocks, likewise skipping them. */ if (line[0] == '#' || line[1] == '#') { - if (strstr(line, "#APP")) skip_app = 1; - if (strstr(line, "#NO_APP")) skip_app = 0; + if (strstr(line, "#APP")) { skip_app = 1; } + if (strstr(line, "#NO_APP")) { skip_app = 0; } } @@ -375,9 +395,12 @@ static void add_instrumentation(void) { */ if (skip_intel || skip_app || skip_csect || !instr_ok || line[0] == '#' || - line[0] == ' ') + line[0] == ' ') { + continue; + } + /* Conditional branch instruction (jnz, etc). We append the instrumentation right after the branch (to instrument the not-taken path) and at the branch destination label (handled later on). */ @@ -449,11 +472,16 @@ static void add_instrumentation(void) { .Lfunc_begin0-style exception handling calculations (a problem on MacOS X). */ - if (!skip_next_label) + if (!skip_next_label) { + instrument_next = 1; - else + + } else { + skip_next_label = 0; + } + } } else { @@ -468,17 +496,19 @@ static void add_instrumentation(void) { } - if (ins_lines) fputs(use_64bit ? main_payload_64 : main_payload_32, outf); + if (ins_lines) { fputs(use_64bit ? main_payload_64 : main_payload_32, outf); } - if (input_file) fclose(inf); + if (input_file) { fclose(inf); } fclose(outf); if (!be_quiet) { - if (!ins_lines) + if (!ins_lines) { + WARNF("No instrumentation targets found%s.", pass_thru ? " (pass-thru mode)" : ""); - else { + + } else { char modeline[100]; snprintf(modeline, sizeof(modeline), "%s%s%s%s", @@ -514,10 +544,12 @@ int main(int argc, char **argv) { SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n"); - } else + } else { be_quiet = 1; + } + if (argc < 2 || (argc == 2 && strcmp(argv[1], "-h") == 0)) { fprintf( @@ -565,14 +597,20 @@ int main(int argc, char **argv) { if (inst_ratio_str) { - if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) + if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || inst_ratio > 100) { + FATAL("Bad value of AFL_INST_RATIO (must be between 0 and 100)"); + } + } - if (getenv(AS_LOOP_ENV_VAR)) + if (getenv(AS_LOOP_ENV_VAR)) { + FATAL("Endless loop when calling 'as' (remove '.' from your PATH)"); + } + setenv(AS_LOOP_ENV_VAR, "1", 1); /* When compiling with ASAN, we don't have a particularly elegant way to skip @@ -582,11 +620,11 @@ int main(int argc, char **argv) { if (getenv("AFL_USE_ASAN") || getenv("AFL_USE_MSAN")) { sanitizer = 1; - if (!getenv("AFL_INST_RATIO")) inst_ratio /= 3; + if (!getenv("AFL_INST_RATIO")) { inst_ratio /= 3; } } - if (!just_version) add_instrumentation(); + if (!just_version) { add_instrumentation(); } if (!(pid = fork())) { @@ -595,11 +633,11 @@ int main(int argc, char **argv) { } - if (pid < 0) PFATAL("fork() failed"); + if (pid < 0) { PFATAL("fork() failed"); } - if (waitpid(pid, &status, 0) <= 0) PFATAL("waitpid() failed"); + if (waitpid(pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); } - if (!getenv("AFL_KEEP_ASSEMBLY")) unlink(modified_file); + if (!getenv("AFL_KEEP_ASSEMBLY")) { unlink(modified_file); } exit(WEXITSTATUS(status)); diff --git a/src/afl-common.c b/src/afl-common.c index 6ef7a195..1dae8509 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -101,7 +101,7 @@ void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) { if (aa_loc) { - if (!prog_in) FATAL("@@ syntax is not supported by this tool."); + if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); } *use_stdin = 0; @@ -198,7 +198,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { cp = alloc_printf("%s/afl-qemu-trace", tmp); - if (access(cp, X_OK)) FATAL("Unable to find '%s'", tmp); + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } *target_path_p = new_argv[0] = cp; return new_argv; @@ -230,7 +230,7 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) { - if (cp) ck_free(cp); + if (cp) { ck_free(cp); } *target_path_p = new_argv[0] = ck_strdup(BIN_PATH "/afl-qemu-trace"); return new_argv; @@ -277,13 +277,13 @@ char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { cp = alloc_printf("%s/afl-qemu-trace", tmp); - if (access(cp, X_OK)) FATAL("Unable to find '%s'", 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); + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", tmp); } *target_path_p = new_argv[0] = cp; return new_argv; @@ -416,15 +416,22 @@ u8 *find_binary(u8 *fname) { ck_free(cur_elem); if (!stat(target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && st.st_size >= 4) + (st.st_mode & 0111) && st.st_size >= 4) { + break; + } + ck_free(target_path); target_path = NULL; } - if (!target_path) FATAL("Program '%s' not found or not executable", fname); + if (!target_path) { + + FATAL("Program '%s' not found or not executable", fname); + + } } @@ -434,7 +441,7 @@ u8 *find_binary(u8 *fname) { void check_environment_vars(char **envp) { - if (be_quiet) return; + if (be_quiet) { return; } int index = 0, found = 0; char *env, *val; @@ -448,24 +455,30 @@ void check_environment_vars(char **envp) { } else if (strncmp(env, "AFL_", 4) == 0) { int i = 0, match = 0; - while (match == 0 && afl_environment_variables[i] != NULL) + while (match == 0 && afl_environment_variables[i] != NULL) { + if (strncmp(env, afl_environment_variables[i], strlen(afl_environment_variables[i])) == 0 && env[strlen(afl_environment_variables[i])] == '=') { match = 1; - if ((val = getenv(afl_environment_variables[i])) && !*val) + if ((val = getenv(afl_environment_variables[i])) && !*val) { + WARNF( "AFL environment variable %s defined but is empty, this can " "lead to unexpected consequences", afl_environment_variables[i]); + } + } else { i++; } + } + if (match == 0) { WARNF("Mistyped AFL environment variable: %s", env); @@ -477,7 +490,7 @@ void check_environment_vars(char **envp) { } - if (found) sleep(2); + if (found) { sleep(2); } } @@ -485,10 +498,16 @@ char *get_afl_env(char *env) { char *val; - if ((val = getenv(env)) != NULL) - if (!be_quiet) + if ((val = getenv(env)) != NULL) { + + if (!be_quiet) { + OKF("Loaded environment variable %s with value %s", env, val); + } + + } + return val; } @@ -499,7 +518,7 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) { s32 fd = open(fname, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", fname); + if (fd < 0) { PFATAL("Unable to open '%s'", fname); } ck_read(fd, map, len, fname); @@ -906,9 +925,13 @@ u32 get_map_size() { if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) { map_size = atoi(ptr); - if (map_size < 8 || map_size > (1 << 29)) + if (map_size < 8 || map_size > (1 << 29)) { + FATAL("illegal AFL_MAP_SIZE %u, must be between 2^3 and 2^30", map_size); - if (map_size % 8) map_size = (((map_size >> 3) + 1) << 3); + + } + + if (map_size % 8) { map_size = (((map_size >> 3) + 1) << 3); } } diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 9b915a7a..0c795f9c 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -128,12 +128,16 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { unsigned char tmp[4] = {0, 0, 0, 0}; pid_t child_pid = -1; - if (!be_quiet) ACTF("Using Fauxserver:"); + if (!be_quiet) { ACTF("Using Fauxserver:"); } /* Phone home and tell the parent that we're OK. If parent isn't there, assume we're not running in forkserver mode and just execute program. */ - if (write(FORKSRV_FD + 1, tmp, 4) != 4) abort(); // TODO: Abort? + if (write(FORKSRV_FD + 1, tmp, 4) != 4) { + + abort(); // TODO: Abort? + + } void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL); @@ -144,13 +148,13 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { /* Wait for parent by reading from the pipe. Exit if read fails. */ - if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(0); + if (read(FORKSRV_FD, &was_killed, 4) != 4) { exit(0); } /* Create a clone of our process. */ child_pid = fork(); - if (child_pid < 0) PFATAL("Fork failed"); + if (child_pid < 0) { PFATAL("Fork failed"); } /* In child process: close fds, resume execution. */ @@ -177,7 +181,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { /* In parent process: write PID to AFL. */ - if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(0); + if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) { exit(0); } /* after child exited, get and relay exit status to parent through waitpid. */ @@ -191,7 +195,7 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) { /* Relay wait status to AFL pipe, then loop back. */ - if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(0); + if (write(FORKSRV_FD + 1, &status, 4) != 4) { exit(0); } } @@ -212,25 +216,28 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, int status; s32 rlen; - if (!be_quiet) ACTF("Spinning up the fork server..."); + if (!be_quiet) { ACTF("Spinning up the fork server..."); } if (fsrv->use_fauxsrv) { /* TODO: Come up with sone nice way to initalize this all */ - if (fsrv->init_child_func != fsrv_exec_child) + if (fsrv->init_child_func != fsrv_exec_child) { + FATAL("Different forkserver not compatible with fauxserver"); + } + fsrv->init_child_func = afl_fauxsrv_execv; } - if (pipe(st_pipe) || pipe(ctl_pipe)) PFATAL("pipe() failed"); + if (pipe(st_pipe) || pipe(ctl_pipe)) { PFATAL("pipe() failed"); } fsrv->last_run_timed_out = 0; fsrv->fsrv_pid = fork(); - if (fsrv->fsrv_pid < 0) PFATAL("fork() failed"); + if (fsrv->fsrv_pid < 0) { PFATAL("fork() failed"); } if (!fsrv->fsrv_pid) { @@ -295,8 +302,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, /* Set up control and status pipes, close the unneeded original fds. */ - if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) PFATAL("dup2() failed"); - if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) PFATAL("dup2() failed"); + if (dup2(ctl_pipe[0], FORKSRV_FD) < 0) { PFATAL("dup2() failed"); } + if (dup2(st_pipe[1], FORKSRV_FD + 1) < 0) { PFATAL("dup2() failed"); } close(ctl_pipe[0]); close(ctl_pipe[1]); @@ -308,12 +315,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, #ifndef HAVE_ARC4RANDOM close(fsrv->dev_urandom_fd); #endif - if (fsrv->plot_file != NULL) fclose(fsrv->plot_file); + if (fsrv->plot_file != NULL) { fclose(fsrv->plot_file); } /* This should improve performance a bit, since it stops the linker from doing extra work post-fork(). */ - if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); + if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); } /* Set sane defaults for ASAN if nothing else specified. */ @@ -391,17 +398,20 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, if (rlen == 4) { - if (!be_quiet) OKF("All right - fork server is up."); + if (!be_quiet) { OKF("All right - fork server is up."); } if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) { - if (!be_quiet && getenv("AFL_DEBUG")) + if (!be_quiet && getenv("AFL_DEBUG")) { + ACTF("Extended forkserver functions received (%08x).", status); + } + if ((status & FS_OPT_SNAPSHOT) == FS_OPT_SNAPSHOT) { fsrv->snapshot = 1; - if (!be_quiet) ACTF("Using SNAPSHOT feature."); + if (!be_quiet) { ACTF("Using SNAPSHOT feature."); } } @@ -409,7 +419,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, u32 tmp_map_size = FS_OPT_GET_MAPSIZE(status); - if (!fsrv->map_size) fsrv->map_size = MAP_SIZE; + if (!fsrv->map_size) { fsrv->map_size = MAP_SIZE; } if (unlikely(tmp_map_size % 8)) { @@ -419,13 +429,17 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if (!be_quiet) ACTF("Target map size: %u", tmp_map_size); - if (tmp_map_size > fsrv->map_size) + if (!be_quiet) { ACTF("Target map size: %u", tmp_map_size); } + if (tmp_map_size > fsrv->map_size) { + 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); + + } + fsrv->map_size = tmp_map_size; } @@ -436,27 +450,44 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, // this is not afl-fuzz - we deny and return status = (0xffffffff ^ (FS_OPT_ENABLED | FS_OPT_AUTODICT)); - if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + FATAL("Writing to forkserver failed."); + + } + return; } - if (!be_quiet) ACTF("Using AUTODICT feature."); + if (!be_quiet) { ACTF("Using AUTODICT feature."); } status = (FS_OPT_ENABLED | FS_OPT_AUTODICT); - if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) + if (write(fsrv->fsrv_ctl_fd, &status, 4) != 4) { + FATAL("Writing to forkserver failed."); - if (read(fsrv->fsrv_st_fd, &status, 4) != 4) + + } + + if (read(fsrv->fsrv_st_fd, &status, 4) != 4) { + FATAL("Reading from forkserver failed."); - if (status < 2 || (u32)status > 0xffffff) + } + + if (status < 2 || (u32)status > 0xffffff) { + FATAL("Dictionary has an illegal size: %d", status); + } + u32 len = status, offset = 0, count = 0; u8 *dict = ck_alloc(len); - if (dict == NULL) + if (dict == NULL) { + FATAL("Could not allocate %u bytes of autodictionary memory", len); + } + while (len != 0) { rlen = read(fsrv->fsrv_st_fd, dict + offset, len); @@ -486,7 +517,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if (!be_quiet) ACTF("Loaded %u autodictionary entries", count); + if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); } ck_free(dict); } @@ -497,10 +528,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if (fsrv->last_run_timed_out) + if (fsrv->last_run_timed_out) { + FATAL("Timeout while initializing fork server (adjusting -t may help)"); - if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) PFATAL("waitpid() failed"); + } + + if (waitpid(fsrv->fsrv_pid, &status, 0) <= 0) { PFATAL("waitpid() failed"); } if (WIFSIGNALED(status)) { @@ -580,9 +614,12 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, } - if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) + if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) { + FATAL("Unable to execute target application ('%s')", argv[0]); + } + if (fsrv->mem_limit && fsrv->mem_limit < 500 && fsrv->uses_asan) { SAYF("\n" cLRD "[-] " cRST @@ -651,7 +688,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, static void afl_fsrv_kill(afl_forkserver_t *fsrv) { - if (fsrv->child_pid > 0) kill(fsrv->child_pid, SIGKILL); + if (fsrv->child_pid > 0) { kill(fsrv->child_pid, SIGKILL); } if (fsrv->fsrv_pid > 0) { kill(fsrv->fsrv_pid, SIGKILL); @@ -680,7 +717,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { } - if (fd < 0) PFATAL("Unable to create '%s'", fsrv->out_file); + if (fd < 0) { PFATAL("Unable to create '%s'", fsrv->out_file); } } else { @@ -692,7 +729,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) { if (!fsrv->out_file) { - if (ftruncate(fd, len)) PFATAL("ftruncate() failed"); + if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); } lseek(fd, 0, SEEK_SET); } else { @@ -727,7 +764,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if ((res = write(fsrv->fsrv_ctl_fd, &fsrv->last_run_timed_out, 4)) != 4) { - if (*stop_soon_p) return 0; + if (*stop_soon_p) { return 0; } RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } @@ -736,12 +773,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, if ((res = read(fsrv->fsrv_st_fd, &fsrv->child_pid, 4)) != 4) { - if (*stop_soon_p) return 0; + if (*stop_soon_p) { return 0; } RPFATAL(res, "Unable to request new process from fork server (OOM?)"); } - if (fsrv->child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)"); + if (fsrv->child_pid <= 0) { FATAL("Fork server is misbehaving (OOM?)"); } exec_ms = read_timed(fsrv->fsrv_st_fd, &status, 4, timeout, stop_soon_p); @@ -752,13 +789,13 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, kill(fsrv->child_pid, SIGKILL); fsrv->last_run_timed_out = 1; - if (read(fsrv->fsrv_st_fd, &status, 4) < 4) exec_ms = 0; + if (read(fsrv->fsrv_st_fd, &status, 4) < 4) { exec_ms = 0; } } if (!exec_ms) { - if (*stop_soon_p) return 0; + if (*stop_soon_p) { return 0; } SAYF("\n" cLRD "[-] " cRST "Unable to communicate with fork server. Some possible reasons:\n\n" " - You've run out of memory. Use -m to increase the the memory " @@ -784,7 +821,7 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, } - if (!WIFSTOPPED(status)) fsrv->child_pid = 0; + if (!WIFSTOPPED(status)) { fsrv->child_pid = 0; } fsrv->total_execs++; @@ -800,9 +837,12 @@ fsrv_run_result_t afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout, fsrv->last_kill_signal = WTERMSIG(status); - if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) + if (fsrv->last_run_timed_out && fsrv->last_kill_signal == SIGKILL) { + return FSRV_RUN_TMOUT; + } + return FSRV_RUN_CRASH; } diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 0823deed..69fe6562 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -35,13 +35,13 @@ void write_bitmap(afl_state_t *afl) { u8 fname[PATH_MAX]; s32 fd; - if (!afl->bitmap_changed) return; + if (!afl->bitmap_changed) { return; } afl->bitmap_changed = 0; snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir); fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) PFATAL("Unable to open '%s'", fname); + if (fd < 0) { PFATAL("Unable to open '%s'", fname); } ck_write(fd, afl->virgin_bits, afl->fsrv.map_size, fname); @@ -102,11 +102,16 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { (cur[1] && vir[1] == 0xff) || (cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) || (cur[4] && vir[4] == 0xff) || (cur[5] && vir[5] == 0xff) || (cur[6] && vir[6] == 0xff) || - (cur[7] && vir[7] == 0xff)) + (cur[7] && vir[7] == 0xff)) { + ret = 2; - else + + } else { + ret = 1; + } + #else if (*virgin == 0xffffffff || (cur[0] && vir[0] == 0xff) || @@ -129,9 +134,12 @@ u8 has_new_bits(afl_state_t *afl, u8 *virgin_map) { } - if (unlikely(ret) && likely(virgin_map == afl->virgin_bits)) + if (unlikely(ret) && likely(virgin_map == afl->virgin_bits)) { + afl->bitmap_changed = 1; + } + return ret; } @@ -183,11 +191,11 @@ u32 count_bytes(afl_state_t *afl, u8 *mem) { u32 v = *(ptr++); - if (!v) continue; - if (v & 0x000000ff) ++ret; - if (v & 0x0000ff00) ++ret; - if (v & 0x00ff0000) ++ret; - if (v & 0xff000000) ++ret; + if (!v) { continue; } + if (v & 0x000000ff) { ++ret; } + if (v & 0x0000ff00) { ++ret; } + if (v & 0x00ff0000) { ++ret; } + if (v & 0xff000000) { ++ret; } } @@ -211,11 +219,11 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) { /* This is called on the virgin bitmap, so optimize for the most likely case. */ - if (v == 0xffffffff) continue; - if ((v & 0x000000ff) != 0x000000ff) ++ret; - if ((v & 0x0000ff00) != 0x0000ff00) ++ret; - if ((v & 0x00ff0000) != 0x00ff0000) ++ret; - if ((v & 0xff000000) != 0xff000000) ++ret; + if (v == 0xffffffff) { continue; } + if ((v & 0x000000ff) != 0x000000ff) { ++ret; } + if ((v & 0x0000ff00) != 0x0000ff00) { ++ret; } + if ((v & 0x00ff0000) != 0x00ff0000) { ++ret; } + if ((v & 0xff000000) != 0xff000000) { ++ret; } } @@ -257,10 +265,12 @@ void simplify_trace(afl_state_t *afl, u64 *mem) { mem8[6] = simplify_lookup[mem8[6]]; mem8[7] = simplify_lookup[mem8[7]]; - } else + } else { *mem = 0x0101010101010101ULL; + } + ++mem; } @@ -322,11 +332,17 @@ void init_count_class16(void) { u32 b1, b2; - for (b1 = 0; b1 < 256; b1++) - for (b2 = 0; b2 < 256; b2++) + for (b1 = 0; b1 < 256; b1++) { + + for (b2 = 0; b2 < 256; b2++) { + count_class_lookup16[(b1 << 8) + b2] = (count_class_lookup8[b1] << 8) | count_class_lookup8[b2]; + } + + } + } #ifdef WORD_SIZE_64 @@ -397,7 +413,7 @@ void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) { while (i < afl->fsrv.map_size) { - if (*(src++)) dst[i >> 3] |= 1 << (i & 7); + if (*(src++)) { dst[i >> 3] |= 1 << (i & 7); } ++i; } @@ -423,27 +439,35 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) { sprintf(ret + strlen(ret), ",time:%llu", get_cur_time() - afl->start_time); - if (afl->splicing_with >= 0) + if (afl->splicing_with >= 0) { + sprintf(ret + strlen(ret), "+%06d", afl->splicing_with); + } + sprintf(ret + strlen(ret), ",op:%s", afl->stage_short); if (afl->stage_cur_byte >= 0) { sprintf(ret + strlen(ret), ",pos:%d", afl->stage_cur_byte); - if (afl->stage_val_type != STAGE_VAL_NONE) + if (afl->stage_val_type != STAGE_VAL_NONE) { + sprintf(ret + strlen(ret), ",val:%s%+d", (afl->stage_val_type == STAGE_VAL_BE) ? "be:" : "", afl->stage_cur_val); - } else + } + + } else { sprintf(ret + strlen(ret), ",rep:%d", afl->stage_cur_val); + } + } - if (hnb == 2) strcat(ret, ",+cov"); + if (hnb == 2) { strcat(ret, ",+cov"); } return ret; @@ -467,7 +491,7 @@ static void write_crash_readme(afl_state_t *afl) { /* Do not die on errors here - that would be impolite. */ - if (unlikely(fd < 0)) return; + if (unlikely(fd < 0)) { return; } f = fdopen(fd, "w"); @@ -512,7 +536,7 @@ static void write_crash_readme(afl_state_t *afl) { u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { - if (unlikely(len == 0)) return 0; + if (unlikely(len == 0)) { return 0; } u8 *queue_fn = ""; u8 hnb = '\0'; @@ -545,7 +569,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { if (!(hnb = has_new_bits(afl, afl->virgin_bits))) { - if (unlikely(afl->crash_mode)) ++afl->total_crashes; + if (unlikely(afl->crash_mode)) { ++afl->total_crashes; } return 0; } @@ -578,11 +602,14 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0); - if (unlikely(res == FSRV_RUN_ERROR)) + if (unlikely(res == FSRV_RUN_ERROR)) { + FATAL("Unable to execute target application"); + } + fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn); + if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); } ck_write(fd, mem, len, queue_fn); close(fd); @@ -601,7 +628,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { ++afl->total_tmouts; - if (afl->unique_hangs >= KEEP_UNIQUE_HANG) return keeping; + if (afl->unique_hangs >= KEEP_UNIQUE_HANG) { return keeping; } if (likely(!afl->dumb_mode)) { @@ -611,7 +638,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ - if (!has_new_bits(afl, afl->virgin_tmout)) return keeping; + if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; } } @@ -631,9 +658,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { timeout actually uncovers a crash. Make sure we don't discard it if so. */ - if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) goto keep_as_crash; + if (!afl->stop_soon && new_fault == FSRV_RUN_CRASH) { + + goto keep_as_crash; - if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) return keeping; + } + + if (afl->stop_soon || new_fault != FSRV_RUN_TMOUT) { return keeping; } } @@ -665,7 +696,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { ++afl->total_crashes; - if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) return keeping; + if (afl->unique_crashes >= KEEP_UNIQUE_CRASH) { return keeping; } if (likely(!afl->dumb_mode)) { @@ -675,11 +706,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { simplify_trace(afl, (u32 *)afl->fsrv.trace_bits); #endif /* ^WORD_SIZE_64 */ - if (!has_new_bits(afl, afl->virgin_crash)) return keeping; + if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; } } - if (unlikely(!afl->unique_crashes)) write_crash_readme(afl); + if (unlikely(!afl->unique_crashes)) { write_crash_readme(afl); } #ifndef SIMPLE_FILES @@ -715,9 +746,11 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { break; - case FSRV_RUN_ERROR: FATAL("Unable to execute target application"); + case FSRV_RUN_ERROR: + FATAL("Unable to execute target application"); - default: return keeping; + default: + return keeping; } @@ -725,7 +758,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { test case, too. */ fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn); + if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); } ck_write(fd, mem, len, fn); close(fd); diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c index 12c814ba..9452fa90 100644 --- a/src/afl-fuzz-cmplog.c +++ b/src/afl-fuzz-cmplog.c @@ -37,9 +37,12 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) { setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1); - if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) + if (!fsrv->qemu_mode && argv[0] != fsrv->cmplog_binary) { + argv[0] = fsrv->cmplog_binary; + } + execv(argv[0], argv); } @@ -54,7 +57,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { size_t post_len = afl->post_handler(afl->post_data, out_buf, len, &post_buf); - if (!post_buf || !post_len) return 0; + if (!post_buf || !post_len) { return 0; } out_buf = post_buf; len = post_len; @@ -64,7 +67,7 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { fault = fuzz_run_target(afl, &afl->cmplog_fsrv, afl->fsrv.exec_tmout); - if (afl->stop_soon) return 1; + if (afl->stop_soon) { return 1; } if (fault == FSRV_RUN_TMOUT) { @@ -75,10 +78,12 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } - } else + } else { afl->subseq_tmouts = 0; + } + /* Users can hit us with SIGUSR1 to request the current input to be abandoned. */ diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c index c366cc5b..12771cd7 100644 --- a/src/afl-fuzz-extras.c +++ b/src/afl-fuzz-extras.c @@ -59,7 +59,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, f = fopen(fname, "r"); - if (!f) PFATAL("Unable to open '%s'", fname); + if (!f) { PFATAL("Unable to open '%s'", fname); } while ((lptr = fgets(buf, MAX_LINE, f))) { @@ -70,57 +70,79 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, /* Trim on left and right. */ - while (isspace(*lptr)) + while (isspace(*lptr)) { + ++lptr; + } + rptr = lptr + strlen(lptr) - 1; - while (rptr >= lptr && isspace(*rptr)) + while (rptr >= lptr && isspace(*rptr)) { + --rptr; + + } + ++rptr; *rptr = 0; /* Skip empty lines and comments. */ - if (!*lptr || *lptr == '#') continue; + if (!*lptr || *lptr == '#') { continue; } /* All other lines must end with '"', which we can consume. */ --rptr; - if (rptr < lptr || *rptr != '"') + if (rptr < lptr || *rptr != '"') { + FATAL("Malformed name=\"value\" pair in line %u.", cur_line); + } + *rptr = 0; /* Skip alphanumerics and dashes (label). */ - while (isalnum(*lptr) || *lptr == '_') + while (isalnum(*lptr) || *lptr == '_') { + ++lptr; + } + /* If @number follows, parse that. */ if (*lptr == '@') { ++lptr; - if (atoi(lptr) > dict_level) continue; - while (isdigit(*lptr)) + if (atoi(lptr) > dict_level) { continue; } + while (isdigit(*lptr)) { + ++lptr; + } + } /* Skip whitespace and = signs. */ - while (isspace(*lptr) || *lptr == '=') + while (isspace(*lptr) || *lptr == '=') { + ++lptr; + } + /* Consume opening '"'. */ - if (*lptr != '"') + if (*lptr != '"') { + FATAL("Malformed name=\"keyword\" pair in line %u.", cur_line); + } + ++lptr; - if (!*lptr) FATAL("Empty keyword in line %u.", cur_line); + if (!*lptr) { FATAL("Empty keyword in line %u.", cur_line); } /* Okay, let's allocate memory and copy data between "...", handling \xNN escaping, \\, and \". */ @@ -130,7 +152,7 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, wptr = afl->extras[afl->extras_cnt].data = ck_alloc(rptr - lptr); - if (!wptr) PFATAL("no mem for data"); + if (!wptr) { PFATAL("no mem for data"); } while (*lptr) { @@ -154,9 +176,12 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, } - if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) + if (*lptr != 'x' || !isxdigit(lptr[1]) || !isxdigit(lptr[2])) { + FATAL("Invalid escaping (not \\xNN) in line %u.", cur_line); + } + *(wptr++) = ((strchr(hexdigits, tolower(lptr[1])) - hexdigits) << 4) | (strchr(hexdigits, tolower(lptr[2])) - hexdigits); @@ -165,7 +190,9 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, break; - default: *(wptr++) = *(lptr++); ++klen; + default: + *(wptr++) = *(lptr++); + ++klen; } @@ -173,14 +200,17 @@ void load_extras_file(afl_state_t *afl, u8 *fname, u32 *min_len, u32 *max_len, afl->extras[afl->extras_cnt].len = klen; - if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE) + if (afl->extras[afl->extras_cnt].len > MAX_DICT_FILE) { + FATAL( "Keyword too big in line %u (%s, limit is %s)", cur_line, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), klen), stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); - if (*min_len > klen) *min_len = klen; - if (*max_len < klen) *max_len = klen; + } + + if (*min_len > klen) { *min_len = klen; } + if (*max_len < klen) { *max_len = klen; } ++afl->extras_cnt; @@ -227,7 +257,7 @@ void load_extras(afl_state_t *afl, u8 *dir) { } - if (x) FATAL("Dictionary levels not supported for directories."); + if (x) { FATAL("Dictionary levels not supported for directories."); } while ((de = readdir(d))) { @@ -235,7 +265,11 @@ void load_extras(afl_state_t *afl, u8 *dir) { u8 * fn = alloc_printf("%s/%s", dir, de->d_name); s32 fd; - if (lstat(fn, &st) || access(fn, R_OK)) PFATAL("Unable to access '%s'", fn); + if (lstat(fn, &st) || access(fn, R_OK)) { + + PFATAL("Unable to access '%s'", fn); + + } /* This also takes care of . and .. */ if (!S_ISREG(st.st_mode) || !st.st_size) { @@ -245,14 +279,17 @@ void load_extras(afl_state_t *afl, u8 *dir) { } - if (st.st_size > MAX_DICT_FILE) + if (st.st_size > MAX_DICT_FILE) { + FATAL( "Extra '%s' is too big (%s, limit is %s)", fn, stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size), stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE)); - if (min_len > st.st_size) min_len = st.st_size; - if (max_len < st.st_size) max_len = st.st_size; + } + + if (min_len > st.st_size) { min_len = st.st_size; } + if (max_len < st.st_size) { max_len = st.st_size; } afl->extras = ck_realloc_block( afl->extras, (afl->extras_cnt + 1) * sizeof(struct extra_data)); @@ -262,7 +299,7 @@ void load_extras(afl_state_t *afl, u8 *dir) { fd = open(fn, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", fn); + if (fd < 0) { PFATAL("Unable to open '%s'", fn); } ck_read(fd, afl->extras[afl->extras_cnt].data, st.st_size, fn); @@ -277,7 +314,7 @@ void load_extras(afl_state_t *afl, u8 *dir) { check_and_sort: - if (!afl->extras_cnt) FATAL("No usable files in '%s'", dir); + if (!afl->extras_cnt) { FATAL("No usable files in '%s'", dir); } qsort(afl->extras, afl->extras_cnt, sizeof(struct extra_data), compare_extras_len); @@ -286,22 +323,32 @@ check_and_sort: stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), min_len), stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), max_len)); - if (max_len > 32) + if (max_len > 32) { + WARNF("Some tokens are relatively large (%s) - consider trimming.", stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), max_len)); - if (afl->extras_cnt > MAX_DET_EXTRAS) + } + + if (afl->extras_cnt > MAX_DET_EXTRAS) { + WARNF("More than %d tokens - will use them probabilistically.", MAX_DET_EXTRAS); + } + } /* Helper function for maybe_add_auto(afl, ) */ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) { - while (len--) - if (tolower(*(m1++)) ^ tolower(*(m2++))) return 1; + while (len--) { + + if (tolower(*(m1++)) ^ tolower(*(m2++))) { return 1; } + + } + return 0; } @@ -318,14 +365,17 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { /* Allow users to specify that they don't want auto dictionaries. */ - if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) return; + if (!MAX_AUTO_EXTRAS || !USE_AUTO_EXTRAS) { return; } /* Skip runs of identical bytes. */ - for (i = 1; i < len; ++i) - if (mem[0] ^ mem[i]) break; + for (i = 1; i < len; ++i) { + + if (mem[0] ^ mem[i]) { break; } - if (i == len) return; + } + + if (i == len) { return; } /* Reject builtin interesting values. */ @@ -333,33 +383,51 @@ void maybe_add_auto(void *afl_tmp, u8 *mem, u32 len) { i = sizeof(interesting_16) >> 1; - while (i--) + while (i--) { + if (*((u16 *)mem) == interesting_16[i] || - *((u16 *)mem) == SWAP16(interesting_16[i])) + *((u16 *)mem) == SWAP16(interesting_16[i])) { + return; + } + + } + } if (len == 4) { i = sizeof(interesting_32) >> 2; - while (i--) + while (i--) { + if (*((u32 *)mem) == interesting_32[i] || - *((u32 *)mem) == SWAP32(interesting_32[i])) + *((u32 *)mem) == SWAP32(interesting_32[i])) { + return; + } + + } + } /* Reject anything that matches existing extras. Do a case-insensitive match. We optimize by exploiting the fact that extras[] are sorted by size. */ - for (i = 0; i < afl->extras_cnt; ++i) - if (afl->extras[i].len >= len) break; + for (i = 0; i < afl->extras_cnt; ++i) { - for (; i < afl->extras_cnt && afl->extras[i].len == len; ++i) - if (!memcmp_nocase(afl->extras[i].data, mem, len)) return; + if (afl->extras[i].len >= len) { break; } + + } + + for (; i < afl->extras_cnt && afl->extras[i].len == len; ++i) { + + if (!memcmp_nocase(afl->extras[i].data, mem, len)) { return; } + + } /* Last but not least, check afl->a_extras[] for matches. There are no guarantees of a particular sort order. */ @@ -423,7 +491,7 @@ void save_auto(afl_state_t *afl) { u32 i; - if (!afl->auto_changed) return; + if (!afl->auto_changed) { return; } afl->auto_changed = 0; for (i = 0; i < MIN(USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) { @@ -434,7 +502,7 @@ void save_auto(afl_state_t *afl) { fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } ck_write(fd, afl->a_extras[i].data, afl->a_extras[i].len, fn); @@ -461,7 +529,7 @@ void load_auto(afl_state_t *afl) { if (fd < 0) { - if (errno != ENOENT) PFATAL("Unable to open '%s'", fn); + if (errno != ENOENT) { PFATAL("Unable to open '%s'", fn); } ck_free(fn); break; @@ -472,21 +540,29 @@ void load_auto(afl_state_t *afl) { len = read(fd, tmp, MAX_AUTO_EXTRA + 1); - if (len < 0) PFATAL("Unable to read from '%s'", fn); + if (len < 0) { PFATAL("Unable to read from '%s'", fn); } + + if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) { - if (len >= MIN_AUTO_EXTRA && len <= MAX_AUTO_EXTRA) maybe_add_auto((u8 *)afl, tmp, len); + } + close(fd); ck_free(fn); } - if (i) + if (i) { + OKF("Loaded %u auto-discovered dictionary tokens.", i); - else + + } else { + OKF("No auto-generated dictionary tokens to reuse."); + } + } /* Destroy extras. */ @@ -495,14 +571,20 @@ void destroy_extras(afl_state_t *afl) { u32 i; - for (i = 0; i < afl->extras_cnt; ++i) + for (i = 0; i < afl->extras_cnt; ++i) { + ck_free(afl->extras[i].data); + } + ck_free(afl->extras); - for (i = 0; i < afl->a_extras_cnt; ++i) + for (i = 0; i < afl->a_extras_cnt; ++i) { + ck_free(afl->a_extras[i].data); + } + ck_free(afl->a_extras); } diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 3da348d2..4dd31ac9 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -42,7 +42,7 @@ void bind_to_free_cpu(afl_state_t *afl) { u8 cpu_used[4096] = {0}; u32 i; - if (afl->cpu_core_count < 2) return; + if (afl->cpu_core_count < 2) { return; } if (afl->afl_env.afl_no_affinity) { @@ -82,7 +82,7 @@ void bind_to_free_cpu(afl_state_t *afl) { u8 tmp[MAX_LINE]; u8 has_vmsize = 0; - if (!isdigit(de->d_name[0])) continue; + if (!isdigit(de->d_name[0])) { continue; } snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name); @@ -94,7 +94,7 @@ void bind_to_free_cpu(afl_state_t *afl) { /* Processes without VmSize are probably kernel tasks. */ - if (!strncmp(tmp, "VmSize:\t", 8)) has_vmsize = 1; + if (!strncmp(tmp, "VmSize:\t", 8)) { has_vmsize = 1; } if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && !strchr(tmp, '-') && !strchr(tmp, ',') && sscanf(tmp + 19, "%u", &hval) == 1 && @@ -190,8 +190,12 @@ void bind_to_free_cpu(afl_state_t *afl) { try: #ifndef __ANDROID__ - for (i = cpu_start; i < afl->cpu_core_count; i++) - if (!cpu_used[i]) break; + for (i = cpu_start; i < afl->cpu_core_count; i++) { + + if (!cpu_used[i]) { break; } + + } + if (i == afl->cpu_core_count) { #else @@ -229,8 +233,12 @@ void bind_to_free_cpu(afl_state_t *afl) { #if defined(__linux__) if (sched_setaffinity(0, sizeof(c), &c)) { - if (cpu_start == afl->cpu_core_count) + if (cpu_start == afl->cpu_core_count) { + PFATAL("sched_setaffinity failed for CPU %d, exit", i); + + } + WARNF("sched_setaffinity failed to CPU %d, trying next CPU", i); cpu_start++; goto try @@ -282,30 +290,37 @@ void setup_post(afl_state_t *afl) { u32 tlen = 6; strncpy(tbuf, "hello", tlen); - if (!fn) return; + if (!fn) { return; } ACTF("Loading postprocessor from '%s'...", fn); dh = dlopen(fn, RTLD_NOW); - if (!dh) FATAL("%s", dlerror()); + if (!dh) { FATAL("%s", dlerror()); } afl->post_handler = dlsym(dh, "afl_postprocess"); - if (!afl->post_handler) FATAL("Symbol 'afl_postprocess' not found."); + if (!afl->post_handler) { FATAL("Symbol 'afl_postprocess' not found."); } afl->post_init = dlsym(dh, "afl_postprocess_init"); - if (!afl->post_init) FATAL("Symbol 'afl_postprocess_init' not found."); + if (!afl->post_init) { FATAL("Symbol 'afl_postprocess_init' not found."); } afl->post_deinit = dlsym(dh, "afl_postprocess_deinit"); - if (!afl->post_deinit) FATAL("Symbol 'afl_postprocess_deinit' not found."); + if (!afl->post_deinit) { + + FATAL("Symbol 'afl_postprocess_deinit' not found."); + + } /* Do a quick test. It's better to segfault now than later =) */ u8 *post_buf = NULL; afl->post_data = afl->post_init(afl); - if (!afl->post_data) FATAL("Could not initialize post handler."); + if (!afl->post_data) { FATAL("Could not initialize post handler."); } size_t post_len = afl->post_handler(afl->post_data, tbuf, tlen, &post_buf); - if (!post_len || !post_buf) + if (!post_len || !post_buf) { + SAYF("Empty return in test post handler for buf=\"hello\\0\"."); + } + OKF("Postprocessor installed successfully."); } @@ -342,11 +357,16 @@ void read_testcases(afl_state_t *afl) { /* Auto-detect non-in-place resumption attempts. */ fn1 = alloc_printf("%s/queue", afl->in_dir); - if (!access(fn1, F_OK)) + if (!access(fn1, F_OK)) { + afl->in_dir = fn1; - else + + } else { + ck_free(fn1); + } + ACTF("Scanning '%s'...", afl->in_dir); /* We use scandir() + alphasort() rather than readdir() because otherwise, @@ -357,7 +377,7 @@ void read_testcases(afl_state_t *afl) { if (nl_cnt < 0) { - if (errno == ENOENT || errno == ENOTDIR) + if (errno == ENOENT || errno == ENOTDIR) { SAYF("\n" cLRD "[-] " cRST "The input directory does not seem to be valid - try again. The " @@ -368,6 +388,8 @@ void read_testcases(afl_state_t *afl) { "the input\n" " directory.\n"); + } + PFATAL("Unable to open '%s'", afl->in_dir); } @@ -392,9 +414,12 @@ void read_testcases(afl_state_t *afl) { free(nl[i]); /* not tracked */ - if (lstat(fn2, &st) || access(fn2, R_OK)) + if (lstat(fn2, &st) || access(fn2, R_OK)) { + PFATAL("Unable to access '%s'", fn2); + } + /* This also takes care of . and .. */ if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) { @@ -404,17 +429,20 @@ void read_testcases(afl_state_t *afl) { } - if (st.st_size > MAX_FILE) + if (st.st_size > MAX_FILE) { + FATAL("Test case '%s' is too big (%s, limit is %s)", fn2, stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size), stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE)); + } + /* Check for metadata that indicates that deterministic fuzzing is complete for this entry. We don't want to repeat deterministic fuzzing when resuming aborted scans, because it would be pointless and probably very time-consuming. */ - if (!access(dfn, F_OK)) passed_det = 1; + if (!access(dfn, F_OK)) { passed_det = 1; } add_to_queue(afl, fn2, st.st_size, passed_det); @@ -462,29 +490,35 @@ void perform_dry_run(afl_state_t *afl) { ACTF("Attempting dry run with '%s'...", fn); fd = open(q->fname, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", q->fname); + if (fd < 0) { PFATAL("Unable to open '%s'", q->fname); } use_mem = ck_alloc_nozero(q->len); - if (read(fd, use_mem, q->len) != q->len) + if (read(fd, use_mem, q->len) != q->len) { + FATAL("Short read from '%s'", q->fname); + } + close(fd); res = calibrate_case(afl, q, use_mem, 0, 1); ck_free(use_mem); - if (afl->stop_soon) return; + if (afl->stop_soon) { return; } + + if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) { - if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST, q->len, q->bitmap_size, q->exec_us); + } + switch (res) { case FSRV_RUN_OK: - if (afl->crash_mode) FATAL("Test case '%s' does *NOT* crash", fn); + if (afl->crash_mode) { FATAL("Test case '%s' does *NOT* crash", fn); } break; @@ -539,7 +573,7 @@ void perform_dry_run(afl_state_t *afl) { case FSRV_RUN_CRASH: - if (afl->crash_mode) break; + if (afl->crash_mode) { break; } if (skip_crashes) { @@ -635,20 +669,28 @@ void perform_dry_run(afl_state_t *afl) { FATAL("Unable to execute target application ('%s')", afl->argv[0]); - case FSRV_RUN_NOINST: FATAL("No instrumentation detected"); + case FSRV_RUN_NOINST: + FATAL("No instrumentation detected"); case FSRV_RUN_NOBITS: ++afl->useless_at_start; - if (!afl->in_bitmap && !afl->shuffle_queue) + if (!afl->in_bitmap && !afl->shuffle_queue) { + WARNF("No new instrumentation output, test case may be useless."); + } + break; } - if (q->var_behavior) WARNF("Instrumentation output varies across runs."); + if (q->var_behavior) { + + WARNF("Instrumentation output varies across runs."); + + } q = q->next; @@ -656,17 +698,23 @@ void perform_dry_run(afl_state_t *afl) { if (cal_failures) { - if (cal_failures == afl->queued_paths) + if (cal_failures == afl->queued_paths) { + FATAL("All test cases time out%s, giving up!", skip_crashes ? " or crash" : ""); + } + WARNF("Skipped %u test cases (%0.02f%%) due to timeouts%s.", cal_failures, ((double)cal_failures) * 100 / afl->queued_paths, skip_crashes ? " or crashes" : ""); - if (cal_failures * 5 > afl->queued_paths) + if (cal_failures * 5 > afl->queued_paths) { + WARNF(cLRD "High percentage of rejected test cases, check settings!"); + } + } OKF("All test cases processed."); @@ -681,20 +729,23 @@ static void link_or_copy(u8 *old_path, u8 *new_path) { s32 sfd, dfd; u8 *tmp; - if (!i) return; + if (!i) { return; } sfd = open(old_path, O_RDONLY); - if (sfd < 0) PFATAL("Unable to open '%s'", old_path); + if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); } dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (dfd < 0) PFATAL("Unable to create '%s'", new_path); + if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); } tmp = ck_alloc(64 * 1024); - while ((i = read(sfd, tmp, 64 * 1024)) > 0) + while ((i = read(sfd, tmp, 64 * 1024)) > 0) { + ck_write(dfd, tmp, i, new_path); - if (i < 0) PFATAL("read() failed"); + } + + if (i < 0) { PFATAL("read() failed"); } ck_free(tmp); close(sfd); @@ -717,11 +768,16 @@ void pivot_inputs(afl_state_t *afl) { u8 *nfn, *rsl = strrchr(q->fname, '/'); u32 orig_id; - if (!rsl) + if (!rsl) { + rsl = q->fname; - else + + } else { + ++rsl; + } + /* If the original file name conforms to the syntax and the recorded ID matches the one we'd assign, just use the original file name. This is valuable for resuming fuzzing runs. */ @@ -743,11 +799,15 @@ void pivot_inputs(afl_state_t *afl) { if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) { struct queue_entry *s = afl->queue; - while (src_id-- && s) + while (src_id-- && s) { + s = s->next; - if (s) q->depth = s->depth + 1; - if (afl->max_depth < q->depth) afl->max_depth = q->depth; + } + + if (s) { q->depth = s->depth + 1; } + + if (afl->max_depth < q->depth) { afl->max_depth = q->depth; } } @@ -760,10 +820,16 @@ void pivot_inputs(afl_state_t *afl) { u8 *use_name = strstr(rsl, ",orig:"); - if (use_name) + if (use_name) { + use_name += 6; - else + + } else { + use_name = rsl; + + } + nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", afl->out_dir, id, use_name); @@ -783,14 +849,14 @@ void pivot_inputs(afl_state_t *afl) { /* Make sure that the passed_det value carries over, too. */ - if (q->passed_det) mark_as_det_done(afl, q); + if (q->passed_det) { mark_as_det_done(afl, q); } q = q->next; ++id; } - if (afl->in_place_resume) nuke_resume_dir(afl); + if (afl->in_place_resume) { nuke_resume_dir(afl); } } @@ -805,27 +871,32 @@ u32 find_start_position(afl_state_t *afl) { s32 fd, i; u32 ret; - if (!afl->resuming_fuzz) return 0; + if (!afl->resuming_fuzz) { return 0; } + + if (afl->in_place_resume) { - if (afl->in_place_resume) fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); - else + + } else { + fn = alloc_printf("%s/../fuzzer_stats", afl->in_dir); + } + fd = open(fn, O_RDONLY); ck_free(fn); - if (fd < 0) return 0; + if (fd < 0) { return 0; } i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ close(fd); off = strstr(tmp, "cur_path : "); - if (!off) return 0; + if (!off) { return 0; } ret = atoi(off + 20); - if (ret >= afl->queued_paths) ret = 0; + if (ret >= afl->queued_paths) { ret = 0; } return ret; } @@ -842,27 +913,32 @@ void find_timeout(afl_state_t *afl) { s32 fd, i; u32 ret; - if (!afl->resuming_fuzz) return; + if (!afl->resuming_fuzz) { return; } + + if (afl->in_place_resume) { - if (afl->in_place_resume) fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); - else + + } else { + fn = alloc_printf("%s/../fuzzer_stats", afl->in_dir); + } + fd = open(fn, O_RDONLY); ck_free(fn); - if (fd < 0) return; + if (fd < 0) { return; } i = read(fd, tmp, sizeof(tmp) - 1); (void)i; /* Ignore errors */ close(fd); off = strstr(tmp, "exec_timeout : "); - if (!off) return; + if (!off) { return; } ret = atoi(off + 20); - if (ret <= 4) return; + if (ret <= 4) { return; } afl->fsrv.exec_tmout = ret; afl->timeout_given = 3; @@ -879,7 +955,7 @@ static u8 delete_files(u8 *path, u8 *prefix) { d = opendir(path); - if (!d) return 0; + if (!d) { return 0; } while ((d_ent = readdir(d))) { @@ -887,7 +963,7 @@ static u8 delete_files(u8 *path, u8 *prefix) { (!prefix || !strncmp(d_ent->d_name, prefix, strlen(prefix)))) { u8 *fname = alloc_printf("%s/%s", path, d_ent->d_name); - if (unlink(fname)) PFATAL("Unable to delete '%s'", fname); + if (unlink(fname)) { PFATAL("Unable to delete '%s'", fname); } ck_free(fname); } @@ -925,14 +1001,17 @@ double get_runnable_processes(void) { u8 tmp[1024]; u32 val = 0; - if (!f) return 0; + if (!f) { return 0; } while (fgets(tmp, sizeof(tmp), f)) { if (!strncmp(tmp, "procs_running ", 14) || - !strncmp(tmp, "procs_blocked ", 14)) + !strncmp(tmp, "procs_blocked ", 14)) { + val += atoi(tmp + 14); + } + } fclose(f); @@ -961,27 +1040,27 @@ void nuke_resume_dir(afl_state_t *afl) { u8 *fn; fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir); - if (delete_files(fn, "auto_")) goto dir_cleanup_failed; + if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume/.state", afl->out_dir); - if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/_resume", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); return; @@ -1006,7 +1085,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { (this requires leaving the descriptor open).*/ afl->fsrv.out_dir_fd = open(afl->out_dir, O_RDONLY); - if (afl->fsrv.out_dir_fd < 0) PFATAL("Unable to open '%s'", afl->out_dir); + if (afl->fsrv.out_dir_fd < 0) { PFATAL("Unable to open '%s'", afl->out_dir); } #ifndef __sun @@ -1034,9 +1113,12 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (fscanf(f, "start_time : %llu\n" "last_update : %llu\n", - &start_time2, &last_update) != 2) + &start_time2, &last_update) != 2) { + FATAL("Malformed data in '%s'", fn); + } + fclose(f); /* Autoresume treats a normal run as in_place_resume if a valid out dir @@ -1110,7 +1192,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { if (!afl->in_place_resume) { fn = alloc_printf("%s/.synced", afl->out_dir); - if (delete_files(fn, NULL)) goto dir_cleanup_failed; + if (delete_files(fn, NULL)) { goto dir_cleanup_failed; } ck_free(fn); } @@ -1118,30 +1200,30 @@ static void handle_existing_out_dir(afl_state_t *afl) { /* Next, we need to clean up out_dir>/queue/.state/ subdirectories: */ fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir); - if (delete_files(fn, "auto_")) goto dir_cleanup_failed; + if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); /* Then, get rid of the .state subdirectory itself (should be empty by now) and everything matching out_dir>/queue/id:*. */ fn = alloc_printf("%s/queue/.state", afl->out_dir); - if (rmdir(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/queue", afl->out_dir); - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); /* All right, let's do out_dir>/crashes/id:* and @@ -1184,7 +1266,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { } - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/hangs", afl->out_dir); @@ -1215,7 +1297,7 @@ static void handle_existing_out_dir(afl_state_t *afl) { } - if (delete_files(fn, CASE_PREFIX)) goto dir_cleanup_failed; + if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; } ck_free(fn); /* And now, for some finishing touches. */ @@ -1230,27 +1312,27 @@ static void handle_existing_out_dir(afl_state_t *afl) { } - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); if (!afl->in_place_resume) { fn = alloc_printf("%s/fuzzer_stats", afl->out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); } fn = alloc_printf("%s/plot_data", afl->out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); fn = alloc_printf("%s/cmdline", afl->out_dir); - if (unlink(fn) && errno != ENOENT) goto dir_cleanup_failed; + if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; } ck_free(fn); OKF("Output dir cleanup successful."); @@ -1287,28 +1369,37 @@ void setup_dirs_fds(afl_state_t *afl) { ACTF("Setting up output directories..."); - if (afl->sync_id && mkdir(afl->sync_dir, 0700) && errno != EEXIST) + if (afl->sync_id && mkdir(afl->sync_dir, 0700) && errno != EEXIST) { + PFATAL("Unable to create '%s'", afl->sync_dir); + } + if (mkdir(afl->out_dir, 0700)) { - if (errno != EEXIST) PFATAL("Unable to create '%s'", afl->out_dir); + if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); } handle_existing_out_dir(afl); } else { - if (afl->in_place_resume) + if (afl->in_place_resume) { + FATAL("Resume attempted but old output directory not found"); + } + afl->fsrv.out_dir_fd = open(afl->out_dir, O_RDONLY); #ifndef __sun if (afl->fsrv.out_dir_fd < 0 || - flock(afl->fsrv.out_dir_fd, LOCK_EX | LOCK_NB)) + flock(afl->fsrv.out_dir_fd, LOCK_EX | LOCK_NB)) { + PFATAL("Unable to flock() output directory."); + } + #endif /* !__sun */ } @@ -1316,39 +1407,39 @@ void setup_dirs_fds(afl_state_t *afl) { /* Queue directory for any starting & discovered paths. */ tmp = alloc_printf("%s/queue", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* Top-level directory for queue metadata used for session resume and related tasks. */ tmp = alloc_printf("%s/queue/.state/", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* Directory for flagging queue entries that went through deterministic fuzzing in the past. */ tmp = alloc_printf("%s/queue/.state/deterministic_done/", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* Directory with the auto-selected dictionary entries. */ tmp = alloc_printf("%s/queue/.state/auto_extras/", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* The set of paths currently deemed redundant. */ tmp = alloc_printf("%s/queue/.state/redundant_edges/", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* The set of paths showing variable behavior. */ tmp = alloc_printf("%s/queue/.state/variable_behavior/", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* Sync directory for keeping track of cooperating fuzzers. */ @@ -1357,9 +1448,12 @@ void setup_dirs_fds(afl_state_t *afl) { tmp = alloc_printf("%s/.synced/", afl->out_dir); - if (mkdir(tmp, 0700) && (!afl->in_place_resume || errno != EEXIST)) + if (mkdir(tmp, 0700) && (!afl->in_place_resume || errno != EEXIST)) { + PFATAL("Unable to create '%s'", tmp); + } + ck_free(tmp); } @@ -1367,34 +1461,34 @@ void setup_dirs_fds(afl_state_t *afl) { /* All recorded crashes. */ tmp = alloc_printf("%s/crashes", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* All recorded hangs. */ tmp = alloc_printf("%s/hangs", afl->out_dir); - if (mkdir(tmp, 0700)) PFATAL("Unable to create '%s'", tmp); + if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); /* Generally useful file descriptors. */ afl->fsrv.dev_null_fd = open("/dev/null", O_RDWR); - if (afl->fsrv.dev_null_fd < 0) PFATAL("Unable to open /dev/null"); + if (afl->fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } #ifndef HAVE_ARC4RANDOM afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY); - if (afl->fsrv.dev_urandom_fd < 0) PFATAL("Unable to open /dev/urandom"); + if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); } #endif /* Gnuplot output file. */ tmp = alloc_printf("%s/plot_data", afl->out_dir); fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", tmp); + if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); afl->fsrv.plot_file = fdopen(fd, "w"); - if (!afl->fsrv.plot_file) PFATAL("fdopen() failed"); + if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); } fprintf(afl->fsrv.plot_file, "# unix_time, cycles_done, cur_path, paths_total, " @@ -1417,11 +1511,11 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) { /* Store the command line to reproduce our findings */ tmp = alloc_printf("%s/cmdline", afl->out_dir); fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", tmp); + if (fd < 0) { PFATAL("Unable to create '%s'", tmp); } ck_free(tmp); cmdline_file = fdopen(fd, "w"); - if (!cmdline_file) PFATAL("fdopen() failed"); + if (!cmdline_file) { PFATAL("fdopen() failed"); } while (argv[i]) { @@ -1453,7 +1547,7 @@ void setup_stdio_file(afl_state_t *afl) { afl->fsrv.out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600); - if (afl->fsrv.out_fd < 0) PFATAL("Unable to create '%s'", fn); + if (afl->fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fn); } ck_free(fn); @@ -1501,7 +1595,7 @@ void check_crash_handling(void) { s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY); u8 fchar; - if (fd < 0) return; + if (fd < 0) { return; } ACTF("Checking core_pattern..."); @@ -1524,9 +1618,12 @@ void check_crash_handling(void) { " echo core >/proc/sys/kernel/core_pattern\n"); - if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) + if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) { + FATAL("Pipe at the beginning of 'core_pattern'"); + } + } close(fd); @@ -1544,24 +1641,36 @@ void check_cpu_governor(afl_state_t *afl) { u8 tmp[128]; u64 min = 0, max = 0; - if (afl->afl_env.afl_skip_cpufreq) return; + if (afl->afl_env.afl_skip_cpufreq) { return; } + + if (afl->cpu_aff > 0) { - if (afl->cpu_aff > 0) snprintf(tmp, sizeof(tmp), "%s%d%s", "/sys/devices/system/cpu/cpu", afl->cpu_aff, "/cpufreq/scaling_governor"); - else + + } else { + snprintf(tmp, sizeof(tmp), "%s", "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"); + + } + f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r"); if (!f) { - if (afl->cpu_aff > 0) + if (afl->cpu_aff > 0) { + snprintf(tmp, sizeof(tmp), "%s%d%s", "/sys/devices/system/cpu/cpufreq/policy", afl->cpu_aff, "/scaling_governor"); - else + + } else { + snprintf(tmp, sizeof(tmp), "%s", "/sys/devices/system/cpu/cpufreq/policy0/scaling_governor"); + + } + f = fopen(tmp, "r"); } @@ -1575,17 +1684,17 @@ void check_cpu_governor(afl_state_t *afl) { ACTF("Checking CPU scaling governor..."); - if (!fgets(tmp, 128, f)) PFATAL("fgets() failed"); + if (!fgets(tmp, 128, f)) { PFATAL("fgets() failed"); } fclose(f); - if (!strncmp(tmp, "perf", 4)) return; + if (!strncmp(tmp, "perf", 4)) { return; } f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r"); if (f) { - if (fscanf(f, "%llu", &min) != 1) min = 0; + if (fscanf(f, "%llu", &min) != 1) { min = 0; } fclose(f); } @@ -1594,12 +1703,12 @@ void check_cpu_governor(afl_state_t *afl) { if (f) { - if (fscanf(f, "%llu", &max) != 1) max = 0; + if (fscanf(f, "%llu", &max) != 1) { max = 0; } fclose(f); } - if (min == max) return; + if (min == max) { return; } SAYF("\n" cLRD "[-] " cRST "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n" @@ -1752,11 +1861,11 @@ void fix_up_sync(afl_state_t *afl) { u8 *x = afl->sync_id; - if (afl->dumb_mode) FATAL("-S / -M and -n are mutually exclusive"); + if (afl->dumb_mode) { FATAL("-S / -M and -n are mutually exclusive"); } if (afl->skip_deterministic) { - if (afl->force_deterministic) FATAL("use -S instead of -M -d"); + if (afl->force_deterministic) { FATAL("use -S instead of -M -d"); } // else // FATAL("-S already implies -d"); @@ -1764,14 +1873,17 @@ void fix_up_sync(afl_state_t *afl) { while (*x) { - if (!isalnum(*x) && *x != '_' && *x != '-') + if (!isalnum(*x) && *x != '_' && *x != '-') { + FATAL("Non-alphanumeric fuzzer ID specified via -S or -M"); + } + ++x; } - if (strlen(afl->sync_id) > 32) FATAL("Fuzzer ID too long"); + if (strlen(afl->sync_id) > 32) { FATAL("Fuzzer ID too long"); } x = alloc_printf("%s/%s", afl->out_dir, afl->sync_id); @@ -1803,25 +1915,37 @@ void check_asan_opts(void) { if (x) { - if (!strstr(x, "abort_on_error=1")) + if (!strstr(x, "abort_on_error=1")) { + FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - if (!strstr(x, "symbolize=0")) + } + + if (!strstr(x, "symbolize=0")) { + FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); + } + } x = get_afl_env("MSAN_OPTIONS"); if (x) { - if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) + if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) { + FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY( MSAN_ERROR) " - please fix!"); - if (!strstr(x, "symbolize=0")) + } + + if (!strstr(x, "symbolize=0")) { + FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); + } + } } @@ -1868,9 +1992,12 @@ void check_binary(afl_state_t *afl, u8 *fname) { afl->fsrv.target_path = ck_strdup(fname); if (stat(afl->fsrv.target_path, &st) || !S_ISREG(st.st_mode) || - !(st.st_mode & 0111) || (f_len = st.st_size) < 4) + !(st.st_mode & 0111) || (f_len = st.st_size) < 4) { + FATAL("Program '%s' not found or not executable", fname); + } + } else { while (env_path) { @@ -1883,52 +2010,71 @@ void check_binary(afl_state_t *afl, u8 *fname) { memcpy(cur_elem, env_path, delim - env_path); ++delim; - } else + } else { cur_elem = ck_strdup(env_path); + } + env_path = delim; - if (cur_elem[0]) + if (cur_elem[0]) { + afl->fsrv.target_path = alloc_printf("%s/%s", cur_elem, fname); - else + + } else { + afl->fsrv.target_path = ck_strdup(fname); + } + ck_free(cur_elem); if (!stat(afl->fsrv.target_path, &st) && S_ISREG(st.st_mode) && - (st.st_mode & 0111) && (f_len = st.st_size) >= 4) + (st.st_mode & 0111) && (f_len = st.st_size) >= 4) { + break; + } + ck_free(afl->fsrv.target_path); afl->fsrv.target_path = 0; } - if (!afl->fsrv.target_path) + if (!afl->fsrv.target_path) { + FATAL("Program '%s' not found or not executable", fname); + } + } - if (afl->afl_env.afl_skip_bin_check || afl->use_wine) return; + if (afl->afl_env.afl_skip_bin_check || afl->use_wine) { return; } /* Check for blatant user errors. */ if ((!strncmp(afl->fsrv.target_path, "/tmp/", 5) && !strchr(afl->fsrv.target_path + 5, '/')) || (!strncmp(afl->fsrv.target_path, "/var/tmp/", 9) && - !strchr(afl->fsrv.target_path + 9, '/'))) + !strchr(afl->fsrv.target_path + 9, '/'))) { + FATAL("Please don't keep binaries in /tmp or /var/tmp"); + } + fd = open(afl->fsrv.target_path, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", afl->fsrv.target_path); + if (fd < 0) { PFATAL("Unable to open '%s'", afl->fsrv.target_path); } f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0); - if (f_data == MAP_FAILED) + if (f_data == MAP_FAILED) { + PFATAL("Unable to mmap file '%s'", afl->fsrv.target_path); + } + close(fd); if (f_data[0] == '#' && f_data[1] == '!') { @@ -1955,9 +2101,12 @@ void check_binary(afl_state_t *afl, u8 *fname) { #ifndef __APPLE__ - if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) + if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) { + FATAL("Program '%s' is not an ELF binary", afl->fsrv.target_path); + } + #else #if !defined(__arm__) && !defined(__arm64__) @@ -2011,9 +2160,12 @@ void check_binary(afl_state_t *afl, u8 *fname) { } if (memmem(f_data, f_len, "__asan_init", 11) || - memmem(f_data, f_len, "__msan_init", 11)) + memmem(f_data, f_len, "__msan_init", 11)) { + afl->fsrv.uses_asan = 1; + } + /* Detect persistent & deferred init signatures in the binary. */ if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) { @@ -2040,7 +2192,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } - if (munmap(f_data, f_len)) PFATAL("unmap() failed"); + if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); } } @@ -2057,11 +2209,16 @@ void fix_up_banner(afl_state_t *afl, u8 *name) { } else { u8 *trim = strrchr(name, '/'); - if (!trim) + if (!trim) { + afl->use_banner = name; - else + + } else { + afl->use_banner = trim + 1; + } + } } @@ -2152,21 +2309,24 @@ void save_cmdline(afl_state_t *afl, u32 argc, char **argv) { u32 len = 1, i; u8 *buf; - for (i = 0; i < argc; ++i) + for (i = 0; i < argc; ++i) { + len += strlen(argv[i]) + 1; + } + buf = afl->orig_cmdline = ck_alloc(len); for (i = 0; i < argc; ++i) { u32 l = strlen(argv[i]); - if (!argv[i] || !buf) FATAL("null deref detected"); + if (!argv[i] || !buf) { FATAL("null deref detected"); } memcpy(buf, argv[i], l); buf += l; - if (i != argc - 1) *(buf++) = ' '; + if (i != argc - 1) { *(buf++) = ' '; } } diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 434b4673..1a279b2d 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -35,12 +35,15 @@ void setup_custom_mutator(afl_state_t *afl) { if (fn) { - if (afl->limit_time_sig) + if (afl->limit_time_sig) { + FATAL( "MOpt and custom mutator are mutually exclusive. We accept pull " "requests that integrates MOpt with the optional mutators " "(custom/radamsa/redquenn/...)."); + } + load_custom_mutator(afl, fn); return; @@ -53,12 +56,15 @@ void setup_custom_mutator(afl_state_t *afl) { if (module_name) { - if (afl->limit_time_sig) + if (afl->limit_time_sig) { + FATAL( "MOpt and Python mutator are mutually exclusive. We accept pull " "requests that integrates MOpt with the optional mutators " "(custom/radamsa/redqueen/...)."); + } + load_custom_mutator_py(afl, module_name); } @@ -76,7 +82,7 @@ void destroy_custom_mutator(afl_state_t *afl) { afl->mutator->afl_custom_deinit(afl->mutator->data); - if (afl->mutator->dh) dlclose(afl->mutator->dh); + if (afl->mutator->dh) { dlclose(afl->mutator->dh); } if (afl->mutator->pre_save_buf) { @@ -104,20 +110,26 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { ACTF("Loading custom mutator library from '%s'...", fn); dh = dlopen(fn, RTLD_NOW); - if (!dh) FATAL("%s", dlerror()); + if (!dh) { FATAL("%s", dlerror()); } afl->mutator->dh = dh; /* Mutator */ /* "afl_custom_init", required */ afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init"); - if (!afl->mutator->afl_custom_init) + if (!afl->mutator->afl_custom_init) { + FATAL("Symbol 'afl_custom_init' not found."); + } + /* "afl_custom_deinit", required */ afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit"); - if (!afl->mutator->afl_custom_deinit) + if (!afl->mutator->afl_custom_deinit) { + FATAL("Symbol 'afl_custom_deinit' not found."); + } + /* "afl_custom_fuzz" or "afl_custom_mutator", required */ afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz"); if (!afl->mutator->afl_custom_fuzz) { @@ -126,32 +138,47 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { WARNF("Symbol 'afl_custom_fuzz' not found. Try 'afl_custom_mutator'."); afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_mutator"); - if (!afl->mutator->afl_custom_fuzz) + if (!afl->mutator->afl_custom_fuzz) { + FATAL("Symbol 'afl_custom_mutator' not found."); + } + } /* "afl_custom_pre_save", optional */ afl->mutator->afl_custom_pre_save = dlsym(dh, "afl_custom_pre_save"); - if (!afl->mutator->afl_custom_pre_save) + if (!afl->mutator->afl_custom_pre_save) { + WARNF("Symbol 'afl_custom_pre_save' not found."); + } + u8 notrim = 0; /* "afl_custom_init_trim", optional */ afl->mutator->afl_custom_init_trim = dlsym(dh, "afl_custom_init_trim"); - if (!afl->mutator->afl_custom_init_trim) + if (!afl->mutator->afl_custom_init_trim) { + WARNF("Symbol 'afl_custom_init_trim' not found."); + } + /* "afl_custom_trim", optional */ afl->mutator->afl_custom_trim = dlsym(dh, "afl_custom_trim"); - if (!afl->mutator->afl_custom_trim) + if (!afl->mutator->afl_custom_trim) { + WARNF("Symbol 'afl_custom_trim' not found."); + } + /* "afl_custom_post_trim", optional */ afl->mutator->afl_custom_post_trim = dlsym(dh, "afl_custom_post_trim"); - if (!afl->mutator->afl_custom_post_trim) + if (!afl->mutator->afl_custom_post_trim) { + WARNF("Symbol 'afl_custom_post_trim' not found."); + } + if (notrim) { afl->mutator->afl_custom_init_trim = NULL; @@ -166,33 +193,48 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) { /* "afl_custom_havoc_mutation", optional */ afl->mutator->afl_custom_havoc_mutation = dlsym(dh, "afl_custom_havoc_mutation"); - if (!afl->mutator->afl_custom_havoc_mutation) + if (!afl->mutator->afl_custom_havoc_mutation) { + WARNF("Symbol 'afl_custom_havoc_mutation' not found."); + } + /* "afl_custom_havoc_mutation", optional */ afl->mutator->afl_custom_havoc_mutation_probability = dlsym(dh, "afl_custom_havoc_mutation_probability"); - if (!afl->mutator->afl_custom_havoc_mutation_probability) + if (!afl->mutator->afl_custom_havoc_mutation_probability) { + WARNF("Symbol 'afl_custom_havoc_mutation_probability' not found."); + } + /* "afl_custom_queue_get", optional */ afl->mutator->afl_custom_queue_get = dlsym(dh, "afl_custom_queue_get"); - if (!afl->mutator->afl_custom_queue_get) + if (!afl->mutator->afl_custom_queue_get) { + WARNF("Symbol 'afl_custom_queue_get' not found."); + } + /* "afl_custom_queue_new_entry", optional */ afl->mutator->afl_custom_queue_new_entry = dlsym(dh, "afl_custom_queue_new_entry"); - if (!afl->mutator->afl_custom_queue_new_entry) + if (!afl->mutator->afl_custom_queue_new_entry) { + WARNF("Symbol 'afl_custom_queue_new_entry' not found"); + } + OKF("Custom mutator '%s' installed successfully.", fn); /* Initialize the custom mutator */ - if (afl->mutator->afl_custom_init) + if (afl->mutator->afl_custom_init) { + afl->mutator->data = afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF)); + } + } u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { @@ -210,12 +252,19 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { afl->stage_cur = 0; afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len); - if (unlikely(afl->stage_max) < 0) + if (unlikely(afl->stage_max) < 0) { + FATAL("custom_init_trim error ret: %d", afl->stage_max); - if (afl->not_on_tty && afl->debug) + + } + + if (afl->not_on_tty && afl->debug) { + SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max, q->len); + } + while (afl->stage_cur < afl->stage_max) { u8 *retbuf = NULL; @@ -227,13 +276,18 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf); - if (unlikely(!retbuf)) + if (unlikely(!retbuf)) { + FATAL("custom_trim failed (ret %zd)", retlen); - else if (unlikely(retlen > orig_len)) + + } else if (unlikely(retlen > orig_len)) { + FATAL( "Trimmed data returned by custom mutator is larger than original " "data"); + } + write_to_testcase(afl, retbuf, retlen); fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); @@ -263,32 +317,45 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 1); - if (afl->not_on_tty && afl->debug) + if (afl->not_on_tty && afl->debug) { + SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)", afl->stage_cur, afl->stage_max, q->len); + } + } else { /* Tell the custom mutator that the trimming was unsuccessful */ afl->stage_cur = afl->mutator->afl_custom_post_trim(afl->mutator->data, 0); - if (unlikely(afl->stage_cur < 0)) + if (unlikely(afl->stage_cur < 0)) { + FATAL("Error ret in custom_post_trim: %d", afl->stage_cur); - if (afl->not_on_tty && afl->debug) + + } + + if (afl->not_on_tty && afl->debug) { + SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur, afl->stage_max); + } + } /* Since this can be slow, update the screen every now and then. */ - if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl); + if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } } - if (afl->not_on_tty && afl->debug) + if (afl->not_on_tty && afl->debug) { + SAYF("[Custom Trimming] DONE: %u bytes -> %u bytes", orig_len, q->len); + } + /* If we have made changes to in_buf, we also need to update the on-disk version of the test case. */ @@ -300,7 +367,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", q->fname); + if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } ck_write(fd, in_buf, q->len, q->fname); close(fd); diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index a4ba739e..6d399a03 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -37,7 +37,7 @@ static int select_algorithm(afl_state_t *afl) { if (unlikely(i_puppet == 0)) { - if (sele < afl->probability_now[afl->swarm_now][i_puppet]) break; + if (sele < afl->probability_now[afl->swarm_now][i_puppet]) { break; } } else { @@ -53,8 +53,12 @@ static int select_algorithm(afl_state_t *afl) { } if (j_puppet == 1 && - sele < afl->probability_now[afl->swarm_now][i_puppet - 1]) + sele < afl->probability_now[afl->swarm_now][i_puppet - 1]) { + FATAL("error select_algorithm"); + + } + return i_puppet; } @@ -67,7 +71,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) { u32 min_value, max_value; u32 rlim = MIN(afl->queue_cycle, 3); - if (unlikely(!afl->run_over10m)) rlim = 1; + if (unlikely(!afl->run_over10m)) { rlim = 1; } switch (rand_below(afl, rlim)) { @@ -97,7 +101,7 @@ static u32 choose_block_len(afl_state_t *afl, u32 limit) { } - if (min_value >= limit) min_value = 1; + if (min_value >= limit) { min_value = 1; } return min_value + rand_below(afl, MIN(max_value, limit) - min_value + 1); @@ -114,7 +118,7 @@ static u8 could_be_bitflip(u32 xor_val) { u32 sh = 0; - if (!xor_val) return 1; + if (!xor_val) { return 1; } /* Shift left until first bit set. */ @@ -127,14 +131,18 @@ static u8 could_be_bitflip(u32 xor_val) { /* 1-, 2-, and 4-bit patterns are OK anywhere. */ - if (xor_val == 1 || xor_val == 3 || xor_val == 15) return 1; + if (xor_val == 1 || xor_val == 3 || xor_val == 15) { return 1; } /* 8-, 16-, and 32-bit patterns are OK only if shift factor is divisible by 8, since that's the stepover for these ops. */ - if (sh & 7) return 0; + if (sh & 7) { return 0; } + + if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) { - if (xor_val == 0xff || xor_val == 0xffff || xor_val == 0xffffffff) return 1; + return 1; + + } return 0; @@ -147,7 +155,7 @@ static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { u32 i, ov = 0, nv = 0, diffs = 0; - if (old_val == new_val) return 1; + if (old_val == new_val) { return 1; } /* See if one-byte adjustments to any byte could produce this result. */ @@ -169,11 +177,11 @@ static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { if (diffs == 1) { - if ((u8)(ov - nv) <= ARITH_MAX || (u8)(nv - ov) <= ARITH_MAX) return 1; + if ((u8)(ov - nv) <= ARITH_MAX || (u8)(nv - ov) <= ARITH_MAX) { return 1; } } - if (blen == 1) return 0; + if (blen == 1) { return 0; } /* See if two-byte adjustments to any byte would produce this result. */ @@ -197,12 +205,20 @@ static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { if (diffs == 1) { - if ((u16)(ov - nv) <= ARITH_MAX || (u16)(nv - ov) <= ARITH_MAX) return 1; + if ((u16)(ov - nv) <= ARITH_MAX || (u16)(nv - ov) <= ARITH_MAX) { + + return 1; + + } ov = SWAP16(ov); nv = SWAP16(nv); - if ((u16)(ov - nv) <= ARITH_MAX || (u16)(nv - ov) <= ARITH_MAX) return 1; + if ((u16)(ov - nv) <= ARITH_MAX || (u16)(nv - ov) <= ARITH_MAX) { + + return 1; + + } } @@ -211,16 +227,22 @@ static u8 could_be_arith(u32 old_val, u32 new_val, u8 blen) { if (blen == 4) { if ((u32)(old_val - new_val) <= ARITH_MAX || - (u32)(new_val - old_val) <= ARITH_MAX) + (u32)(new_val - old_val) <= ARITH_MAX) { + return 1; + } + new_val = SWAP32(new_val); old_val = SWAP32(old_val); if ((u32)(old_val - new_val) <= ARITH_MAX || - (u32)(new_val - old_val) <= ARITH_MAX) + (u32)(new_val - old_val) <= ARITH_MAX) { + return 1; + } + } return 0; @@ -237,7 +259,7 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { u32 i, j; - if (old_val == new_val) return 1; + if (old_val == new_val) { return 1; } /* See if one-byte insertions from interesting_8 over old_val could produce new_val. */ @@ -249,7 +271,7 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { u32 tval = (old_val & ~(0xff << (i * 8))) | (((u8)interesting_8[j]) << (i * 8)); - if (new_val == tval) return 1; + if (new_val == tval) { return 1; } } @@ -258,7 +280,7 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { /* Bail out unless we're also asked to examine two-byte LE insertions as a preparation for BE attempts. */ - if (blen == 2 && !check_le) return 0; + if (blen == 2 && !check_le) { return 0; } /* See if two-byte insertions over old_val could give us new_val. */ @@ -269,7 +291,7 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { u32 tval = (old_val & ~(0xffff << (i * 8))) | (((u16)interesting_16[j]) << (i * 8)); - if (new_val == tval) return 1; + if (new_val == tval) { return 1; } /* Continue here only if blen > 2. */ @@ -278,7 +300,7 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { tval = (old_val & ~(0xffff << (i * 8))) | (SWAP16(interesting_16[j]) << (i * 8)); - if (new_val == tval) return 1; + if (new_val == tval) { return 1; } } @@ -291,8 +313,11 @@ static u8 could_be_interest(u32 old_val, u32 new_val, u8 blen, u8 check_le) { /* See if four-byte insertions could produce the same result (LE only). */ - for (j = 0; j < sizeof(interesting_32) / 4; ++j) - if (new_val == (u32)interesting_32[j]) return 1; + for (j = 0; j < sizeof(interesting_32) / 4; ++j) { + + if (new_val == (u32)interesting_32[j]) { return 1; } + + } } @@ -315,7 +340,7 @@ static void locate_diffs(u8 *ptr1, u8 *ptr2, u32 len, s32 *first, s32 *last) { if (*(ptr1++) != *(ptr2++)) { - if (f_loc == -1) f_loc = pos; + if (f_loc == -1) { f_loc = pos; } l_loc = pos; } @@ -364,9 +389,12 @@ u8 fuzz_one_original(afl_state_t *afl) { /* The custom mutator will decide to skip this test case or not. */ if (!afl->mutator->afl_custom_queue_get(afl->mutator->data, - afl->queue_cur->fname)) + afl->queue_cur->fname)) { + return 1; + } + } if (likely(afl->pending_favored)) { @@ -377,9 +405,12 @@ u8 fuzz_one_original(afl_state_t *afl) { if (((afl->queue_cur->was_fuzzed > 0 || afl->queue_cur->fuzz_level > 0) || !afl->queue_cur->favored) && - rand_below(afl, 100) < SKIP_TO_NEW_PROB) + rand_below(afl, 100) < SKIP_TO_NEW_PROB) { + return 1; + } + } else if (!afl->dumb_mode && !afl->queue_cur->favored && afl->queued_paths > 10) { @@ -391,11 +422,11 @@ u8 fuzz_one_original(afl_state_t *afl) { if (afl->queue_cycle > 1 && (afl->queue_cur->fuzz_level == 0 || afl->queue_cur->was_fuzzed)) { - if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) return 1; + if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) { return 1; } } else { - if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) return 1; + if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) { return 1; } } @@ -415,15 +446,22 @@ u8 fuzz_one_original(afl_state_t *afl) { fd = open(afl->queue_cur->fname, O_RDONLY); - if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", afl->queue_cur->fname); + if (unlikely(fd < 0)) { + + PFATAL("Unable to open '%s'", afl->queue_cur->fname); + + } len = afl->queue_cur->len; orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (unlikely(orig_in == MAP_FAILED)) + if (unlikely(orig_in == MAP_FAILED)) { + PFATAL("Unable to mmap '%s' with len %d", afl->queue_cur->fname, len); + } + close(fd); /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every @@ -449,9 +487,12 @@ u8 fuzz_one_original(afl_state_t *afl) { res = calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0); - if (unlikely(res == FSRV_RUN_ERROR)) + if (unlikely(res == FSRV_RUN_ERROR)) { + FATAL("Unable to execute target application"); + } + } if (unlikely(afl->stop_soon) || res != afl->crash_mode) { @@ -471,9 +512,12 @@ u8 fuzz_one_original(afl_state_t *afl) { u8 res = trim_case(afl, afl->queue_cur, in_buf); - if (unlikely(res == FSRV_RUN_ERROR)) + if (unlikely(res == FSRV_RUN_ERROR)) { + FATAL("Unable to execute target application"); + } + if (unlikely(afl->stop_soon)) { ++afl->cur_skipped_paths; @@ -497,16 +541,19 @@ u8 fuzz_one_original(afl_state_t *afl) { orig_perf = perf_score = calculate_score(afl, afl->queue_cur); - if (unlikely(perf_score == 0)) goto abandon_entry; + if (unlikely(perf_score == 0)) { goto abandon_entry; } - if (unlikely(afl->use_radamsa > 1)) goto radamsa_stage; + if (unlikely(afl->use_radamsa > 1)) { goto radamsa_stage; } if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) { if (input_to_state_stage(afl, in_buf, out_buf, len, - afl->queue_cur->exec_cksum)) + afl->queue_cur->exec_cksum)) { + goto abandon_entry; + } + } /* Skip right away if -d is given, if it has not been chosen sufficiently @@ -568,7 +615,7 @@ u8 fuzz_one_original(afl_state_t *afl) { FLIP_BIT(out_buf, afl->stage_cur); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } FLIP_BIT(out_buf, afl->stage_cur); @@ -608,21 +655,31 @@ u8 fuzz_one_original(afl_state_t *afl) { /* If at end of file and we are still collecting a string, grab the final character and force output. */ - if (a_len < MAX_AUTO_EXTRA) + if (a_len < MAX_AUTO_EXTRA) { + a_collect[a_len] = out_buf[afl->stage_cur >> 3]; + + } + ++a_len; - if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) + if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { + maybe_add_auto((u8 *)afl, a_collect, a_len); + } + } else if (cksum != prev_cksum) { /* Otherwise, if the checksum has changed, see if we have something worthwhile queued up, and collect that if the answer is yes. */ - if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) + if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { + maybe_add_auto((u8 *)afl, a_collect, a_len); + } + a_len = 0; prev_cksum = cksum; @@ -633,8 +690,12 @@ u8 fuzz_one_original(afl_state_t *afl) { if (cksum != afl->queue_cur->exec_cksum) { - if (a_len < MAX_AUTO_EXTRA) + if (a_len < MAX_AUTO_EXTRA) { + a_collect[a_len] = out_buf[afl->stage_cur >> 3]; + + } + ++a_len; } @@ -663,7 +724,7 @@ u8 fuzz_one_original(afl_state_t *afl) { FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -692,7 +753,7 @@ u8 fuzz_one_original(afl_state_t *afl) { FLIP_BIT(out_buf, afl->stage_cur + 2); FLIP_BIT(out_buf, afl->stage_cur + 3); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -746,7 +807,7 @@ u8 fuzz_one_original(afl_state_t *afl) { out_buf[afl->stage_cur] ^= 0xFF; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } /* We also use this stage to pull off a simple trick: we identify bytes that seem to have no effect on the current execution path @@ -760,11 +821,16 @@ u8 fuzz_one_original(afl_state_t *afl) { /* If in dumb mode or if the file is very short, just flag everything without wasting time on checksums. */ - if (!afl->dumb_mode && len >= EFF_MIN_LEN) + if (!afl->dumb_mode && len >= EFF_MIN_LEN) { + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - else + + } else { + cksum = ~afl->queue_cur->exec_cksum; + } + if (cksum != afl->queue_cur->exec_cksum) { eff_map[EFF_APOS(afl->stage_cur)] = 1; @@ -804,7 +870,7 @@ u8 fuzz_one_original(afl_state_t *afl) { /* Two walking bytes. */ - if (len < 2) goto skip_bitflip; + if (len < 2) { goto skip_bitflip; } afl->stage_name = "bitflip 16/8"; afl->stage_short = "flip16"; @@ -828,7 +894,7 @@ u8 fuzz_one_original(afl_state_t *afl) { *(u16 *)(out_buf + i) ^= 0xFFFF; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; *(u16 *)(out_buf + i) ^= 0xFFFF; @@ -840,7 +906,7 @@ u8 fuzz_one_original(afl_state_t *afl) { afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP16] += afl->stage_max; - if (len < 4) goto skip_bitflip; + if (len < 4) { goto skip_bitflip; } /* Four walking bytes. */ @@ -866,7 +932,7 @@ u8 fuzz_one_original(afl_state_t *afl) { *(u32 *)(out_buf + i) ^= 0xFFFFFFFF; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; *(u32 *)(out_buf + i) ^= 0xFFFFFFFF; @@ -880,7 +946,7 @@ u8 fuzz_one_original(afl_state_t *afl) { skip_bitflip: - if (afl->no_arith) goto skip_arith; + if (afl->no_arith) { goto skip_arith; } /********************** * ARITHMETIC INC/DEC * @@ -924,13 +990,15 @@ skip_bitflip: afl->stage_cur_val = j; out_buf[i] = orig + j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + r = orig ^ (orig - j); if (!could_be_bitflip(r)) { @@ -938,13 +1006,15 @@ skip_bitflip: afl->stage_cur_val = -j; out_buf[i] = orig - j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + out_buf[i] = orig; } @@ -958,7 +1028,7 @@ skip_bitflip: /* 16-bit arithmetics, both endians. */ - if (len < 2) goto skip_arith; + if (len < 2) { goto skip_arith; } afl->stage_name = "arith 16/8"; afl->stage_short = "arith16"; @@ -1000,25 +1070,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u16 *)(out_buf + i) = orig + j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((orig & 0xff) < j && !could_be_bitflip(r2)) { afl->stage_cur_val = -j; *(u16 *)(out_buf + i) = orig - j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + /* Big endian comes next. Same deal. */ afl->stage_val_type = STAGE_VAL_BE; @@ -1028,25 +1102,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) + j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((orig >> 8) < j && !could_be_bitflip(r4)) { afl->stage_cur_val = -j; *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) - j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + *(u16 *)(out_buf + i) = orig; } @@ -1060,7 +1138,7 @@ skip_bitflip: /* 32-bit arithmetics, both endians. */ - if (len < 4) goto skip_arith; + if (len < 4) { goto skip_arith; } afl->stage_name = "arith 32/8"; afl->stage_short = "arith32"; @@ -1101,25 +1179,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u32 *)(out_buf + i) = orig + j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((orig & 0xffff) < j && !could_be_bitflip(r2)) { afl->stage_cur_val = -j; *(u32 *)(out_buf + i) = orig - j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + /* Big endian next. */ afl->stage_val_type = STAGE_VAL_BE; @@ -1129,25 +1211,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) + j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((SWAP32(orig) & 0xffff) < j && !could_be_bitflip(r4)) { afl->stage_cur_val = -j; *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) - j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + *(u32 *)(out_buf + i) = orig; } @@ -1206,7 +1292,7 @@ skip_arith: afl->stage_cur_val = interesting_8[j]; out_buf[i] = interesting_8[j]; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } out_buf[i] = orig; ++afl->stage_cur; @@ -1222,7 +1308,7 @@ skip_arith: /* Setting 16-bit integers, both endians. */ - if (afl->no_arith || len < 2) goto skip_interest; + if (afl->no_arith || len < 2) { goto skip_interest; } afl->stage_name = "interest 16/8"; afl->stage_short = "int16"; @@ -1261,13 +1347,15 @@ skip_arith: *(u16 *)(out_buf + i) = interesting_16[j]; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) && !could_be_bitflip(orig ^ SWAP16(interesting_16[j])) && !could_be_arith(orig, SWAP16(interesting_16[j]), 2) && @@ -1276,13 +1364,15 @@ skip_arith: afl->stage_val_type = STAGE_VAL_BE; *(u16 *)(out_buf + i) = SWAP16(interesting_16[j]); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + } *(u16 *)(out_buf + i) = orig; @@ -1294,7 +1384,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max; - if (len < 4) goto skip_interest; + if (len < 4) { goto skip_interest; } /* Setting 32-bit integers, both endians. */ @@ -1336,13 +1426,15 @@ skip_arith: *(u32 *)(out_buf + i) = interesting_32[j]; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) && !could_be_bitflip(orig ^ SWAP32(interesting_32[j])) && !could_be_arith(orig, SWAP32(interesting_32[j]), 4) && @@ -1351,13 +1443,15 @@ skip_arith: afl->stage_val_type = STAGE_VAL_BE; *(u32 *)(out_buf + i) = SWAP32(interesting_32[j]); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + } *(u32 *)(out_buf + i) = orig; @@ -1375,7 +1469,7 @@ skip_interest: * DICTIONARY STUFF * ********************/ - if (!afl->extras_cnt) goto skip_user_extras; + if (!afl->extras_cnt) { goto skip_user_extras; } /* Overwrite with user-supplied extras. */ @@ -1421,7 +1515,7 @@ skip_interest: last_len = afl->extras[j].len; memcpy(out_buf + i, afl->extras[j].data, last_len); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; @@ -1489,7 +1583,7 @@ skip_interest: skip_user_extras: - if (!afl->a_extras_cnt) goto skip_extras; + if (!afl->a_extras_cnt) { goto skip_extras; } afl->stage_name = "auto extras (over)"; afl->stage_short = "ext_AO"; @@ -1523,7 +1617,7 @@ skip_user_extras: last_len = afl->a_extras[j].len; memcpy(out_buf + i, afl->a_extras[j].data, last_len); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; @@ -1545,22 +1639,22 @@ skip_extras: we're properly done with deterministic steps and can mark it as such in the .state/ directory. */ - if (!afl->queue_cur->passed_det) mark_as_det_done(afl, afl->queue_cur); + if (!afl->queue_cur->passed_det) { mark_as_det_done(afl, afl->queue_cur); } custom_mutator_stage: /******************* * CUSTOM MUTATORS * *******************/ - if (likely(!afl->mutator)) goto havoc_stage; - if (likely(!afl->mutator->afl_custom_fuzz)) goto havoc_stage; + if (likely(!afl->mutator)) { goto havoc_stage; } + if (likely(!afl->mutator->afl_custom_fuzz)) { goto havoc_stage; } afl->stage_name = "custom mutator"; afl->stage_short = "custom"; afl->stage_max = HAVOC_CYCLES * perf_score / afl->havoc_div / 100; afl->stage_val_type = STAGE_VAL_NONE; - if (afl->stage_max < HAVOC_MIN) afl->stage_max = HAVOC_MIN; + if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; } const u32 max_seed_size = MAX_FILE; @@ -1589,9 +1683,12 @@ custom_mutator_stage: } - while (tid--) + while (tid--) { + target = target->next; + } + /* Make sure that the target has a reasonable length. */ while (target && (target->len < 2 || target == afl->queue_cur) && @@ -1602,11 +1699,11 @@ custom_mutator_stage: } - if (!target) goto retry_external_pick; + if (!target) { goto retry_external_pick; } /* Read the additional testcase into a new buffer. */ fd = open(target->fname, O_RDONLY); - if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname); + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); } new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len); ck_read(fd, new_buf, target->len, target->fname); @@ -1618,9 +1715,12 @@ custom_mutator_stage: afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len, max_seed_size); - if (unlikely(!mutated_buf)) + if (unlikely(!mutated_buf)) { + FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size); + } + if (mutated_size > 0) { if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) { @@ -1695,7 +1795,7 @@ havoc_stage: } - if (afl->stage_max < HAVOC_MIN) afl->stage_max = HAVOC_MIN; + if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; } temp_len = len; @@ -1710,11 +1810,14 @@ havoc_stage: stacked_custom_prob = afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data); - if (stacked_custom_prob > 100) + if (stacked_custom_prob > 100) { + FATAL( "The probability returned by afl_custom_havoc_mutation_propability " "has to be in the range 0-100."); + } + } /* We essentially just do several thousand runs (depending on perf_score) @@ -1733,8 +1836,12 @@ havoc_stage: u8 * custom_havoc_buf = NULL; size_t new_len = afl->mutator->afl_custom_havoc_mutation( afl->mutator->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE); - if (unlikely(!custom_havoc_buf)) + if (unlikely(!custom_havoc_buf)) { + FATAL("Error in custom_havoc (return %zd)", new_len); + + } + if (likely(new_len > 0 && custom_havoc_buf)) { temp_len = new_len; @@ -1771,7 +1878,7 @@ havoc_stage: /* Set word to interesting value, randomly choosing endian. */ - if (temp_len < 2) break; + if (temp_len < 2) { break; } if (rand_below(afl, 2)) { @@ -1791,7 +1898,7 @@ havoc_stage: /* Set dword to interesting value, randomly choosing endian. */ - if (temp_len < 4) break; + if (temp_len < 4) { break; } if (rand_below(afl, 2)) { @@ -1825,7 +1932,7 @@ havoc_stage: /* Randomly subtract from word, random endian. */ - if (temp_len < 2) break; + if (temp_len < 2) { break; } if (rand_below(afl, 2)) { @@ -1849,7 +1956,7 @@ havoc_stage: /* Randomly add to word, random endian. */ - if (temp_len < 2) break; + if (temp_len < 2) { break; } if (rand_below(afl, 2)) { @@ -1873,7 +1980,7 @@ havoc_stage: /* Randomly subtract from dword, random endian. */ - if (temp_len < 4) break; + if (temp_len < 4) { break; } if (rand_below(afl, 2)) { @@ -1897,7 +2004,7 @@ havoc_stage: /* Randomly add to dword, random endian. */ - if (temp_len < 4) break; + if (temp_len < 4) { break; } if (rand_below(afl, 2)) { @@ -1934,7 +2041,7 @@ havoc_stage: u32 del_from, del_len; - if (temp_len < 2) break; + if (temp_len < 2) { break; } /* Don't delete too much. */ @@ -1984,14 +2091,19 @@ havoc_stage: /* Inserted part */ - if (actually_clone) + if (actually_clone) { + memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); - else + + } else { + memset(new_buf + clone_to, rand_below(afl, 2) ? rand_below(afl, 256) : out_buf[rand_below(afl, temp_len)], clone_len); + } + /* Tail */ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); @@ -2012,7 +2124,7 @@ havoc_stage: u32 copy_from, copy_to, copy_len; - if (temp_len < 2) break; + if (temp_len < 2) { break; } copy_len = choose_block_len(afl, temp_len - 1); @@ -2021,16 +2133,21 @@ havoc_stage: if (rand_below(afl, 4)) { - if (copy_from != copy_to) + if (copy_from != copy_to) { + memmove(out_buf + copy_to, out_buf + copy_from, copy_len); - } else + } + + } else { memset(out_buf + copy_to, rand_below(afl, 2) ? rand_below(afl, 256) : out_buf[rand_below(afl, temp_len)], copy_len); + } + break; } @@ -2051,7 +2168,7 @@ havoc_stage: u32 extra_len = afl->a_extras[use_extra].len; u32 insert_at; - if (extra_len > temp_len) break; + if (extra_len > temp_len) { break; } insert_at = rand_below(afl, temp_len - extra_len + 1); memcpy(out_buf + insert_at, afl->a_extras[use_extra].data, @@ -2065,7 +2182,7 @@ havoc_stage: u32 extra_len = afl->extras[use_extra].len; u32 insert_at; - if (extra_len > temp_len) break; + if (extra_len > temp_len) { break; } insert_at = rand_below(afl, temp_len - extra_len + 1); memcpy(out_buf + insert_at, afl->extras[use_extra].data, extra_len); @@ -2089,7 +2206,7 @@ havoc_stage: use_extra = rand_below(afl, afl->a_extras_cnt); extra_len = afl->a_extras[use_extra].len; - if (temp_len + extra_len >= MAX_FILE) break; + if (temp_len + extra_len >= MAX_FILE) { break; } new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); @@ -2106,7 +2223,7 @@ havoc_stage: use_extra = rand_below(afl, afl->extras_cnt); extra_len = afl->extras[use_extra].len; - if (temp_len + extra_len >= MAX_FILE) break; + if (temp_len + extra_len >= MAX_FILE) { break; } new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len); @@ -2136,7 +2253,7 @@ havoc_stage: } - if (common_fuzz_stuff(afl, out_buf, temp_len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, temp_len)) { goto abandon_entry; } /* out_buf might have been mangled a bit, so let's restore it to its original size and shape. */ @@ -2226,9 +2343,12 @@ retry_splicing: } - while (tid--) + while (tid--) { + target = target->next; + } + /* Make sure that the target has a reasonable length. */ while (target && (target->len < 2 || target == afl->queue_cur)) { @@ -2238,13 +2358,13 @@ retry_splicing: } - if (!target) goto retry_splicing; + if (!target) { goto retry_splicing; } /* Read the testcase into a new buffer. */ fd = open(target->fname, O_RDONLY); - if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname); + if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); } new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len); @@ -2288,14 +2408,18 @@ retry_splicing: radamsa_stage: - if (likely(!afl->use_radamsa || !afl->radamsa_mutate_ptr)) goto abandon_entry; + if (likely(!afl->use_radamsa || !afl->radamsa_mutate_ptr)) { + + goto abandon_entry; + + } afl->stage_name = "radamsa"; afl->stage_short = "radamsa"; afl->stage_max = (HAVOC_CYCLES * perf_score / afl->havoc_div / 100) << afl->use_radamsa; - if (afl->stage_max < HAVOC_MIN) afl->stage_max = HAVOC_MIN; + if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; } orig_hit_cnt = afl->queued_paths + afl->unique_crashes; @@ -2351,7 +2475,7 @@ abandon_entry: --afl->pending_not_fuzzed; afl->queue_cur->was_fuzzed = 1; - if (afl->queue_cur->favored) --afl->pending_favored; + if (afl->queue_cur->favored) { --afl->pending_favored; } } @@ -2405,9 +2529,12 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { cases. */ if ((afl->queue_cur->was_fuzzed || !afl->queue_cur->favored) && - rand_below(afl, 100) < SKIP_TO_NEW_PROB) + rand_below(afl, 100) < SKIP_TO_NEW_PROB) { + return 1; + } + } else if (!afl->dumb_mode && !afl->queue_cur->favored && afl->queued_paths > 10) { @@ -2418,11 +2545,11 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (afl->queue_cycle > 1 && !afl->queue_cur->was_fuzzed) { - if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) return 1; + if (rand_below(afl, 100) < SKIP_NFAV_NEW_PROB) { return 1; } } else { - if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) return 1; + if (rand_below(afl, 100) < SKIP_NFAV_OLD_PROB) { return 1; } } @@ -2442,15 +2569,18 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { fd = open(afl->queue_cur->fname, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", afl->queue_cur->fname); + if (fd < 0) { PFATAL("Unable to open '%s'", afl->queue_cur->fname); } len = afl->queue_cur->len; orig_in = in_buf = mmap(0, len, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (orig_in == MAP_FAILED) + if (orig_in == MAP_FAILED) { + PFATAL("Unable to mmap '%s'", afl->queue_cur->fname); + } + close(fd); /* We could mmap() out_buf as MAP_PRIVATE, but we end up clobbering every @@ -2476,7 +2606,11 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { res = calibrate_case(afl, afl->queue_cur, in_buf, afl->queue_cycle - 1, 0); - if (res == FSRV_RUN_ERROR) FATAL("Unable to execute target application"); + if (res == FSRV_RUN_ERROR) { + + FATAL("Unable to execute target application"); + + } } @@ -2497,7 +2631,11 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { u8 res = trim_case(afl, afl->queue_cur, in_buf); - if (res == FSRV_RUN_ERROR) FATAL("Unable to execute target application"); + if (res == FSRV_RUN_ERROR) { + + FATAL("Unable to execute target application"); + + } if (afl->stop_soon) { @@ -2525,9 +2663,12 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (afl->shm.cmplog_mode && !afl->queue_cur->fully_colorized) { if (input_to_state_stage(afl, in_buf, out_buf, len, - afl->queue_cur->exec_cksum)) + afl->queue_cur->exec_cksum)) { + goto abandon_entry; + } + } /* Go to pacemker fuzzing if MOpt is doing well */ @@ -2549,16 +2690,22 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { testing in earlier, resumed runs (passed_det). */ if (afl->skip_deterministic || afl->queue_cur->was_fuzzed || - afl->queue_cur->passed_det) + afl->queue_cur->passed_det) { + goto havoc_stage; + } + /* Skip deterministic fuzzing if exec path checksum puts this out of scope for this master instance. */ if (afl->master_max && - (afl->queue_cur->exec_cksum % afl->master_max) != afl->master_id - 1) + (afl->queue_cur->exec_cksum % afl->master_max) != afl->master_id - 1) { + goto havoc_stage; + } + doing_det = 1; /********************************************* @@ -2592,7 +2739,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { FLIP_BIT(out_buf, afl->stage_cur); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } FLIP_BIT(out_buf, afl->stage_cur); @@ -2632,21 +2779,31 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { /* If at end of file and we are still collecting a string, grab the final character and force output. */ - if (a_len < MAX_AUTO_EXTRA) + if (a_len < MAX_AUTO_EXTRA) { + a_collect[a_len] = out_buf[afl->stage_cur >> 3]; + + } + ++a_len; - if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) + if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { + maybe_add_auto((u8 *)afl, a_collect, a_len); + } + } else if (cksum != prev_cksum) { /* Otherwise, if the checksum has changed, see if we have something worthwhile queued up, and collect that if the answer is yes. */ - if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) + if (a_len >= MIN_AUTO_EXTRA && a_len <= MAX_AUTO_EXTRA) { + maybe_add_auto((u8 *)afl, a_collect, a_len); + } + a_len = 0; prev_cksum = cksum; @@ -2657,8 +2814,12 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { if (cksum != afl->queue_cur->exec_cksum) { - if (a_len < MAX_AUTO_EXTRA) + if (a_len < MAX_AUTO_EXTRA) { + a_collect[a_len] = out_buf[afl->stage_cur >> 3]; + + } + ++a_len; } @@ -2687,7 +2848,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -2716,7 +2877,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { FLIP_BIT(out_buf, afl->stage_cur + 2); FLIP_BIT(out_buf, afl->stage_cur + 3); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } FLIP_BIT(out_buf, afl->stage_cur); FLIP_BIT(out_buf, afl->stage_cur + 1); @@ -2770,7 +2931,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { out_buf[afl->stage_cur] ^= 0xFF; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } /* We also use this stage to pull off a simple trick: we identify bytes that seem to have no effect on the current execution path @@ -2784,11 +2945,16 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { /* If in dumb mode or if the file is very short, just flag everything without wasting time on checksums. */ - if (!afl->dumb_mode && len >= EFF_MIN_LEN) + if (!afl->dumb_mode && len >= EFF_MIN_LEN) { + cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); - else + + } else { + cksum = ~afl->queue_cur->exec_cksum; + } + if (cksum != afl->queue_cur->exec_cksum) { eff_map[EFF_APOS(afl->stage_cur)] = 1; @@ -2828,7 +2994,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { /* Two walking bytes. */ - if (len < 2) goto skip_bitflip; + if (len < 2) { goto skip_bitflip; } afl->stage_name = "bitflip 16/8"; afl->stage_short = "flip16"; @@ -2852,7 +3018,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { *(u16 *)(out_buf + i) ^= 0xFFFF; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; *(u16 *)(out_buf + i) ^= 0xFFFF; @@ -2864,7 +3030,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_FLIP16] += afl->stage_max; - if (len < 4) goto skip_bitflip; + if (len < 4) { goto skip_bitflip; } /* Four walking bytes. */ @@ -2890,7 +3056,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { *(u32 *)(out_buf + i) ^= 0xFFFFFFFF; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; *(u32 *)(out_buf + i) ^= 0xFFFFFFFF; @@ -2904,7 +3070,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) { skip_bitflip: - if (afl->no_arith) goto skip_arith; + if (afl->no_arith) { goto skip_arith; } /********************** * ARITHMETIC INC/DEC * @@ -2948,13 +3114,15 @@ skip_bitflip: afl->stage_cur_val = j; out_buf[i] = orig + j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + r = orig ^ (orig - j); if (!could_be_bitflip(r)) { @@ -2962,13 +3130,15 @@ skip_bitflip: afl->stage_cur_val = -j; out_buf[i] = orig - j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + out_buf[i] = orig; } @@ -2982,7 +3152,7 @@ skip_bitflip: /* 16-bit arithmetics, both endians. */ - if (len < 2) goto skip_arith; + if (len < 2) { goto skip_arith; } afl->stage_name = "arith 16/8"; afl->stage_short = "arith16"; @@ -3024,25 +3194,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u16 *)(out_buf + i) = orig + j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((orig & 0xff) < j && !could_be_bitflip(r2)) { afl->stage_cur_val = -j; *(u16 *)(out_buf + i) = orig - j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + /* Big endian comes next. Same deal. */ afl->stage_val_type = STAGE_VAL_BE; @@ -3052,25 +3226,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) + j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((orig >> 8) < j && !could_be_bitflip(r4)) { afl->stage_cur_val = -j; *(u16 *)(out_buf + i) = SWAP16(SWAP16(orig) - j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + *(u16 *)(out_buf + i) = orig; } @@ -3084,7 +3262,7 @@ skip_bitflip: /* 32-bit arithmetics, both endians. */ - if (len < 4) goto skip_arith; + if (len < 4) { goto skip_arith; } afl->stage_name = "arith 32/8"; afl->stage_short = "arith32"; @@ -3125,25 +3303,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u32 *)(out_buf + i) = orig + j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((orig & 0xffff) < j && !could_be_bitflip(r2)) { afl->stage_cur_val = -j; *(u32 *)(out_buf + i) = orig - j; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + /* Big endian next. */ afl->stage_val_type = STAGE_VAL_BE; @@ -3153,25 +3335,29 @@ skip_bitflip: afl->stage_cur_val = j; *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) + j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((SWAP32(orig) & 0xffff) < j && !could_be_bitflip(r4)) { afl->stage_cur_val = -j; *(u32 *)(out_buf + i) = SWAP32(SWAP32(orig) - j); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + *(u32 *)(out_buf + i) = orig; } @@ -3230,7 +3416,7 @@ skip_arith: afl->stage_cur_val = interesting_8[j]; out_buf[i] = interesting_8[j]; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } out_buf[i] = orig; ++afl->stage_cur; @@ -3246,7 +3432,7 @@ skip_arith: /* Setting 16-bit integers, both endians. */ - if (afl->no_arith || len < 2) goto skip_interest; + if (afl->no_arith || len < 2) { goto skip_interest; } afl->stage_name = "interest 16/8"; afl->stage_short = "int16"; @@ -3285,13 +3471,15 @@ skip_arith: *(u16 *)(out_buf + i) = interesting_16[j]; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((u16)interesting_16[j] != SWAP16(interesting_16[j]) && !could_be_bitflip(orig ^ SWAP16(interesting_16[j])) && !could_be_arith(orig, SWAP16(interesting_16[j]), 2) && @@ -3300,13 +3488,15 @@ skip_arith: afl->stage_val_type = STAGE_VAL_BE; *(u16 *)(out_buf + i) = SWAP16(interesting_16[j]); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + } *(u16 *)(out_buf + i) = orig; @@ -3318,7 +3508,7 @@ skip_arith: afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt; afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max; - if (len < 4) goto skip_interest; + if (len < 4) { goto skip_interest; } /* Setting 32-bit integers, both endians. */ @@ -3360,13 +3550,15 @@ skip_arith: *(u32 *)(out_buf + i) = interesting_32[j]; - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + if ((u32)interesting_32[j] != SWAP32(interesting_32[j]) && !could_be_bitflip(orig ^ SWAP32(interesting_32[j])) && !could_be_arith(orig, SWAP32(interesting_32[j]), 4) && @@ -3375,13 +3567,15 @@ skip_arith: afl->stage_val_type = STAGE_VAL_BE; *(u32 *)(out_buf + i) = SWAP32(interesting_32[j]); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; - } else + } else { --afl->stage_max; + } + } *(u32 *)(out_buf + i) = orig; @@ -3399,7 +3593,7 @@ skip_interest: * DICTIONARY STUFF * ********************/ - if (!afl->extras_cnt) goto skip_user_extras; + if (!afl->extras_cnt) { goto skip_user_extras; } /* Overwrite with user-supplied extras. */ @@ -3445,7 +3639,7 @@ skip_interest: last_len = afl->extras[j].len; memcpy(out_buf + i, afl->extras[j].data, last_len); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; @@ -3513,7 +3707,7 @@ skip_interest: skip_user_extras: - if (!afl->a_extras_cnt) goto skip_extras; + if (!afl->a_extras_cnt) { goto skip_extras; } afl->stage_name = "auto extras (over)"; afl->stage_short = "ext_AO"; @@ -3547,7 +3741,7 @@ skip_user_extras: last_len = afl->a_extras[j].len; memcpy(out_buf + i, afl->a_extras[j].data, last_len); - if (common_fuzz_stuff(afl, out_buf, len)) goto abandon_entry; + if (common_fuzz_stuff(afl, out_buf, len)) { goto abandon_entry; } ++afl->stage_cur; @@ -3569,7 +3763,7 @@ skip_extras: we're properly done with deterministic steps and can mark it as such in the .state/ directory. */ - if (!afl->queue_cur->passed_det) mark_as_det_done(afl, afl->queue_cur); + if (!afl->queue_cur->passed_det) { mark_as_det_done(afl, afl->queue_cur); } /**************** * RANDOM HAVOC * @@ -3652,7 +3846,7 @@ pacemaker_fuzzing: } - if (afl->stage_max < HAVOC_MIN) afl->stage_max = HAVOC_MIN; + if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; } temp_len = len; @@ -3684,7 +3878,7 @@ pacemaker_fuzzing: break; case 1: - if (temp_len < 2) break; + if (temp_len < 2) { break; } temp_len_puppet = rand_below(afl, (temp_len << 3) - 1); FLIP_BIT(out_buf, temp_len_puppet); FLIP_BIT(out_buf, temp_len_puppet + 1); @@ -3692,7 +3886,7 @@ pacemaker_fuzzing: break; case 2: - if (temp_len < 2) break; + if (temp_len < 2) { break; } temp_len_puppet = rand_below(afl, (temp_len << 3) - 3); FLIP_BIT(out_buf, temp_len_puppet); FLIP_BIT(out_buf, temp_len_puppet + 1); @@ -3702,19 +3896,19 @@ pacemaker_fuzzing: break; case 3: - if (temp_len < 4) break; + if (temp_len < 4) { break; } out_buf[rand_below(afl, temp_len)] ^= 0xFF; MOpt_globals.cycles_v2[STAGE_FLIP8] += 1; break; case 4: - if (temp_len < 8) break; + if (temp_len < 8) { break; } *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) ^= 0xFFFF; MOpt_globals.cycles_v2[STAGE_FLIP16] += 1; break; case 5: - if (temp_len < 8) break; + if (temp_len < 8) { break; } *(u32 *)(out_buf + rand_below(afl, temp_len - 3)) ^= 0xFFFFFFFF; MOpt_globals.cycles_v2[STAGE_FLIP32] += 1; break; @@ -3729,7 +3923,7 @@ pacemaker_fuzzing: case 7: /* Randomly subtract from word, random endian. */ - if (temp_len < 8) break; + if (temp_len < 8) { break; } if (rand_below(afl, 2)) { u32 pos = rand_below(afl, temp_len - 1); @@ -3764,7 +3958,7 @@ pacemaker_fuzzing: case 8: /* Randomly subtract from dword, random endian. */ - if (temp_len < 8) break; + if (temp_len < 8) { break; } if (rand_below(afl, 2)) { u32 pos = rand_below(afl, temp_len - 3); @@ -3800,7 +3994,7 @@ pacemaker_fuzzing: case 9: /* Set byte to interesting value. */ - if (temp_len < 4) break; + if (temp_len < 4) { break; } out_buf[rand_below(afl, temp_len)] = interesting_8[rand_below(afl, sizeof(interesting_8))]; MOpt_globals.cycles_v2[STAGE_INTEREST8] += 1; @@ -3808,7 +4002,7 @@ pacemaker_fuzzing: case 10: /* Set word to interesting value, randomly choosing endian. */ - if (temp_len < 8) break; + if (temp_len < 8) { break; } if (rand_below(afl, 2)) { *(u16 *)(out_buf + rand_below(afl, temp_len - 1)) = @@ -3829,7 +4023,7 @@ pacemaker_fuzzing: case 11: /* Set dword to interesting value, randomly choosing endian. */ - if (temp_len < 8) break; + if (temp_len < 8) { break; } if (rand_below(afl, 2)) { @@ -3866,7 +4060,7 @@ pacemaker_fuzzing: u32 del_from, del_len; - if (temp_len < 2) break; + if (temp_len < 2) { break; } /* Don't delete too much. */ @@ -3917,15 +4111,20 @@ pacemaker_fuzzing: /* Inserted part */ - if (actually_clone) + if (actually_clone) { + memcpy(new_buf + clone_to, out_buf + clone_from, clone_len); - else + + } else { + memset(new_buf + clone_to, rand_below(afl, 2) ? rand_below(afl, 256) : out_buf[rand_below(afl, temp_len)], clone_len); + } + /* Tail */ memcpy(new_buf + clone_to + clone_len, out_buf + clone_to, temp_len - clone_to); @@ -3946,7 +4145,7 @@ pacemaker_fuzzing: u32 copy_from, copy_to, copy_len; - if (temp_len < 2) break; + if (temp_len < 2) { break; } copy_len = choose_block_len(afl, temp_len - 1); @@ -3955,15 +4154,21 @@ pacemaker_fuzzing: if (rand_below(afl, 4)) { - if (copy_from != copy_to) + if (copy_from != copy_to) { + memmove(out_buf + copy_to, out_buf + copy_from, copy_len); - } else + } + + } else { memset(out_buf + copy_to, rand_below(afl, 2) ? rand_below(afl, 256) : out_buf[rand_below(afl, temp_len)], copy_len); + + } + MOpt_globals.cycles_v2[STAGE_OverWrite75] += 1; break; @@ -3977,9 +4182,12 @@ pacemaker_fuzzing: u64 temp_total_found = afl->queued_paths + afl->unique_crashes; - if (common_fuzz_stuff(afl, out_buf, temp_len)) + if (common_fuzz_stuff(afl, out_buf, temp_len)) { + goto abandon_entry_puppet; + } + /* out_buf might have been mangled a bit, so let's restore it to its original size and shape. */ @@ -4011,9 +4219,12 @@ pacemaker_fuzzing: afl->total_puppet_find = afl->total_puppet_find + temp_temp_puppet; for (i = 0; i < operator_num; ++i) { - if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) + if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles_v3[i]) { + MOpt_globals.finds_v2[i] += temp_temp_puppet; + } + } } /* if */ @@ -4085,9 +4296,12 @@ pacemaker_fuzzing: } - while (tid--) + while (tid--) { + target = target->next; + } + /* Make sure that the target has a reasonable length. */ while (target && (target->len < 2 || target == afl->queue_cur)) { @@ -4097,13 +4311,13 @@ pacemaker_fuzzing: } - if (!target) goto retry_splicing_puppet; + if (!target) { goto retry_splicing_puppet; } /* Read the testcase into a new buffer. */ fd = open(target->fname, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", target->fname); + if (fd < 0) { PFATAL("Unable to open '%s'", target->fname); } new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len); @@ -4147,12 +4361,15 @@ pacemaker_fuzzing: abandon_entry: abandon_entry_puppet: - if (splice_cycle >= afl->SPLICE_CYCLES_puppet) + if (splice_cycle >= afl->SPLICE_CYCLES_puppet) { + afl->SPLICE_CYCLES_puppet = (rand_below( afl, SPLICE_CYCLES_puppet_up - SPLICE_CYCLES_puppet_low + 1) + SPLICE_CYCLES_puppet_low); + } + afl->splicing_with = -1; /* Update afl->pending_not_fuzzed count if we made it through the @@ -4205,11 +4422,14 @@ pacemaker_fuzzing: double temp_eff = 0.0; - if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles[i]) + if (MOpt_globals.cycles_v2[i] > MOpt_globals.cycles[i]) { + temp_eff = (double)(MOpt_globals.finds_v2[i] - MOpt_globals.finds[i]) / (double)(MOpt_globals.cycles_v2[i] - MOpt_globals.cycles[i]); + } + if (afl->eff_best[afl->swarm_now][i] < temp_eff) { afl->eff_best[afl->swarm_now][i] = temp_eff; @@ -4255,9 +4475,12 @@ pacemaker_fuzzing: } - if (afl->swarm_now < 0 || afl->swarm_now > swarm_num - 1) + if (afl->swarm_now < 0 || afl->swarm_now > swarm_num - 1) { + PFATAL("swarm_now error number %d", afl->swarm_now); + } + } /* if afl->swarm_now == swarm_num */ /* adjust pointers dependent on 'afl->swarm_now' */ @@ -4307,7 +4530,7 @@ u8 pilot_fuzzing(afl_state_t *afl) { void pso_updating(afl_state_t *afl) { afl->g_now += 1; - if (afl->g_now > afl->g_max) afl->g_now = 0; + if (afl->g_now > afl->g_max) { afl->g_now = 0; } afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) / (afl->g_max) + afl->w_end; @@ -4331,10 +4554,13 @@ void pso_updating(afl_state_t *afl) { for (i = 0; i < operator_num; ++i) { - if (afl->operator_finds_puppet[i]) + if (afl->operator_finds_puppet[i]) { + afl->G_best[i] = (double)((double)(afl->operator_finds_puppet[i]) / (double)(temp_operator_finds_puppet)); + } + } for (tmp_swarm = 0; tmp_swarm < swarm_num; ++tmp_swarm) { @@ -4348,10 +4574,16 @@ void pso_updating(afl_state_t *afl) { RAND_C * (afl->L_best[tmp_swarm][i] - afl->x_now[tmp_swarm][i]) + RAND_C * (afl->G_best[i] - afl->x_now[tmp_swarm][i]); afl->x_now[tmp_swarm][i] += afl->v_now[tmp_swarm][i]; - if (afl->x_now[tmp_swarm][i] > v_max) + if (afl->x_now[tmp_swarm][i] > v_max) { + afl->x_now[tmp_swarm][i] = v_max; - else if (afl->x_now[tmp_swarm][i] < v_min) + + } else if (afl->x_now[tmp_swarm][i] < v_min) { + afl->x_now[tmp_swarm][i] = v_min; + + } + x_temp += afl->x_now[tmp_swarm][i]; } @@ -4359,18 +4591,26 @@ void pso_updating(afl_state_t *afl) { for (i = 0; i < operator_num; ++i) { afl->x_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i] / x_temp; - if (likely(i != 0)) + if (likely(i != 0)) { + afl->probability_now[tmp_swarm][i] = afl->probability_now[tmp_swarm][i - 1] + afl->x_now[tmp_swarm][i]; - else + + } else { + afl->probability_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i]; + } + } if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 || - afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) + afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) { + FATAL("ERROR probability"); + } + } afl->swarm_now = 0; @@ -4410,13 +4650,20 @@ u8 fuzz_one(afl_state_t *afl) { if (afl->limit_time_sig != 0) { - if (afl->key_module == 0) + if (afl->key_module == 0) { + key_val_lv_2 = pilot_fuzzing(afl); - else if (afl->key_module == 1) + + } else if (afl->key_module == 1) { + key_val_lv_2 = core_fuzzing(afl); - else if (afl->key_module == 2) + + } else if (afl->key_module == 2) { + pso_updating(afl); + } + } return (key_val_lv_1 | key_val_lv_2); diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c index d4519c6d..64cabcad 100644 --- a/src/afl-fuzz-python.c +++ b/src/afl-fuzz-python.c @@ -111,10 +111,10 @@ static size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf, static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { - if (!module_name) return NULL; + if (!module_name) { return NULL; } py_mutator_t *py = calloc(1, sizeof(py_mutator_t)); - if (!py) PFATAL("Could not allocate memory for python mutator!"); + if (!py) { PFATAL("Could not allocate memory for python mutator!"); } Py_Initialize(); @@ -160,12 +160,12 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { if (py_idx == PY_FUNC_PRE_SAVE) { // Implenting the pre_save API is optional for now - if (PyErr_Occurred()) PyErr_Print(); + if (PyErr_Occurred()) { PyErr_Print(); } } else if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) { // Implementing the trim API is optional for now - if (PyErr_Occurred()) PyErr_Print(); + if (PyErr_Occurred()) { PyErr_Print(); } py_notrim = 1; } else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) && @@ -173,11 +173,11 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) { (py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) { // Implenting the havoc and queue API is optional for now - if (PyErr_Occurred()) PyErr_Print(); + if (PyErr_Occurred()) { PyErr_Print(); } } else { - if (PyErr_Occurred()) PyErr_Print(); + if (PyErr_Occurred()) { PyErr_Print(); } fprintf(stderr, "Cannot find/call function with index %d in external " "Python module.\n", @@ -222,9 +222,12 @@ void finalize_py_module(void *py_mutator) { deinit_py(py_mutator); u32 i; - for (i = 0; i < PY_FUNC_COUNT; ++i) + for (i = 0; i < PY_FUNC_COUNT; ++i) { + Py_XDECREF(py->py_functions[i]); + } + Py_DECREF(py->py_module); } @@ -308,38 +311,67 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) { PyObject **py_functions = py_mutator->py_functions; - if (py_functions[PY_FUNC_INIT]) afl->mutator->afl_custom_init = unsupported; + if (py_functions[PY_FUNC_INIT]) { + + afl->mutator->afl_custom_init = unsupported; - if (py_functions[PY_FUNC_DEINIT]) afl->mutator->afl_custom_deinit = deinit_py; + } + + if (py_functions[PY_FUNC_DEINIT]) { + + afl->mutator->afl_custom_deinit = deinit_py; + + } /* "afl_custom_fuzz" should not be NULL, but the interface of Python mutator is quite different from the custom mutator. */ afl->mutator->afl_custom_fuzz = fuzz_py; - if (py_functions[PY_FUNC_PRE_SAVE]) + if (py_functions[PY_FUNC_PRE_SAVE]) { + afl->mutator->afl_custom_pre_save = pre_save_py; - if (py_functions[PY_FUNC_INIT_TRIM]) + } + + if (py_functions[PY_FUNC_INIT_TRIM]) { + afl->mutator->afl_custom_init_trim = init_trim_py; - if (py_functions[PY_FUNC_POST_TRIM]) + } + + if (py_functions[PY_FUNC_POST_TRIM]) { + afl->mutator->afl_custom_post_trim = post_trim_py; - if (py_functions[PY_FUNC_TRIM]) afl->mutator->afl_custom_trim = trim_py; + } + + if (py_functions[PY_FUNC_TRIM]) { afl->mutator->afl_custom_trim = trim_py; } + + if (py_functions[PY_FUNC_HAVOC_MUTATION]) { - if (py_functions[PY_FUNC_HAVOC_MUTATION]) afl->mutator->afl_custom_havoc_mutation = havoc_mutation_py; - if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) + } + + if (py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY]) { + afl->mutator->afl_custom_havoc_mutation_probability = havoc_mutation_probability_py; - if (py_functions[PY_FUNC_QUEUE_GET]) + } + + if (py_functions[PY_FUNC_QUEUE_GET]) { + afl->mutator->afl_custom_queue_get = queue_get_py; - if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) + } + + if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) { + afl->mutator->afl_custom_queue_new_entry = queue_new_entry_py; + } + OKF("Python mutator '%s' installed successfully.", module_name); /* Initialize the custom mutator */ diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c index 121eb3f1..f998c06b 100644 --- a/src/afl-fuzz-queue.c +++ b/src/afl-fuzz-queue.c @@ -38,7 +38,7 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) { strrchr(q->fname, '/') + 1); fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); q->passed_det = 1; @@ -61,7 +61,7 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) { if (symlink(ldest, fn)) { s32 fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); } @@ -77,7 +77,7 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { u8 fn[PATH_MAX]; - if (state == q->fs_redundant) return; + if (state == q->fs_redundant) { return; } q->fs_redundant = state; @@ -89,12 +89,12 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) { s32 fd; fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } close(fd); } else { - if (unlink(fn)) PFATAL("Unable to remove '%s'", fn); + if (unlink(fn)) { PFATAL("Unable to remove '%s'", fn); } } @@ -113,17 +113,19 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { q->n_fuzz = 1; q->trace_mini = NULL; - if (q->depth > afl->max_depth) afl->max_depth = q->depth; + if (q->depth > afl->max_depth) { afl->max_depth = q->depth; } if (afl->queue_top) { afl->queue_top->next = q; afl->queue_top = q; - } else + } else { afl->q_prev100 = afl->queue = afl->queue_top = q; + } + ++afl->queued_paths; ++afl->pending_not_fuzzed; @@ -143,7 +145,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) { u8 *fname_orig = NULL; /* At the initialization stage, queue_cur is NULL */ - if (afl->queue_cur) fname_orig = afl->queue_cur->fname; + if (afl->queue_cur) { fname_orig = afl->queue_cur->fname; } afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname, fname_orig); @@ -188,14 +190,19 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 fuzz_p2 = next_pow2(q->n_fuzz); if (afl->schedule == MMOPT || afl->schedule == RARE || - unlikely(afl->fixed_seed)) + unlikely(afl->fixed_seed)) { + fav_factor = q->len << 2; - else + + } else { + fav_factor = q->exec_us * q->len; + } + /* For every byte set in afl->fsrv.trace_bits[], see if there is a previous winner, and how it compares to us. */ - for (i = 0; i < afl->fsrv.map_size; ++i) + for (i = 0; i < afl->fsrv.map_size; ++i) { if (afl->fsrv.trace_bits[i]) { @@ -206,27 +213,41 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz); if (afl->schedule == MMOPT || afl->schedule == RARE || - unlikely(afl->fixed_seed)) + unlikely(afl->fixed_seed)) { + top_rated_fav_factor = afl->top_rated[i]->len << 2; - else + + } else { + top_rated_fav_factor = afl->top_rated[i]->exec_us * afl->top_rated[i]->len; - if (fuzz_p2 > top_rated_fuzz_p2) + } + + if (fuzz_p2 > top_rated_fuzz_p2) { + continue; - else if (fuzz_p2 == top_rated_fuzz_p2) - if (fav_factor > top_rated_fav_factor) continue; + + } else if (fuzz_p2 == top_rated_fuzz_p2) { + + if (fav_factor > top_rated_fav_factor) { continue; } + + } if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed)) { - if (fav_factor > afl->top_rated[i]->len << 2) continue; + if (fav_factor > afl->top_rated[i]->len << 2) { continue; } } else { - if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len) + if (fav_factor > + afl->top_rated[i]->exec_us * afl->top_rated[i]->len) { + continue; + } + } /* Looks like we're going to win. Decrease ref count for the @@ -258,6 +279,8 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) { } + } + } /* The second part of the mechanism discussed above is a routine that @@ -273,7 +296,7 @@ void cull_queue(afl_state_t *afl) { u32 i; u8 * temp_v = afl->map_tmp_buf; - if (afl->dumb_mode || !afl->score_changed) return; + if (afl->dumb_mode || !afl->score_changed) { return; } afl->score_changed = 0; @@ -294,25 +317,38 @@ void cull_queue(afl_state_t *afl) { /* Let's see if anything in the bitmap isn't captured in temp_v. If yes, and if it has a afl->top_rated[] contender, let's use it. */ - for (i = 0; i < afl->fsrv.map_size; ++i) + for (i = 0; i < afl->fsrv.map_size; ++i) { + if (afl->top_rated[i] && (temp_v[i >> 3] & (1 << (i & 7)))) { u32 j = len; /* Remove all bits belonging to the current entry from temp_v. */ - while (j--) - if (afl->top_rated[i]->trace_mini[j]) + while (j--) { + + if (afl->top_rated[i]->trace_mini[j]) { + temp_v[j] &= ~afl->top_rated[i]->trace_mini[j]; + } + + } + afl->top_rated[i]->favored = 1; ++afl->queued_favored; - if (afl->top_rated[i]->fuzz_level == 0 || !afl->top_rated[i]->was_fuzzed) + if (afl->top_rated[i]->fuzz_level == 0 || + !afl->top_rated[i]->was_fuzzed) { + ++afl->pending_favored; + } + } + } + q = afl->queue; while (q) { @@ -347,39 +383,67 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { if (afl->schedule != MMOPT && afl->schedule != RARE && likely(!afl->fixed_seed)) { - if (q->exec_us * 0.1 > avg_exec_us) + if (q->exec_us * 0.1 > avg_exec_us) { + perf_score = 10; - else if (q->exec_us * 0.25 > avg_exec_us) + + } else if (q->exec_us * 0.25 > avg_exec_us) { + perf_score = 25; - else if (q->exec_us * 0.5 > avg_exec_us) + + } else if (q->exec_us * 0.5 > avg_exec_us) { + perf_score = 50; - else if (q->exec_us * 0.75 > avg_exec_us) + + } else if (q->exec_us * 0.75 > avg_exec_us) { + perf_score = 75; - else if (q->exec_us * 4 < avg_exec_us) + + } else if (q->exec_us * 4 < avg_exec_us) { + perf_score = 300; - else if (q->exec_us * 3 < avg_exec_us) + + } else if (q->exec_us * 3 < avg_exec_us) { + perf_score = 200; - else if (q->exec_us * 2 < avg_exec_us) + + } else if (q->exec_us * 2 < avg_exec_us) { + perf_score = 150; + } + } /* Adjust score based on bitmap size. The working theory is that better coverage translates to better targets. Multiplier from 0.25x to 3x. */ - if (q->bitmap_size * 0.3 > avg_bitmap_size) + if (q->bitmap_size * 0.3 > avg_bitmap_size) { + perf_score *= 3; - else if (q->bitmap_size * 0.5 > avg_bitmap_size) + + } else if (q->bitmap_size * 0.5 > avg_bitmap_size) { + perf_score *= 2; - else if (q->bitmap_size * 0.75 > avg_bitmap_size) + + } else if (q->bitmap_size * 0.75 > avg_bitmap_size) { + perf_score *= 1.5; - else if (q->bitmap_size * 3 < avg_bitmap_size) + + } else if (q->bitmap_size * 3 < avg_bitmap_size) { + perf_score *= 0.25; - else if (q->bitmap_size * 2 < avg_bitmap_size) + + } else if (q->bitmap_size * 2 < avg_bitmap_size) { + perf_score *= 0.5; - else if (q->bitmap_size * 1.5 < avg_bitmap_size) + + } else if (q->bitmap_size * 1.5 < avg_bitmap_size) { + perf_score *= 0.75; + } + /* Adjust score based on handicap. Handicap is proportional to how late in the game we learned about this path. Latecomers are allowed to run for a bit longer until they catch up with the rest. */ @@ -402,11 +466,19 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { switch (q->depth) { - case 0 ... 3: break; - case 4 ... 7: perf_score *= 2; break; - case 8 ... 13: perf_score *= 3; break; - case 14 ... 25: perf_score *= 4; break; - default: perf_score *= 5; + case 0 ... 3: + break; + case 4 ... 7: + perf_score *= 2; + break; + case 8 ... 13: + perf_score *= 3; + break; + case 14 ... 25: + perf_score *= 4; + break; + default: + perf_score *= 5; } @@ -418,9 +490,12 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { switch (afl->schedule) { - case EXPLORE: break; + case EXPLORE: + break; - case EXPLOIT: factor = MAX_FACTOR; break; + case EXPLOIT: + factor = MAX_FACTOR; + break; case COE: fuzz_total = 0; @@ -435,16 +510,21 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { } - if (unlikely(!n_paths)) FATAL("Queue state corrupt"); + if (unlikely(!n_paths)) { FATAL("Queue state corrupt"); } fuzz_mu = fuzz_total / n_paths; if (fuzz <= fuzz_mu) { - if (q->fuzz_level < 16) + if (q->fuzz_level < 16) { + factor = ((u32)(1 << q->fuzz_level)); - else + + } else { + factor = MAX_FACTOR; + } + } else { factor = 0; @@ -454,13 +534,21 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { break; case FAST: - if (q->fuzz_level < 16) + if (q->fuzz_level < 16) { + factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz); - else + + } else { + factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz)); + + } + break; - case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break; + case LIN: + factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); + break; case QUAD: factor = q->fuzz_level * q->fuzz_level / (fuzz == 0 ? 1 : fuzz); @@ -477,7 +565,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { (afl->max_depth - q->depth)) / 5)); */ // put focus on the last 5 entries - if (afl->max_depth - q->depth < 5) perf_score *= 2; + if (afl->max_depth - q->depth < 5) { perf_score *= 2; } break; @@ -493,26 +581,35 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) { break; - default: PFATAL("Unknown Power Schedule"); + default: + PFATAL("Unknown Power Schedule"); } - if (factor > MAX_FACTOR) factor = MAX_FACTOR; + if (factor > MAX_FACTOR) { factor = MAX_FACTOR; } perf_score *= factor / POWER_BETA; // MOpt mode - if (afl->limit_time_sig != 0 && afl->max_depth - q->depth < 3) + if (afl->limit_time_sig != 0 && afl->max_depth - q->depth < 3) { + perf_score *= 2; - else if (perf_score < 1) + + } else if (perf_score < 1) { + // Add a lower bound to AFLFast's energy assignment strategies perf_score = 1; + } + /* Make sure that we don't go over limit. */ - if (perf_score > afl->havoc_max_mult * 100) + if (perf_score > afl->havoc_max_mult * 100) { + perf_score = afl->havoc_max_mult * 100; + } + return perf_score; } diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 3e9af088..3a3e6be1 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -73,11 +73,16 @@ static struct range *pop_biggest_range(struct range **ranges) { if (rmax) { - if (prev_rmax) + if (prev_rmax) { + prev_rmax->next = rmax->next; - else + + } else { + *ranges = rmax->next; + } + } return rmax; @@ -86,7 +91,7 @@ static struct range *pop_biggest_range(struct range **ranges) { static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) { - if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1; + if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; } *cksum = hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST); return 0; @@ -96,9 +101,12 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u32 *cksum) { static void rand_replace(afl_state_t *afl, u8 *buf, u32 len) { u32 i; - for (i = 0; i < len; ++i) + for (i = 0; i < len; ++i) { + buf[i] = rand_below(afl, 256); + } + } static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { @@ -131,9 +139,12 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { u32 cksum; u64 start_us = get_cur_time_us(); - if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) + if (unlikely(get_exec_checksum(afl, buf, len, &cksum))) { + goto checksum_fail; + } + u64 stop_us = get_cur_time_us(); /* Discard if the mutations change the paths or if it is too decremental @@ -159,7 +170,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { } - if (afl->stage_cur < afl->stage_max) afl->queue_cur->fully_colorized = 1; + if (afl->stage_cur < afl->stage_max) { afl->queue_cur->fully_colorized = 1; } new_hit_cnt = afl->queued_paths + afl->unique_crashes; afl->stage_finds[STAGE_COLORIZATION] += new_hit_cnt - orig_hit_cnt; @@ -192,7 +203,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { } - if (fd < 0) PFATAL("Unable to create '%s'", afl->queue_cur->fname); + if (fd < 0) { PFATAL("Unable to create '%s'", afl->queue_cur->fname); } ck_write(fd, buf, len, afl->queue_cur->fname); afl->queue_cur->len = len; // no-op, just to be 100% safe @@ -204,7 +215,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { return 0; checksum_fail: - if (rng) ck_free(rng); + if (rng) { ck_free(rng); } ck_free(backup); while (ranges) { @@ -230,15 +241,20 @@ static u8 its_fuzz(afl_state_t *afl, u8 *buf, u32 len, u8 *status) { orig_hit_cnt = afl->queued_paths + afl->unique_crashes; - if (unlikely(common_fuzz_stuff(afl, buf, len))) return 1; + if (unlikely(common_fuzz_stuff(afl, buf, len))) { return 1; } new_hit_cnt = afl->queued_paths + afl->unique_crashes; - if (unlikely(new_hit_cnt != orig_hit_cnt)) + if (unlikely(new_hit_cnt != orig_hit_cnt)) { + *status = 1; - else + + } else { + *status = 2; + } + return 0; } @@ -265,18 +281,24 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (its_len >= 8 && *buf_64 == pattern && *o_buf_64 == o_pattern) { *buf_64 = repl; - if (unlikely(its_fuzz(afl, buf, len, status))) return 1; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } *buf_64 = pattern; } // reverse encoding - if (do_reverse) + if (do_reverse) { + if (unlikely(cmp_extend_encoding(afl, h, SWAP64(pattern), SWAP64(repl), SWAP64(o_pattern), idx, orig_buf, buf, - len, 0, status))) + len, 0, status))) { + return 1; + } + + } + } if (SHAPE_BYTES(h->shape) == 4 || *status == 2) { @@ -285,18 +307,24 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, *o_buf_32 == (u32)o_pattern) { *buf_32 = (u32)repl; - if (unlikely(its_fuzz(afl, buf, len, status))) return 1; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } *buf_32 = pattern; } // reverse encoding - if (do_reverse) + if (do_reverse) { + if (unlikely(cmp_extend_encoding(afl, h, SWAP32(pattern), SWAP32(repl), SWAP32(o_pattern), idx, orig_buf, buf, - len, 0, status))) + len, 0, status))) { + return 1; + } + + } + } if (SHAPE_BYTES(h->shape) == 2 || *status == 2) { @@ -305,18 +333,24 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, *o_buf_16 == (u16)o_pattern) { *buf_16 = (u16)repl; - if (unlikely(its_fuzz(afl, buf, len, status))) return 1; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } *buf_16 = (u16)pattern; } // reverse encoding - if (do_reverse) + if (do_reverse) { + if (unlikely(cmp_extend_encoding(afl, h, SWAP16(pattern), SWAP16(repl), SWAP16(o_pattern), idx, orig_buf, buf, - len, 0, status))) + len, 0, status))) { + return 1; + } + + } + } if (SHAPE_BYTES(h->shape) == 1 || *status == 2) { @@ -324,7 +358,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h, if (its_len >= 1 && *buf_8 == (u8)pattern && *o_buf_8 == (u8)o_pattern) { *buf_8 = (u8)repl; - if (unlikely(its_fuzz(afl, buf, len, status))) return 1; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } *buf_8 = (u8)pattern; } @@ -343,14 +377,21 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { u8 cons_ff = 0, cons_0 = 0; for (k = 0; k < shape; ++k) { - if (b[k] == 0) + if (b[k] == 0) { + ++cons_0; - else if (b[k] == 0xff) + + } else if (b[k] == 0xff) { + ++cons_0; - else + + } else { + cons_0 = cons_ff = 0; - if (cons_0 > 1 || cons_ff > 1) return; + } + + if (cons_0 > 1 || cons_ff > 1) { return; } } @@ -359,7 +400,8 @@ static void try_to_add_to_dict(afl_state_t *afl, u64 v, u8 shape) { u64 rev; switch (shape) { - case 1: break; + case 1: + break; case 2: rev = SWAP16((u16)v); maybe_add_auto((u8 *)afl, (u8 *)&rev, shape); @@ -383,7 +425,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { u32 i, j, idx; u32 loggeds = h->hits; - if (h->hits > CMP_MAP_H) loggeds = CMP_MAP_H; + if (h->hits > CMP_MAP_H) { loggeds = CMP_MAP_H; } u8 status = 0; // opt not in the paper @@ -410,12 +452,12 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { } else { - if (s_v0 != o->v0) s_v0_fixed = 0; - if (s_v1 != o->v1) s_v1_fixed = 0; - if (s_v0 + 1 != o->v0) s_v0_inc = 0; - if (s_v1 + 1 != o->v1) s_v1_inc = 0; - if (s_v0 - 1 != o->v0) s_v0_dec = 0; - if (s_v1 - 1 != o->v1) s_v1_dec = 0; + if (s_v0 != o->v0) { s_v0_fixed = 0; } + if (s_v1 != o->v1) { s_v1_fixed = 0; } + if (s_v0 + 1 != o->v0) { s_v0_inc = 0; } + if (s_v1 + 1 != o->v1) { s_v1_inc = 0; } + if (s_v0 - 1 != o->v0) { s_v0_dec = 0; } + if (s_v1 - 1 != o->v1) { s_v1_dec = 0; } s_v0 = o->v0; s_v1 = o->v1; @@ -424,32 +466,56 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { struct cmp_operands *orig_o = &afl->orig_cmp_map->log[key][i]; // opt not in the paper - for (j = 0; j < i; ++j) + for (j = 0; j < i; ++j) { + if (afl->shm.cmp_map->log[key][j].v0 == o->v0 && - afl->shm.cmp_map->log[key][i].v1 == o->v1) + afl->shm.cmp_map->log[key][i].v1 == o->v1) { + goto cmp_fuzz_next_iter; + } + + } + for (idx = 0; idx < len && fails < 8; ++idx) { if (unlikely(cmp_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx, - orig_buf, buf, len, 1, &status))) + orig_buf, buf, len, 1, &status))) { + return 1; - if (status == 2) + + } + + if (status == 2) { + ++fails; - else if (status == 1) + + } else if (status == 1) { + break; + } + if (unlikely(cmp_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx, - orig_buf, buf, len, 1, &status))) + orig_buf, buf, len, 1, &status))) { + return 1; - if (status == 2) + + } + + if (status == 2) { + ++fails; - else if (status == 1) + + } else if (status == 1) { + break; + } + } - if (status == 1) found_one = 1; + if (status == 1) { found_one = 1; } // If failed, add to dictionary if (fails == 8) { @@ -481,7 +547,7 @@ static u8 cmp_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { } - if (afl->pass_stats[key].total < 0xff) afl->pass_stats[key].total++; + if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; } return 0; @@ -502,11 +568,14 @@ static u8 rtn_extend_encoding(afl_state_t *afl, struct cmp_header *h, for (i = 0; i < its_len; ++i) { if (pattern[idx + i] != buf[idx + i] || - o_pattern[idx + i] != orig_buf[idx + i] || *status == 1) + o_pattern[idx + i] != orig_buf[idx + i] || *status == 1) { + break; + } + buf[idx + i] = repl[idx + i]; - if (unlikely(its_fuzz(afl, buf, len, status))) return 1; + if (unlikely(its_fuzz(afl, buf, len, status))) { return 1; } } @@ -521,7 +590,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { u32 i, j, idx; u32 loggeds = h->hits; - if (h->hits > CMP_MAP_RTN_H) loggeds = CMP_MAP_RTN_H; + if (h->hits > CMP_MAP_RTN_H) { loggeds = CMP_MAP_RTN_H; } u8 status = 0; // opt not in the paper @@ -539,32 +608,56 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { &((struct cmpfn_operands *)afl->orig_cmp_map->log[key])[i]; // opt not in the paper - for (j = 0; j < i; ++j) + for (j = 0; j < i; ++j) { + if (!memcmp(&((struct cmpfn_operands *)afl->shm.cmp_map->log[key])[j], o, - sizeof(struct cmpfn_operands))) + sizeof(struct cmpfn_operands))) { + goto rtn_fuzz_next_iter; + } + + } + for (idx = 0; idx < len && fails < 8; ++idx) { if (unlikely(rtn_extend_encoding(afl, h, o->v0, o->v1, orig_o->v0, idx, - orig_buf, buf, len, &status))) + orig_buf, buf, len, &status))) { + return 1; - if (status == 2) + + } + + if (status == 2) { + ++fails; - else if (status == 1) + + } else if (status == 1) { + break; + } + if (unlikely(rtn_extend_encoding(afl, h, o->v1, o->v0, orig_o->v1, idx, - orig_buf, buf, len, &status))) + orig_buf, buf, len, &status))) { + return 1; - if (status == 2) + + } + + if (status == 2) { + ++fails; - else if (status == 1) + + } else if (status == 1) { + break; + } + } - if (status == 1) found_one = 1; + if (status == 1) { found_one = 1; } // If failed, add to dictionary if (fails == 8) { @@ -589,7 +682,7 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u32 len) { } - if (afl->pass_stats[key].total < 0xff) afl->pass_stats[key].total++; + if (afl->pass_stats[key].total < 0xff) { afl->pass_stats[key].total++; } return 0; @@ -602,25 +695,31 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, u32 exec_cksum) { u8 r = 1; - if (afl->orig_cmp_map == NULL) + if (afl->orig_cmp_map == NULL) { + afl->orig_cmp_map = ck_alloc_nozero(sizeof(struct cmp_map)); - if (afl->pass_stats == NULL) + } + + if (afl->pass_stats == NULL) { + afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W); + } + // do it manually, forkserver clear only afl->fsrv.trace_bits memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers)); - if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1; + if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; } memcpy(afl->orig_cmp_map, afl->shm.cmp_map, sizeof(struct cmp_map)); - if (unlikely(colorization(afl, buf, len, exec_cksum))) return 1; + if (unlikely(colorization(afl, buf, len, exec_cksum))) { return 1; } // do it manually, forkserver clear only afl->fsrv.trace_bits memset(afl->shm.cmp_map->headers, 0, sizeof(afl->shm.cmp_map->headers)); - if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) return 1; + if (unlikely(common_fuzz_cmplog_stuff(afl, buf, len))) { return 1; } u64 orig_hit_cnt, new_hit_cnt; u64 orig_execs = afl->fsrv.total_execs; @@ -634,33 +733,41 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len, u32 k; for (k = 0; k < CMP_MAP_W; ++k) { - if (!afl->shm.cmp_map->headers[k].hits) continue; + if (!afl->shm.cmp_map->headers[k].hits) { continue; } if (afl->pass_stats[k].total && (rand_below(afl, afl->pass_stats[k].total) >= afl->pass_stats[k].faileds || - afl->pass_stats[k].total == 0xff)) + afl->pass_stats[k].total == 0xff)) { + afl->shm.cmp_map->headers[k].hits = 0; // blacklist this cmp - if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) + } + + if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) { + afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H); - else + + } else { + afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H); + } + } for (k = 0; k < CMP_MAP_W; ++k) { - if (!afl->shm.cmp_map->headers[k].hits) continue; + if (!afl->shm.cmp_map->headers[k].hits) { continue; } if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS) { - if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, len))) goto exit_its; + if (unlikely(cmp_fuzz(afl, k, orig_buf, buf, len))) { goto exit_its; } } else { - if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, len))) goto exit_its; + if (unlikely(rtn_fuzz(afl, k, orig_buf, buf, len))) { goto exit_its; } } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index 30ba0e65..bf8c4ec0 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -72,9 +72,12 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) { size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem, len, &new_buf); - if (unlikely(!new_buf)) + if (unlikely(!new_buf)) { + FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size); + } + /* everything as planned. use the new data. */ afl_fsrv_write_to_testcase(&afl->fsrv, new_buf, new_size); @@ -108,27 +111,34 @@ static void write_with_gap(afl_state_t *afl, void *mem, u32 len, u32 skip_at, } - if (fd < 0) PFATAL("Unable to create '%s'", afl->fsrv.out_file); + if (fd < 0) { PFATAL("Unable to create '%s'", afl->fsrv.out_file); } - } else + } else { lseek(fd, 0, SEEK_SET); - if (skip_at) ck_write(fd, mem, skip_at, afl->fsrv.out_file); + } + + if (skip_at) { ck_write(fd, mem, skip_at, afl->fsrv.out_file); } u8 *memu8 = mem; - if (tail_len) + if (tail_len) { + ck_write(fd, memu8 + skip_at + skip_len, tail_len, afl->fsrv.out_file); + } + if (!afl->fsrv.out_file) { - if (ftruncate(fd, len - skip_len)) PFATAL("ftruncate() failed"); + if (ftruncate(fd, len - skip_len)) { PFATAL("ftruncate() failed"); } lseek(fd, 0, SEEK_SET); - } else + } else { close(fd); + } + } /* Calibrate a new test case. This is done when processing the input directory @@ -151,10 +161,13 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, trying to calibrate already-added finds. This helps avoid trouble due to intermittent latency. */ - if (!from_queue || afl->resuming_fuzz) + if (!from_queue || afl->resuming_fuzz) { + use_tmout = MAX(afl->fsrv.exec_tmout + CAL_TMOUT_ADD, afl->fsrv.exec_tmout * CAL_TMOUT_PERC / 100); + } + ++q->cal_failed; afl->stage_name = "calibration"; @@ -177,18 +190,24 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } - if (q->exec_cksum) + if (q->exec_cksum) { + memcpy(afl->first_trace, afl->fsrv.trace_bits, afl->fsrv.map_size); + } + start_us = get_cur_time_us(); for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) { u32 cksum; - if (!first_run && !(afl->stage_cur % afl->stats_update_freq)) + if (!first_run && !(afl->stage_cur % afl->stats_update_freq)) { + show_stats(afl); + } + write_to_testcase(afl, use_mem, q->len); fault = fuzz_run_target(afl, &afl->fsrv, use_tmout); @@ -196,7 +215,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, /* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed, we want to bail out quickly. */ - if (afl->stop_soon || fault != afl->crash_mode) goto abort_calibration; + if (afl->stop_soon || fault != afl->crash_mode) { goto abort_calibration; } if (!afl->dumb_mode && !afl->stage_cur && !count_bytes(afl, afl->fsrv.trace_bits)) { @@ -211,7 +230,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, if (q->exec_cksum != cksum) { u8 hnb = has_new_bits(afl, afl->virgin_bits); - if (hnb > new_bits) new_bits = hnb; + if (hnb > new_bits) { new_bits = hnb; } if (q->exec_cksum) { @@ -220,9 +239,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, for (i = 0; i < afl->fsrv.map_size; ++i) { if (unlikely(!afl->var_bytes[i]) && - unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i])) + unlikely(afl->first_trace[i] != afl->fsrv.trace_bits[i])) { + afl->var_bytes[i] = 1; + } + } var_detected = 1; @@ -261,9 +283,12 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, parent. This is a non-critical problem, but something to warn the user about. */ - if (!afl->dumb_mode && first_run && !fault && !new_bits) + if (!afl->dumb_mode && first_run && !fault && !new_bits) { + fault = FSRV_RUN_NOBITS; + } + abort_calibration: if (new_bits == 2 && !q->has_new_cov) { @@ -292,7 +317,7 @@ abort_calibration: afl->stage_cur = old_sc; afl->stage_max = old_sm; - if (!first_run) show_stats(afl); + if (!first_run) { show_stats(afl); } return fault; @@ -307,7 +332,7 @@ void sync_fuzzers(afl_state_t *afl) { u32 sync_cnt = 0; sd = opendir(afl->sync_dir); - if (!sd) PFATAL("Unable to open '%s'", afl->sync_dir); + if (!sd) { PFATAL("Unable to open '%s'", afl->sync_dir); } afl->stage_max = afl->stage_cur = 0; afl->cur_depth = 0; @@ -326,9 +351,12 @@ void sync_fuzzers(afl_state_t *afl) { /* Skip dot files and our own output directory. */ - if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) + if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) { + continue; + } + /* Skip anything that doesn't have a queue/ subdirectory. */ qd_path = alloc_printf("%s/%s/queue", afl->sync_dir, sd_ent->d_name); @@ -347,9 +375,13 @@ void sync_fuzzers(afl_state_t *afl) { id_fd = open(qd_synced_path, O_RDWR | O_CREAT, 0600); - if (id_fd < 0) PFATAL("Unable to create '%s'", qd_synced_path); + if (id_fd < 0) { PFATAL("Unable to create '%s'", qd_synced_path); } - if (read(id_fd, &min_accept, sizeof(u32)) > 0) lseek(id_fd, 0, SEEK_SET); + if (read(id_fd, &min_accept, sizeof(u32)) > 0) { + + lseek(id_fd, 0, SEEK_SET); + + } next_min_accept = min_accept; @@ -372,14 +404,20 @@ void sync_fuzzers(afl_state_t *afl) { if (qd_ent->d_name[0] == '.' || sscanf(qd_ent->d_name, CASE_PREFIX "%06u", &afl->syncing_case) != 1 || - afl->syncing_case < min_accept) + afl->syncing_case < min_accept) { + continue; + } + /* OK, sounds like a new one. Let's give it a try. */ - if (afl->syncing_case >= next_min_accept) + if (afl->syncing_case >= next_min_accept) { + next_min_accept = afl->syncing_case + 1; + } + path = alloc_printf("%s/%s", qd_path, qd_ent->d_name); /* Allow this to fail in case the other fuzzer is resuming or so... */ @@ -393,7 +431,7 @@ void sync_fuzzers(afl_state_t *afl) { } - if (fstat(fd, &st)) PFATAL("fstat() failed"); + if (fstat(fd, &st)) { PFATAL("fstat() failed"); } /* Ignore zero-sized or oversized files. */ @@ -402,7 +440,7 @@ void sync_fuzzers(afl_state_t *afl) { u8 fault; u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0); - if (mem == MAP_FAILED) PFATAL("Unable to mmap '%s'", path); + if (mem == MAP_FAILED) { PFATAL("Unable to mmap '%s'", path); } /* See what happens. We rely on save_if_interesting() to catch major errors and save the test case. */ @@ -411,7 +449,7 @@ void sync_fuzzers(afl_state_t *afl) { fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); - if (afl->stop_soon) goto close_sync; + if (afl->stop_soon) { goto close_sync; } afl->syncing_party = sd_ent->d_name; afl->queued_imported += @@ -420,7 +458,7 @@ void sync_fuzzers(afl_state_t *afl) { munmap(mem, st.st_size); - if (!(afl->stage_cur++ % afl->stats_update_freq)) show_stats(afl); + if (!(afl->stage_cur++ % afl->stats_update_freq)) { show_stats(afl); } } @@ -450,9 +488,12 @@ void sync_fuzzers(afl_state_t *afl) { u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { /* Custom mutator trimmer */ - if (afl->mutator && afl->mutator->afl_custom_trim) + if (afl->mutator && afl->mutator->afl_custom_trim) { + return trim_case_custom(afl, q, in_buf); + } + u8 needs_write = 0, fault = 0; u32 trim_exec = 0; u32 remove_len; @@ -464,7 +505,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { detected, it will still work to some extent, so we don't check for this. */ - if (q->len < 5) return 0; + if (q->len < 5) { return 0; } afl->stage_name = afl->stage_name_buf; afl->bytes_trim_in += q->len; @@ -499,7 +540,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); ++afl->trim_execs; - if (afl->stop_soon || fault == FSRV_RUN_ERROR) goto abort_trimming; + if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; } /* Note that we don't keep track of crashes or hangs here; maybe TODO? */ @@ -531,13 +572,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - } else + } else { remove_pos += remove_len; + } + /* Since this can be slow, update the screen every now and then. */ - if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl); + if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); } ++afl->stage_cur; } @@ -564,7 +607,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) { } - if (fd < 0) PFATAL("Unable to create '%s'", q->fname); + if (fd < 0) { PFATAL("Unable to create '%s'", q->fname); } ck_write(fd, in_buf, q->len, q->fname); close(fd); @@ -595,7 +638,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { size_t post_len = afl->post_handler(afl->post_data, out_buf, len, &post_buf); - if (!post_buf || !post_len) return 0; + if (!post_buf || !post_len) { return 0; } out_buf = post_buf; len = post_len; @@ -605,7 +648,7 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout); - if (afl->stop_soon) return 1; + if (afl->stop_soon) { return 1; } if (fault == FSRV_RUN_TMOUT) { @@ -616,10 +659,12 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { } - } else + } else { afl->subseq_tmouts = 0; + } + /* Users can hit us with SIGUSR1 to request the current input to be abandoned. */ @@ -636,9 +681,12 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) { afl->queued_discovered += save_if_interesting(afl, out_buf, len, fault); if (!(afl->stage_cur % afl->stats_update_freq) || - afl->stage_cur + 1 == afl->stage_max) + afl->stage_cur + 1 == afl->stage_max) { + show_stats(afl); + } + return 0; } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index de7a4481..b38c9ec5 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -81,7 +81,7 @@ 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; } afl->w_init = 0.9; afl->w_end = 0.3; @@ -344,10 +344,12 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } - } else + } else { i++; + } + } if (match == 0) { @@ -361,7 +363,7 @@ void read_afl_environment(afl_state_t *afl, char **envp) { } - if (found) sleep(2); + if (found) { sleep(2); } } @@ -369,18 +371,18 @@ void read_afl_environment(afl_state_t *afl, char **envp) { void afl_state_deinit(afl_state_t *afl) { - if (afl->post_deinit) afl->post_deinit(afl->post_data); - if (afl->in_place_resume) ck_free(afl->in_dir); - if (afl->sync_id) ck_free(afl->out_dir); - if (afl->pass_stats) ck_free(afl->pass_stats); - if (afl->orig_cmp_map) ck_free(afl->orig_cmp_map); - - if (afl->out_buf) free(afl->out_buf); - if (afl->out_scratch_buf) free(afl->out_scratch_buf); - if (afl->eff_buf) free(afl->eff_buf); - if (afl->in_buf) free(afl->in_buf); - if (afl->in_scratch_buf) free(afl->in_scratch_buf); - if (afl->ex_buf) free(afl->ex_buf); + if (afl->post_deinit) { afl->post_deinit(afl->post_data); } + if (afl->in_place_resume) { ck_free(afl->in_dir); } + if (afl->sync_id) { ck_free(afl->out_dir); } + if (afl->pass_stats) { ck_free(afl->pass_stats); } + if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); } + + if (afl->out_buf) { free(afl->out_buf); } + if (afl->out_scratch_buf) { free(afl->out_scratch_buf); } + if (afl->eff_buf) { free(afl->eff_buf); } + if (afl->in_buf) { free(afl->in_buf); } + if (afl->in_scratch_buf) { free(afl->in_scratch_buf); } + if (afl->ex_buf) { free(afl->ex_buf); } ck_free(afl->virgin_bits); ck_free(afl->virgin_tmout); diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index c507b7f7..3cbb2d8c 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -43,11 +43,11 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", fn); + if (fd < 0) { PFATAL("Unable to create '%s'", fn); } f = fdopen(fd, "w"); - if (!f) PFATAL("fdopen() failed"); + if (!f) { PFATAL("fdopen() failed"); } /* Keep last values in case we're called from another context where exec/sec stats and such are not readily available. */ @@ -65,7 +65,7 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability, } - if (getrusage(RUSAGE_CHILDREN, &rus)) rus.ru_maxrss = 0; + if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; } fprintf( f, @@ -153,9 +153,12 @@ void maybe_update_plot_file(afl_state_t *afl, double bitmap_cvg, double eps) { afl->plot_prev_uc == afl->unique_crashes && afl->plot_prev_uh == afl->unique_hangs && afl->plot_prev_md == afl->max_depth) || - unlikely(!afl->queue_cycle)) + unlikely(!afl->queue_cycle)) { + return; + } + afl->plot_prev_qp = afl->queued_paths; afl->plot_prev_pf = afl->pending_favored; afl->plot_prev_pnf = afl->pending_not_fuzzed; @@ -190,10 +193,10 @@ static void check_term_size(afl_state_t *afl) { afl->term_too_small = 0; - if (ioctl(1, TIOCGWINSZ, &ws)) return; + if (ioctl(1, TIOCGWINSZ, &ws)) { return; } - if (ws.ws_row == 0 || ws.ws_col == 0) return; - if (ws.ws_row < 24 || ws.ws_col < 79) afl->term_too_small = 1; + if (ws.ws_row == 0 || ws.ws_col == 0) { return; } + if (ws.ws_row < 24 || ws.ws_col < 79) { afl->term_too_small = 1; } } @@ -241,12 +244,15 @@ void show_stats(afl_state_t *afl) { /* If not enough time has passed since last UI update, bail out. */ if (cur_ms - afl->stats_last_ms < 1000 / UI_TARGET_HZ && - !afl->force_ui_update) + !afl->force_ui_update) { + return; + } + /* Check if we're past the 10 minute mark. */ - if (cur_ms - afl->start_time > 10 * 60 * 1000) afl->run_over10m = 1; + if (cur_ms - afl->start_time > 10 * 60 * 1000) { afl->run_over10m = 1; } /* Calculate smoothed exec speed stats. */ @@ -263,9 +269,13 @@ void show_stats(afl_state_t *afl) { /* If there is a dramatic (5x+) jump in speed, reset the indicator more quickly. */ - if (cur_avg * 5 < afl->stats_avg_exec || cur_avg / 5 > afl->stats_avg_exec) + if (cur_avg * 5 < afl->stats_avg_exec || + cur_avg / 5 > afl->stats_avg_exec) { + afl->stats_avg_exec = cur_avg; + } + afl->stats_avg_exec = afl->stats_avg_exec * (1.0 - 1.0 / AVG_SMOOTHING) + cur_avg * (1.0 / AVG_SMOOTHING); @@ -277,18 +287,23 @@ void show_stats(afl_state_t *afl) { /* Tell the callers when to contact us (as measured in execs). */ afl->stats_update_freq = afl->stats_avg_exec / (UI_TARGET_HZ * 10); - if (!afl->stats_update_freq) afl->stats_update_freq = 1; + if (!afl->stats_update_freq) { afl->stats_update_freq = 1; } /* Do some bitmap stats. */ t_bytes = count_non_255_bytes(afl, afl->virgin_bits); t_byte_ratio = ((double)t_bytes * 100) / afl->fsrv.map_size; - if (likely(t_bytes) && unlikely(afl->var_byte_count)) + if (likely(t_bytes) && unlikely(afl->var_byte_count)) { + stab_ratio = 100 - (((double)afl->var_byte_count * 100) / t_bytes); - else + + } else { + stab_ratio = 100; + } + /* Roughly every minute, update fuzzer stats and save auto tokens. */ if (cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000) { @@ -312,19 +327,25 @@ void show_stats(afl_state_t *afl) { /* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */ if (!afl->dumb_mode && afl->cycles_wo_finds > 100 && - !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) + !afl->pending_not_fuzzed && afl->afl_env.afl_exit_when_done) { + afl->stop_soon = 2; - if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) + } + + if (afl->total_crashes && afl->afl_env.afl_bench_until_crash) { + afl->stop_soon = 2; + } + /* If we're not on TTY, bail out. */ - if (afl->not_on_tty) return; + if (afl->not_on_tty) { return; } /* If we haven't started doing things, bail out. */ - if (!afl->queue_cur) return; + if (!afl->queue_cur) { return; } /* Compute some mildly useful bitmap stats. */ @@ -389,9 +410,9 @@ void show_stats(afl_state_t *afl) { /* Lord, forgive me this. */ - SAYF(SET_G1 bSTG bLT bH bSTOP cCYA + SAYF(SET_G1 bSTG bLT bH bSTOP cCYA " process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA - " overall results " bSTG bH2 bH2 bRT "\n"); + " overall results " bSTG bH2 bH2 bRT "\n"); if (afl->dumb_mode) { @@ -402,24 +423,33 @@ void show_stats(afl_state_t *afl) { u64 min_wo_finds = (cur_ms - afl->last_path_time) / 1000 / 60; /* First queue cycle: don't stop now! */ - if (afl->queue_cycle == 1 || min_wo_finds < 15) + if (afl->queue_cycle == 1 || min_wo_finds < 15) { + strcpy(tmp, cMGN); - else + + } else /* Subsequent cycles, but we're still making finds. */ - if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) + if (afl->cycles_wo_finds < 25 || min_wo_finds < 30) { + strcpy(tmp, cYEL); - else + + } else /* No finds for a long time and no test cases to try. */ if (afl->cycles_wo_finds > 100 && !afl->pending_not_fuzzed && - min_wo_finds > 120) + min_wo_finds > 120) { + strcpy(tmp, cLGN); - /* Default: cautiously OK to stop? */ - else + /* Default: cautiously OK to stop? */ + + } else { + strcpy(tmp, cLBL); + } + } u_stringify_time_diff(time_tmp, cur_ms, afl->start_time); @@ -439,16 +469,18 @@ void show_stats(afl_state_t *afl) { } else { - if (afl->dumb_mode) + if (afl->dumb_mode) { SAYF(bV bSTOP " last new path : " cPIN "n/a" cRST " (non-instrumented mode) "); - else + } else { SAYF(bV bSTOP " last new path : " cRST "none yet " cLRD "(odd, check syntax!) "); + } + } SAYF(bSTG bV bSTOP " total paths : " cRST "%-5s " bSTG bV "\n", @@ -473,9 +505,9 @@ void show_stats(afl_state_t *afl) { " uniq hangs : " cRST "%-6s" bSTG bV "\n", time_tmp, tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA - " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); + " map coverage " bSTG bH bHT bH20 bH2 bVL "\n"); /* This gets funny because we want to print several variable-length variables together, but then cram them into a fixed-width field - so we need to @@ -505,9 +537,9 @@ void show_stats(afl_state_t *afl) { SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp); - SAYF(bVR bH bSTOP cCYA + SAYF(bVR bH bSTOP cCYA " stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA - " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); + " findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n"); sprintf(tmp, "%s (%0.02f%%)", u_stringify_int(IB(0), afl->queued_favored), ((double)afl->queued_favored) * 100 / afl->queued_paths); @@ -581,7 +613,7 @@ void show_stats(afl_state_t *afl) { /* Aaaalmost there... hold on! */ - SAYF(bVR bH cCYA bSTOP + SAYF(bVR bH cCYA bSTOP " fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA " path geometry " bSTG bH5 bH2 bVL "\n"); @@ -605,7 +637,8 @@ void show_stats(afl_state_t *afl) { " levels : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->max_depth)); - if (!afl->skip_deterministic) + if (!afl->skip_deterministic) { + sprintf(tmp, "%s/%s, %s/%s, %s/%s", u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]), @@ -614,11 +647,14 @@ void show_stats(afl_state_t *afl) { u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]), u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32])); + } + SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP " pending : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_not_fuzzed)); - if (!afl->skip_deterministic) + if (!afl->skip_deterministic) { + sprintf(tmp, "%s/%s, %s/%s, %s/%s", u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]), @@ -627,11 +663,14 @@ void show_stats(afl_state_t *afl) { u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]), u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32])); + } + SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP " pend fav : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->pending_favored)); - if (!afl->skip_deterministic) + if (!afl->skip_deterministic) { + sprintf(tmp, "%s/%s, %s/%s, %s/%s", u_stringify_int(IB(0), afl->stage_finds[STAGE_INTEREST8]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_INTEREST8]), @@ -640,11 +679,14 @@ void show_stats(afl_state_t *afl) { u_stringify_int(IB(4), afl->stage_finds[STAGE_INTEREST32]), u_stringify_int(IB(5), afl->stage_cycles[STAGE_INTEREST32])); + } + SAYF(bV bSTOP " known ints : " cRST "%-36s " bSTG bV bSTOP " own finds : " cRST "%-10s" bSTG bV "\n", tmp, u_stringify_int(IB(0), afl->queued_discovered)); - if (!afl->skip_deterministic) + if (!afl->skip_deterministic) { + sprintf(tmp, "%s/%s, %s/%s, %s/%s", u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]), u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]), @@ -653,6 +695,8 @@ void show_stats(afl_state_t *afl) { u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]), u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO])); + } + SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP " imported : " cRST "%-10s" bSTG bV "\n", tmp, @@ -669,11 +713,16 @@ void show_stats(afl_state_t *afl) { SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp); - if (t_bytes) + if (t_bytes) { + sprintf(tmp, "%0.02f%%", stab_ratio); - else + + } else { + strcpy(tmp, "n/a"); + } + SAYF(" stability : %s%-10s" bSTG bV "\n", (stab_ratio < 85 && afl->var_byte_count > 40) ? cLRD @@ -769,14 +818,17 @@ void show_stats(afl_state_t *afl) { /* If we could still run one or more processes, use green. */ - if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) + if (afl->cpu_core_count > 1 && cur_runnable + 1 <= afl->cpu_core_count) { + cpu_color = cLGN; + } + /* If we're clearly oversubscribed, use red. */ - if (!afl->no_cpu_meter_red && cur_utilization >= 150) cpu_color = cLRD; + if (!afl->no_cpu_meter_red && cur_utilization >= 150) { cpu_color = cLRD; } - if (afl->fsrv.snapshot) spacing = snap; + if (afl->fsrv.snapshot) { spacing = snap; } #ifdef HAVE_AFFINITY @@ -799,10 +851,12 @@ void show_stats(afl_state_t *afl) { #endif /* ^HAVE_AFFINITY */ - } else + } else { SAYF("\r"); + } + /* Last line */ SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1); @@ -829,17 +883,21 @@ void show_init_stats(afl_state_t *afl) { u8 val_bufs[4][STRINGIFY_VAL_SIZE_MAX]; #define IB(i) val_bufs[(i)], sizeof(val_bufs[(i)]) - if (afl->total_cal_cycles) avg_us = afl->total_cal_us / afl->total_cal_cycles; + if (afl->total_cal_cycles) { + + avg_us = afl->total_cal_us / afl->total_cal_cycles; + + } while (q) { - if (!min_us || q->exec_us < min_us) min_us = q->exec_us; - if (q->exec_us > max_us) max_us = q->exec_us; + if (!min_us || q->exec_us < min_us) { min_us = q->exec_us; } + if (q->exec_us > max_us) { max_us = q->exec_us; } - if (!min_bits || q->bitmap_size < min_bits) min_bits = q->bitmap_size; - if (q->bitmap_size > max_bits) max_bits = q->bitmap_size; + if (!min_bits || q->bitmap_size < min_bits) { min_bits = q->bitmap_size; } + if (q->bitmap_size > max_bits) { max_bits = q->bitmap_size; } - if (q->len > max_len) max_len = q->len; + if (q->len > max_len) { max_len = q->len; } q = q->next; @@ -847,38 +905,61 @@ void show_init_stats(afl_state_t *afl) { SAYF("\n"); - if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) + if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) { + WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.", doc_path); + } + /* Let's keep things moving with slow binaries. */ - if (avg_us > 50000) + if (avg_us > 50000) { + afl->havoc_div = 10; /* 0-19 execs/sec */ - else if (avg_us > 20000) + + } else if (avg_us > 20000) { + afl->havoc_div = 5; /* 20-49 execs/sec */ - else if (avg_us > 10000) + + } else if (avg_us > 10000) { + afl->havoc_div = 2; /* 50-100 execs/sec */ + } + if (!afl->resuming_fuzz) { - if (max_len > 50 * 1024) + if (max_len > 50 * 1024) { + WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!", stringify_mem_size(IB(0), max_len), doc_path); - else if (max_len > 10 * 1024) + + } else if (max_len > 10 * 1024) { + WARNF("Some test cases are big (%s) - see %s/perf_tips.md.", stringify_mem_size(IB(0), max_len), doc_path); - if (afl->useless_at_start && !afl->in_bitmap) + } + + if (afl->useless_at_start && !afl->in_bitmap) { + WARNF(cLRD "Some test cases look useless. Consider using a smaller set."); - if (afl->queued_paths > 100) + } + + if (afl->queued_paths > 100) { + WARNF(cLRD "You probably have far too many input files! Consider trimming " "down."); - else if (afl->queued_paths > 20) + + } else if (afl->queued_paths > 20) { + WARNF("You have lots of input files; try starting small."); + } + } OKF("Here are some useful stats:\n\n" @@ -903,20 +984,30 @@ void show_init_stats(afl_state_t *afl) { random scheduler jitter is less likely to have any impact, and because our patience is wearing thin =) */ - if (avg_us > 50000) + if (avg_us > 50000) { + afl->fsrv.exec_tmout = avg_us * 2 / 1000; - else if (avg_us > 10000) + + } else if (avg_us > 10000) { + afl->fsrv.exec_tmout = avg_us * 3 / 1000; - else + + } else { + afl->fsrv.exec_tmout = avg_us * 5 / 1000; + } + afl->fsrv.exec_tmout = MAX(afl->fsrv.exec_tmout, max_us / 1000); afl->fsrv.exec_tmout = (afl->fsrv.exec_tmout + EXEC_TM_ROUND) / EXEC_TM_ROUND * EXEC_TM_ROUND; - if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) + if (afl->fsrv.exec_tmout > EXEC_TIMEOUT) { + afl->fsrv.exec_tmout = EXEC_TIMEOUT; + } + ACTF("No -t option specified, so I'll use exec timeout of %u ms.", afl->fsrv.exec_tmout); @@ -932,9 +1023,12 @@ void show_init_stats(afl_state_t *afl) { /* In dumb mode, re-running every timing out test case with a generous time limit is very expensive, so let's select a more conservative default. */ - if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout)) + if (afl->dumb_mode && !(afl->afl_env.afl_hang_tmout)) { + afl->hang_tmout = MIN(EXEC_TIMEOUT, afl->fsrv.exec_tmout * 2 + 100); + } + OKF("All set and ready to roll!"); #undef IB diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index efb65ba6..5920f5c0 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -37,7 +37,7 @@ static u8 *get_libradamsa_path(u8 *own_loc) { cp = alloc_printf("%s/libradamsa.so", tmp); - if (access(cp, X_OK)) FATAL("Unable to find '%s'", cp); + if (access(cp, X_OK)) { FATAL("Unable to find '%s'", cp); } return cp; @@ -53,12 +53,14 @@ static u8 *get_libradamsa_path(u8 *own_loc) { cp = alloc_printf("%s/libradamsa.so", own_copy); ck_free(own_copy); - if (!access(cp, X_OK)) return cp; + if (!access(cp, X_OK)) { return cp; } - } else + } else { ck_free(own_copy); + } + if (!access(AFL_PATH "/libradamsa.so", X_OK)) { return ck_strdup(AFL_PATH "/libradamsa.so"); @@ -148,7 +150,8 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) { "case\n\n", argv0, EXEC_TIMEOUT, MEM_LIMIT); - if (more_help > 1) + if (more_help > 1) { + SAYF( "Environment variables used:\n" "LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n" @@ -193,11 +196,15 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) { //"AFL_DEFER_FORKSRV: not supported anymore -> no effect, just a warning\n" "\n" ); - else + + } else { + SAYF( "To view also the supported environment variables of afl-fuzz please " "use \"-hh\".\n\n"); + } + #ifdef USE_PYTHON SAYF("Compiled with %s module support, see docs/custom_mutator.md\n", (char *)PYTHON_VERSION); @@ -216,13 +223,13 @@ static void usage(afl_state_t *afl, u8 *argv0, int more_help) { static int stricmp(char const *a, char const *b) { - if (!a || !b) FATAL("Null reference"); + if (!a || !b) { FATAL("Null reference"); } for (;; ++a, ++b) { int d; d = tolower(*a) - tolower(*b); - if (d != 0 || !*a) return d; + if (d != 0 || !*a) { return d; } } @@ -247,14 +254,14 @@ int main(int argc, char **argv_orig, char **envp) { afl_state_t *afl = calloc(1, sizeof(afl_state_t)); if (!afl) { FATAL("Could not create afl state"); } - if (get_afl_env("AFL_DEBUG")) afl->debug = 1; + if (get_afl_env("AFL_DEBUG")) { afl->debug = 1; } map_size = get_map_size(); afl_state_init(afl, map_size); afl_fsrv_init(&afl->fsrv); read_afl_environment(afl, envp); - if (afl->shm.map_size) afl->fsrv.map_size = afl->shm.map_size; + if (afl->shm.map_size) { afl->fsrv.map_size = afl->shm.map_size; } exit_1 = !!afl->afl_env.afl_bench_just_one; SAYF(cCYA "afl-fuzz" VERSION cRST @@ -266,11 +273,14 @@ int main(int argc, char **argv_orig, char **envp) { afl->init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid(); while ((opt = getopt(argc, argv, - "+c:i:I:o:f:m:t:T:dnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > 0) + "+c:i:I:o:f:m:t:T:dnCB:S:M:x:QNUWe:p:s:V:E:L:hRP:")) > + 0) { switch (opt) { - case 'I': afl->infoexec = optarg; break; + case 'I': + afl->infoexec = optarg; + break; case 'c': { @@ -334,7 +344,7 @@ int main(int argc, char **argv_orig, char **envp) { case 'e': - if (afl->file_extension) FATAL("Multiple -e options not supported"); + if (afl->file_extension) { FATAL("Multiple -e options not supported"); } afl->file_extension = optarg; @@ -342,16 +352,16 @@ int main(int argc, char **argv_orig, char **envp) { case 'i': /* input dir */ - if (afl->in_dir) FATAL("Multiple -i options not supported"); + if (afl->in_dir) { FATAL("Multiple -i options not supported"); } afl->in_dir = optarg; - if (!strcmp(afl->in_dir, "-")) afl->in_place_resume = 1; + if (!strcmp(afl->in_dir, "-")) { afl->in_place_resume = 1; } break; case 'o': /* output dir */ - if (afl->out_dir) FATAL("Multiple -o options not supported"); + if (afl->out_dir) { FATAL("Multiple -o options not supported"); } afl->out_dir = optarg; break; @@ -359,7 +369,7 @@ int main(int argc, char **argv_orig, char **envp) { u8 *c; - if (afl->sync_id) FATAL("Multiple -S or -M options not supported"); + if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); } afl->sync_id = ck_strdup(optarg); if ((c = strchr(afl->sync_id, ':'))) { @@ -368,9 +378,12 @@ int main(int argc, char **argv_orig, char **envp) { if (sscanf(c + 1, "%u/%u", &afl->master_id, &afl->master_max) != 2 || !afl->master_id || !afl->master_max || - afl->master_id > afl->master_max || afl->master_max > 1000000) + afl->master_id > afl->master_max || afl->master_max > 1000000) { + FATAL("Bogus master ID passed to -M"); + } + } afl->force_deterministic = 1; @@ -381,20 +394,20 @@ int main(int argc, char **argv_orig, char **envp) { case 'S': - if (afl->sync_id) FATAL("Multiple -S or -M options not supported"); + if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); } afl->sync_id = ck_strdup(optarg); break; case 'f': /* target file */ - if (afl->fsrv.out_file) FATAL("Multiple -f options not supported"); + if (afl->fsrv.out_file) { FATAL("Multiple -f options not supported"); } afl->fsrv.out_file = ck_strdup(optarg); afl->fsrv.use_stdin = 0; break; case 'x': /* dictionary */ - if (extras_dir) FATAL("Multiple -x options not supported"); + if (extras_dir) { FATAL("Multiple -x options not supported"); } extras_dir = optarg; break; @@ -402,19 +415,27 @@ int main(int argc, char **argv_orig, char **envp) { u8 suffix = 0; - if (afl->timeout_given) FATAL("Multiple -t options not supported"); + if (afl->timeout_given) { FATAL("Multiple -t options not supported"); } if (sscanf(optarg, "%u%c", &afl->fsrv.exec_tmout, &suffix) < 1 || - optarg[0] == '-') + optarg[0] == '-') { + FATAL("Bad syntax used for -t"); - if (afl->fsrv.exec_tmout < 5) FATAL("Dangerously low value of -t"); + } + + if (afl->fsrv.exec_tmout < 5) { FATAL("Dangerously low value of -t"); } + + if (suffix == '+') { - if (suffix == '+') afl->timeout_given = 2; - else + + } else { + afl->timeout_given = 1; + } + break; } @@ -423,10 +444,10 @@ int main(int argc, char **argv_orig, char **envp) { u8 suffix = 'M'; - if (mem_limit_given) FATAL("Multiple -m options not supported"); + if (mem_limit_given) { FATAL("Multiple -m options not supported"); } mem_limit_given = 1; - if (!optarg) FATAL("Wrong usage of -m"); + if (!optarg) { FATAL("Wrong usage of -m"); } if (!strcmp(optarg, "none")) { @@ -436,32 +457,51 @@ int main(int argc, char **argv_orig, char **envp) { } if (sscanf(optarg, "%llu%c", &afl->fsrv.mem_limit, &suffix) < 1 || - optarg[0] == '-') + optarg[0] == '-') { + FATAL("Bad syntax used for -m"); - switch (suffix) { + } - case 'T': afl->fsrv.mem_limit *= 1024 * 1024; break; - case 'G': afl->fsrv.mem_limit *= 1024; break; - case 'k': afl->fsrv.mem_limit /= 1024; break; - case 'M': break; + switch (suffix) { - default: FATAL("Unsupported suffix or bad syntax for -m"); + case 'T': + afl->fsrv.mem_limit *= 1024 * 1024; + break; + case 'G': + afl->fsrv.mem_limit *= 1024; + break; + case 'k': + afl->fsrv.mem_limit /= 1024; + break; + case 'M': + break; + + default: + FATAL("Unsupported suffix or bad syntax for -m"); } - if (afl->fsrv.mem_limit < 5) FATAL("Dangerously low value of -m"); + if (afl->fsrv.mem_limit < 5) { FATAL("Dangerously low value of -m"); } + + if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) { - if (sizeof(rlim_t) == 4 && afl->fsrv.mem_limit > 2000) FATAL("Value of -m out of range on 32-bit systems"); + } + } break; case 'd': /* skip deterministic */ - if (afl->skip_deterministic) FATAL("Multiple -d options not supported"); + if (afl->skip_deterministic) { + + FATAL("Multiple -d options not supported"); + + } + afl->skip_deterministic = 1; afl->use_splicing = 1; break; @@ -479,7 +519,7 @@ int main(int argc, char **argv_orig, char **envp) { I only used this once or twice to get variants of a particular file, so I'm not making this an official setting. */ - if (afl->in_bitmap) FATAL("Multiple -B options not supported"); + if (afl->in_bitmap) { FATAL("Multiple -B options not supported"); } afl->in_bitmap = optarg; read_bitmap(afl->in_bitmap, afl->virgin_bits, afl->fsrv.map_size); @@ -487,85 +527,99 @@ int main(int argc, char **argv_orig, char **envp) { case 'C': /* crash mode */ - if (afl->crash_mode) FATAL("Multiple -C options not supported"); + if (afl->crash_mode) { FATAL("Multiple -C options not supported"); } afl->crash_mode = FSRV_RUN_CRASH; break; case 'n': /* dumb mode */ - if (afl->dumb_mode) FATAL("Multiple -n options not supported"); - if (afl->afl_env.afl_dumb_forksrv) + if (afl->dumb_mode) { FATAL("Multiple -n options not supported"); } + if (afl->afl_env.afl_dumb_forksrv) { + afl->dumb_mode = 2; - else + + } else { + afl->dumb_mode = 1; + } + break; case 'T': /* banner */ - if (afl->use_banner) FATAL("Multiple -T options not supported"); + if (afl->use_banner) { FATAL("Multiple -T options not supported"); } afl->use_banner = optarg; break; case 'Q': /* QEMU mode */ - if (afl->fsrv.qemu_mode) FATAL("Multiple -Q options not supported"); + if (afl->fsrv.qemu_mode) { FATAL("Multiple -Q options not supported"); } afl->fsrv.qemu_mode = 1; - if (!mem_limit_given) afl->fsrv.mem_limit = MEM_LIMIT_QEMU; + if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_QEMU; } break; case 'N': /* Unicorn mode */ - if (afl->no_unlink) FATAL("Multiple -N options not supported"); + if (afl->no_unlink) { FATAL("Multiple -N options not supported"); } afl->no_unlink = 1; break; case 'U': /* Unicorn mode */ - if (afl->unicorn_mode) FATAL("Multiple -U options not supported"); + if (afl->unicorn_mode) { FATAL("Multiple -U options not supported"); } afl->unicorn_mode = 1; - if (!mem_limit_given) afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; + if (!mem_limit_given) { afl->fsrv.mem_limit = MEM_LIMIT_UNICORN; } break; case 'W': /* Wine+QEMU mode */ - if (afl->use_wine) FATAL("Multiple -W options not supported"); + if (afl->use_wine) { FATAL("Multiple -W options not supported"); } afl->fsrv.qemu_mode = 1; afl->use_wine = 1; - if (!mem_limit_given) afl->fsrv.mem_limit = 0; + if (!mem_limit_given) { afl->fsrv.mem_limit = 0; } break; case 'V': { afl->most_time_key = 1; - if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') + if (sscanf(optarg, "%llu", &afl->most_time) < 1 || optarg[0] == '-') { + FATAL("Bad syntax used for -V"); + } + } break; case 'E': { afl->most_execs_key = 1; - if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') + if (sscanf(optarg, "%llu", &afl->most_execs) < 1 || optarg[0] == '-') { + FATAL("Bad syntax used for -E"); + } + } break; case 'L': { /* MOpt mode */ - if (afl->limit_time_sig) FATAL("Multiple -L options not supported"); + if (afl->limit_time_sig) { FATAL("Multiple -L options not supported"); } afl->havoc_max_mult = HAVOC_MAX_MULT_MOPT; - if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) + if (sscanf(optarg, "%d", &afl->limit_time_puppet) < 1) { + FATAL("Bad syntax used for -L"); + } + if (afl->limit_time_puppet == -1) { afl->limit_time_sig = -1; @@ -583,19 +637,23 @@ int main(int argc, char **argv_orig, char **envp) { u64 limit_time_puppet2 = afl->limit_time_puppet * 60 * 1000; - if (limit_time_puppet2 < afl->limit_time_puppet) + if (limit_time_puppet2 < afl->limit_time_puppet) { + FATAL("limit_time overflow"); + + } + afl->limit_time_puppet = limit_time_puppet2; SAYF("limit_time_puppet %d\n", afl->limit_time_puppet); afl->swarm_now = 0; - if (afl->limit_time_puppet == 0) afl->key_puppet = 1; + if (afl->limit_time_puppet == 0) { afl->key_puppet = 1; } int i; int tmp_swarm = 0; - if (afl->g_now > afl->g_max) afl->g_now = 0; + if (afl->g_now > afl->g_max) { afl->g_now = 0; } afl->w_now = (afl->w_init - afl->w_end) * (afl->g_max - afl->g_now) / (afl->g_max) + afl->w_end; @@ -643,11 +701,16 @@ int main(int argc, char **argv_orig, char **envp) { afl->x_now[tmp_swarm][i] += afl->v_now[tmp_swarm][i]; - if (afl->x_now[tmp_swarm][i] > v_max) + if (afl->x_now[tmp_swarm][i] > v_max) { + afl->x_now[tmp_swarm][i] = v_max; - else if (afl->x_now[tmp_swarm][i] < v_min) + + } else if (afl->x_now[tmp_swarm][i] < v_min) { + afl->x_now[tmp_swarm][i] = v_min; + } + x_temp += afl->x_now[tmp_swarm][i]; } @@ -655,19 +718,27 @@ int main(int argc, char **argv_orig, char **envp) { for (i = 0; i < operator_num; ++i) { afl->x_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i] / x_temp; - if (likely(i != 0)) + if (likely(i != 0)) { + afl->probability_now[tmp_swarm][i] = afl->probability_now[tmp_swarm][i - 1] + afl->x_now[tmp_swarm][i]; - else + + } else { + afl->probability_now[tmp_swarm][i] = afl->x_now[tmp_swarm][i]; + } + } if (afl->probability_now[tmp_swarm][operator_num - 1] < 0.99 || - afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) + afl->probability_now[tmp_swarm][operator_num - 1] > 1.01) { + FATAL("ERROR probability"); + } + } for (i = 0; i < operator_num; ++i) { @@ -682,25 +753,37 @@ int main(int argc, char **argv_orig, char **envp) { } break; - case 'h': show_help++; break; // not needed + case 'h': + show_help++; + break; // not needed case 'R': - if (afl->use_radamsa) + if (afl->use_radamsa) { + afl->use_radamsa = 2; - else + + } else { + afl->use_radamsa = 1; + } + break; default: - if (!show_help) show_help = 1; + if (!show_help) { show_help = 1; } } - if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) + } + + if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) { + usage(afl, argv[0], show_help); + } + OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" " "Eißfeldt, Andrea Fioraldi and Dominik Maier"); OKF("afl++ is open source, get it at " @@ -711,40 +794,57 @@ int main(int argc, char **argv_orig, char **envp) { OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL"); if (afl->sync_id && afl->force_deterministic && - afl->afl_env.afl_custom_mutator_only) + afl->afl_env.afl_custom_mutator_only) { + WARNF( "Using -M master with the AFL_CUSTOM_MUTATOR_ONLY mutator options will " "result in no deterministic mutations being done!"); - if (afl->fixed_seed) OKF("Running with fixed seed: %u", (u32)afl->init_seed); + } + + if (afl->fixed_seed) { + + OKF("Running with fixed seed: %u", (u32)afl->init_seed); + + } + srandom((u32)afl->init_seed); srand((u32)afl->init_seed); // in case it is a different implementation if (afl->use_radamsa) { - if (afl->limit_time_sig > 0) + if (afl->limit_time_sig > 0) { + FATAL( "MOpt and Radamsa are mutually exclusive unless you specify -L -1. " "We accept pull requests that integrates MOpt with the optional " "mutators (custom/radamsa/redqueen/...)."); - if (afl->limit_time_sig && afl->use_radamsa > 1) + } + + if (afl->limit_time_sig && afl->use_radamsa > 1) { + FATAL("Radamsa in radamsa-only mode can not run together with -L"); + } + OKF("Using Radamsa add-on"); u8 * libradamsa_path = get_libradamsa_path(argv[0]); void *handle = dlopen(libradamsa_path, RTLD_NOW); ck_free(libradamsa_path); - if (!handle) FATAL("Failed to dlopen() libradamsa"); + if (!handle) { FATAL("Failed to dlopen() libradamsa"); } void (*radamsa_init_ptr)(void) = dlsym(handle, "radamsa_init"); afl->radamsa_mutate_ptr = dlsym(handle, "radamsa"); - if (!radamsa_init_ptr || !afl->radamsa_mutate_ptr) + if (!radamsa_init_ptr || !afl->radamsa_mutate_ptr) { + FATAL("Failed to dlsym() libradamsa"); + } + /* randamsa_init installs some signal hadlers, call it before setup_signal_handlers so that AFL++ can then replace those signal handlers */ @@ -767,80 +867,113 @@ int main(int argc, char **argv_orig, char **envp) { afl->power_name = power_names[afl->schedule]; - if (afl->sync_id) fix_up_sync(afl); + if (afl->sync_id) { fix_up_sync(afl); } + + if (!strcmp(afl->in_dir, afl->out_dir)) { - if (!strcmp(afl->in_dir, afl->out_dir)) FATAL("Input and output directories can't be the same"); + } + if (afl->dumb_mode) { - if (afl->crash_mode) FATAL("-C and -n are mutually exclusive"); - if (afl->fsrv.qemu_mode) FATAL("-Q and -n are mutually exclusive"); - if (afl->unicorn_mode) FATAL("-U and -n are mutually exclusive"); + if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); } + if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); } + if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); } } - if (get_afl_env("AFL_DISABLE_TRIM")) afl->disable_trim = 1; + if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; } + + if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) { - if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive"); - if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) + } + + if (strchr(argv[optind], '/') == NULL && !afl->unicorn_mode) { + WARNF(cLRD "Target binary called without a prefixed path, make sure you are " "fuzzing the right binary: " cRST "%s", argv[optind]); + } + ACTF("Getting to work..."); switch (afl->schedule) { - case FAST: OKF("Using exponential power schedule (FAST)"); break; - case COE: OKF("Using cut-off exponential power schedule (COE)"); break; + case FAST: + OKF("Using exponential power schedule (FAST)"); + break; + case COE: + OKF("Using cut-off exponential power schedule (COE)"); + break; case EXPLOIT: OKF("Using exploitation-based constant power schedule (EXPLOIT)"); break; - case LIN: OKF("Using linear power schedule (LIN)"); break; - case QUAD: OKF("Using quadratic power schedule (QUAD)"); break; - case MMOPT: OKF("Using modified MOpt power schedule (MMOPT)"); break; - case RARE: OKF("Using rare edge focus power schedule (RARE)"); break; + case LIN: + OKF("Using linear power schedule (LIN)"); + break; + case QUAD: + OKF("Using quadratic power schedule (QUAD)"); + break; + case MMOPT: + OKF("Using modified MOpt power schedule (MMOPT)"); + break; + case RARE: + OKF("Using rare edge focus power schedule (RARE)"); + break; case EXPLORE: OKF("Using exploration-based constant power schedule (EXPLORE, default)"); break; - default: FATAL("Unknown power schedule"); break; + default: + FATAL("Unknown power schedule"); + break; } - if (get_afl_env("AFL_NO_FORKSRV")) afl->no_forkserver = 1; - if (get_afl_env("AFL_NO_CPU_RED")) afl->no_cpu_meter_red = 1; - if (get_afl_env("AFL_NO_ARITH")) afl->no_arith = 1; - if (get_afl_env("AFL_SHUFFLE_QUEUE")) afl->shuffle_queue = 1; - if (get_afl_env("AFL_FAST_CAL")) afl->fast_cal = 1; + if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; } + if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; } + if (get_afl_env("AFL_NO_ARITH")) { afl->no_arith = 1; } + if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; } + if (get_afl_env("AFL_FAST_CAL")) { afl->fast_cal = 1; } if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; - if (afl->in_place_resume) SAYF("AFL_AUTORESUME has no effect for '-i -'"); + if (afl->in_place_resume) { + + SAYF("AFL_AUTORESUME has no effect for '-i -'"); + + } } if (afl->afl_env.afl_hang_tmout) { afl->hang_tmout = atoi(afl->afl_env.afl_hang_tmout); - if (!afl->hang_tmout) FATAL("Invalid value of AFL_HANG_TMOUT"); + if (!afl->hang_tmout) { FATAL("Invalid value of AFL_HANG_TMOUT"); } } - if (afl->dumb_mode == 2 && afl->no_forkserver) + if (afl->dumb_mode == 2 && afl->no_forkserver) { + FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive"); + } + afl->fsrv.use_fauxsrv = afl->dumb_mode == 1 || afl->no_forkserver; - if (getenv("LD_PRELOAD")) + if (getenv("LD_PRELOAD")) { + WARNF( "LD_PRELOAD is set, are you sure that is what to you want to do " "instead of using AFL_PRELOAD?"); + } + if (afl->afl_env.afl_preload) { if (afl->fsrv.qemu_mode) { @@ -852,20 +985,28 @@ int main(int argc, char **argv_orig, char **envp) { s32 i, afl_preload_size = strlen(afl_preload); for (i = 0; i < afl_preload_size; ++i) { - if (afl_preload[i] == ',') + if (afl_preload[i] == ',') { + PFATAL( "Comma (',') is not allowed in AFL_PRELOAD when -Q is " "specified!"); + } + } - if (qemu_preload) + if (qemu_preload) { + buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", qemu_preload, afl_preload, afl_preload); - else + + } else { + buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", afl_preload, afl_preload); + } + setenv("QEMU_SET_ENV", buf, 1); ck_free(buf); @@ -879,15 +1020,18 @@ int main(int argc, char **argv_orig, char **envp) { } - if (getenv("AFL_LD_PRELOAD")) + if (getenv("AFL_LD_PRELOAD")) { + FATAL("Use AFL_PRELOAD instead of AFL_LD_PRELOAD"); + } + save_cmdline(afl, argc, argv); fix_up_banner(afl, argv[optind]); check_if_tty(afl); - if (afl->afl_env.afl_force_ui) afl->not_on_tty = 0; + if (afl->afl_env.afl_force_ui) { afl->not_on_tty = 0; } if (afl->afl_env.afl_cal_fast) { @@ -921,7 +1065,7 @@ int main(int argc, char **argv_orig, char **envp) { setup_post(afl); - if (!afl->in_bitmap) memset(afl->virgin_bits, 255, afl->fsrv.map_size); + if (!afl->in_bitmap) { memset(afl->virgin_bits, 255, afl->fsrv.map_size); } memset(afl->virgin_tmout, 255, afl->fsrv.map_size); memset(afl->virgin_crash, 255, afl->fsrv.map_size); @@ -938,9 +1082,9 @@ int main(int argc, char **argv_orig, char **envp) { pivot_inputs(afl); - if (extras_dir) load_extras(afl, extras_dir); + if (extras_dir) { load_extras(afl, extras_dir); } - if (!afl->timeout_given) find_timeout(afl); + if (!afl->timeout_given) { find_timeout(afl); } if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL && !afl->in_place_resume) { @@ -959,16 +1103,21 @@ int main(int argc, char **argv_orig, char **envp) { } /* there is still a race condition here, but well ... */ - if (access(tmpfile, F_OK) != -1) + if (access(tmpfile, F_OK) != -1) { + FATAL( "AFL_TMPDIR already has an existing temporary input file: %s - if " "this is not from another instance, then just remove the file.", tmpfile); - } else + } + + } else { afl->tmp_dir = afl->out_dir; + } + /* If we don't have a file name chosen yet, use a safe default. */ if (!afl->fsrv.out_file) { @@ -1005,13 +1154,17 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!afl->fsrv.out_file) setup_stdio_file(afl); + if (!afl->fsrv.out_file) { setup_stdio_file(afl); } if (afl->cmplog_binary) { - if (afl->unicorn_mode) + if (afl->unicorn_mode) { + FATAL("CmpLog and Unicorn mode are not compatible at the moment, sorry"); - if (!afl->fsrv.qemu_mode) check_binary(afl, afl->cmplog_binary); + + } + + if (!afl->fsrv.qemu_mode) { check_binary(afl, afl->cmplog_binary); } } @@ -1021,13 +1174,18 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->fsrv.qemu_mode) { - if (afl->use_wine) + if (afl->use_wine) { + use_argv = get_wine_argv(argv[0], &afl->fsrv.target_path, argc - optind, argv + optind); - else + + } else { + use_argv = get_qemu_argv(argv[0], &afl->fsrv.target_path, argc - optind, argv + optind); + } + } else { use_argv = argv + optind; @@ -1062,7 +1220,7 @@ int main(int argc, char **argv_orig, char **envp) { maybe_update_plot_file(afl, 0, 0); save_auto(afl); - if (afl->stop_soon) goto stop_fuzzing; + if (afl->stop_soon) { goto stop_fuzzing; } /* Woop woop woop */ @@ -1070,7 +1228,7 @@ int main(int argc, char **argv_orig, char **envp) { sleep(4); afl->start_time += 4000; - if (afl->stop_soon) goto stop_fuzzing; + if (afl->stop_soon) { goto stop_fuzzing; } } @@ -1112,34 +1270,44 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->queued_paths == prev_queued) { - if (afl->use_splicing) + if (afl->use_splicing) { + ++afl->cycles_wo_finds; - else + + } else { + afl->use_splicing = 1; - } else + } + + } else { afl->cycles_wo_finds = 0; + } + prev_queued = afl->queued_paths; if (afl->sync_id && afl->queue_cycle == 1 && - afl->afl_env.afl_import_first) + afl->afl_env.afl_import_first) { + sync_fuzzers(afl); + } + } skipped_fuzz = fuzz_one(afl); if (!skipped_fuzz && !afl->stop_soon && afl->sync_id) { - if (!(sync_interval_cnt++ % SYNC_INTERVAL)) sync_fuzzers(afl); + if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); } } - if (!afl->stop_soon && exit_1) afl->stop_soon = 2; + if (!afl->stop_soon && exit_1) { afl->stop_soon = 2; } - if (afl->stop_soon) break; + if (afl->stop_soon) { break; } afl->queue_cur = afl->queue_cur->next; ++afl->current_entry; @@ -1159,11 +1327,18 @@ stop_fuzzing: SAYF(CURSOR_SHOW cLRD "\n\n+++ Testing aborted %s +++\n" cRST, afl->stop_soon == 2 ? "programmatically" : "by user"); - if (afl->most_time_key == 2) + if (afl->most_time_key == 2) { + SAYF(cYEL "[!] " cRST "Time limit was reached\n"); - if (afl->most_execs_key == 2) + + } + + if (afl->most_execs_key == 2) { + SAYF(cYEL "[!] " cRST "Execution limit was reached\n"); + } + /* Running for more than 30 minutes but still doing first cycle? */ if (afl->queue_cycle == 1 && @@ -1182,7 +1357,7 @@ stop_fuzzing: destroy_custom_mutator(afl); afl_shm_deinit(&afl->shm); afl_fsrv_deinit(&afl->fsrv); - if (afl->orig_cmdline) ck_free(afl->orig_cmdline); + if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); } ck_free(afl->fsrv.target_path); ck_free(afl->fsrv.out_file); ck_free(afl->sync_id); diff --git a/src/afl-gcc.c b/src/afl-gcc.c index 1ae10975..6c6bd1f1 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -128,11 +128,16 @@ static void edit_params(u32 argc, char **argv) { cc_params = ck_alloc((argc + 128) * sizeof(u8 *)); name = strrchr(argv[0], '/'); - if (!name) + if (!name) { + name = argv[0]; - else + + } else { + ++name; + } + if (!strncmp(name, "afl-clang", 9)) { clang_mode = 1; @@ -211,7 +216,7 @@ static void edit_params(u32 argc, char **argv) { if (!strncmp(cur, "-B", 2)) { - if (!be_quiet) WARNF("-B is already set, overriding"); + if (!be_quiet) { WARNF("-B is already set, overriding"); } if (!cur[2] && argc > 1) { @@ -224,18 +229,22 @@ static void edit_params(u32 argc, char **argv) { } - if (!strcmp(cur, "-integrated-as")) continue; + if (!strcmp(cur, "-integrated-as")) { continue; } - if (!strcmp(cur, "-pipe")) continue; + if (!strcmp(cur, "-pipe")) { continue; } #if defined(__FreeBSD__) && defined(WORD_SIZE_64) if (!strcmp(cur, "-m32")) m32_set = 1; #endif - if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory")) + if (!strcmp(cur, "-fsanitize=address") || + !strcmp(cur, "-fsanitize=memory")) { + asan_set = 1; - if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1; + } + + if (strstr(cur, "FORTIFY_SOURCE")) { fortify_set = 1; } cc_params[cc_par_cnt++] = cur; @@ -244,13 +253,13 @@ static void edit_params(u32 argc, char **argv) { cc_params[cc_par_cnt++] = "-B"; cc_params[cc_par_cnt++] = as_path; - if (clang_mode) cc_params[cc_par_cnt++] = "-no-integrated-as"; + if (clang_mode) { cc_params[cc_par_cnt++] = "-no-integrated-as"; } if (getenv("AFL_HARDEN")) { cc_params[cc_par_cnt++] = "-fstack-protector-all"; - if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; + if (!fortify_set) { cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2"; } } @@ -262,21 +271,35 @@ static void edit_params(u32 argc, char **argv) { } else if (getenv("AFL_USE_ASAN")) { - if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (getenv("AFL_USE_MSAN")) { + + FATAL("ASAN and MSAN are mutually exclusive"); + + } + + if (getenv("AFL_HARDEN")) { - if (getenv("AFL_HARDEN")) FATAL("ASAN and AFL_HARDEN are mutually exclusive"); + } + cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-fsanitize=address"; } else if (getenv("AFL_USE_MSAN")) { - if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive"); + if (getenv("AFL_USE_ASAN")) { + + FATAL("ASAN and MSAN are mutually exclusive"); + + } + + if (getenv("AFL_HARDEN")) { - if (getenv("AFL_HARDEN")) FATAL("MSAN and AFL_HARDEN are mutually exclusive"); + } + cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE"; cc_params[cc_par_cnt++] = "-fsanitize=memory"; @@ -386,10 +409,12 @@ int main(int argc, char **argv) { "afl-gcc is deprecated, llvm_mode is much faster and has more " "options\n"); - } else + } else { be_quiet = 1; + } + if (argc < 2) { SAYF( @@ -416,7 +441,11 @@ int main(int argc, char **argv) { ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE")))) { u32 map_size = atoi(ptr); - if (map_size != MAP_SIZE) FATAL("AFL_MAP_SIZE is not supported by afl-gcc"); + if (map_size != MAP_SIZE) { + + FATAL("AFL_MAP_SIZE is not supported by afl-gcc"); + + } } diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c index 6c2fa147..ab7aad5c 100644 --- a/src/afl-gotcpu.c +++ b/src/afl-gotcpu.c @@ -102,8 +102,12 @@ repeat_loop: v1 = CTEST_BUSY_CYCLES; - while (v1--) + while (v1--) { + v2++; + + } + sched_yield(); en_t = get_cur_time_us(); @@ -154,7 +158,7 @@ int main(int argc, char **argv) { s32 fr = fork(); - if (fr < 0) PFATAL("fork failed"); + if (fr < 0) { PFATAL("fork failed"); } if (!fr) { @@ -192,8 +196,12 @@ int main(int argc, char **argv) { #endif #if defined(__linux__) - if (sched_setaffinity(0, sizeof(c), &c)) + if (sched_setaffinity(0, sizeof(c), &c)) { + PFATAL("sched_setaffinity failed for cpu %d", i); + + } + #endif util_perc = measure_preemption(CTEST_CORE_TRG_MS); @@ -221,10 +229,10 @@ int main(int argc, char **argv) { for (i = 0; i < cpu_cnt; i++) { int ret; - if (waitpid(-1, &ret, 0) < 0) PFATAL("waitpid failed"); + if (waitpid(-1, &ret, 0) < 0) { PFATAL("waitpid failed"); } - if (WEXITSTATUS(ret) == 0) idle_cpus++; - if (WEXITSTATUS(ret) <= 1) maybe_cpus++; + if (WEXITSTATUS(ret) == 0) { idle_cpus++; } + if (WEXITSTATUS(ret) <= 1) { maybe_cpus++; } } diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index a130411e..94fca09e 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -86,7 +86,7 @@ void afl_shm_deinit(sharedmem_t *shm) { #else shmctl(shm->shm_id, IPC_RMID, NULL); - if (shm->cmplog_mode) shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); + if (shm->cmplog_mode) { shmctl(shm->cmplog_shm_id, IPC_RMID, NULL); } #endif shm->map = NULL; @@ -152,14 +152,14 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { shm->shm_id = shmget(IPC_PRIVATE, map_size, IPC_CREAT | IPC_EXCL | 0600); - if (shm->shm_id < 0) PFATAL("shmget() failed"); + if (shm->shm_id < 0) { PFATAL("shmget() failed"); } if (shm->cmplog_mode) { shm->cmplog_shm_id = shmget(IPC_PRIVATE, sizeof(struct cmp_map), IPC_CREAT | IPC_EXCL | 0600); - if (shm->cmplog_shm_id < 0) PFATAL("shmget() failed"); + if (shm->cmplog_shm_id < 0) { PFATAL("shmget() failed"); } } @@ -170,7 +170,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { fork server commands. This should be replaced with better auto-detection later on, perhaps? */ - if (!dumb_mode) setenv(SHM_ENV_VAR, shm_str, 1); + if (!dumb_mode) { setenv(SHM_ENV_VAR, shm_str, 1); } ck_free(shm_str); @@ -178,7 +178,7 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { shm_str = alloc_printf("%d", shm->cmplog_shm_id); - if (!dumb_mode) setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); + if (!dumb_mode) { setenv(CMPLOG_SHM_ENV_VAR, shm_str, 1); } ck_free(shm_str); @@ -186,13 +186,17 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { shm->map = shmat(shm->shm_id, NULL, 0); - if (shm->map == (void *)-1 || !shm->map) PFATAL("shmat() failed"); + if (shm->map == (void *)-1 || !shm->map) { PFATAL("shmat() failed"); } if (shm->cmplog_mode) { shm->cmp_map = shmat(shm->cmplog_shm_id, NULL, 0); - if (shm->cmp_map == (void *)-1 || !shm->cmp_map) PFATAL("shmat() failed"); + if (shm->cmp_map == (void *)-1 || !shm->cmp_map) { + + PFATAL("shmat() failed"); + + } } diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 59b4963d..63b54851 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -121,7 +121,7 @@ static void classify_counts(afl_forkserver_t *fsrv) { while (i--) { - if (*mem) *mem = 1; + if (*mem) { *mem = 1; } mem++; } @@ -143,7 +143,7 @@ static void classify_counts(afl_forkserver_t *fsrv) { static void at_exit_handler(void) { - if (stdin_file) unlink(stdin_file); + if (stdin_file) { unlink(stdin_file); } } @@ -161,25 +161,28 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { fd = open(outfile, O_WRONLY); - if (fd < 0) PFATAL("Unable to open '%s'", out_file); + if (fd < 0) { PFATAL("Unable to open '%s'", out_file); } } else if (!strcmp(outfile, "-")) { fd = dup(1); - if (fd < 0) PFATAL("Unable to open stdout"); + if (fd < 0) { PFATAL("Unable to open stdout"); } } else { unlink(outfile); /* Ignore errors */ fd = open(outfile, O_WRONLY | O_CREAT | O_EXCL, 0600); - if (fd < 0) PFATAL("Unable to create '%s'", outfile); + if (fd < 0) { PFATAL("Unable to create '%s'", outfile); } } if (binary_mode) { - for (i = 0; i < map_size; i++) - if (fsrv->trace_bits[i]) ret++; + for (i = 0; i < map_size; i++) { + + if (fsrv->trace_bits[i]) { ret++; } + + } ck_write(fd, fsrv->trace_bits, map_size, outfile); close(fd); @@ -188,27 +191,29 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { FILE *f = fdopen(fd, "w"); - if (!f) PFATAL("fdopen() failed"); + if (!f) { PFATAL("fdopen() failed"); } for (i = 0; i < map_size; i++) { - if (!fsrv->trace_bits[i]) continue; + if (!fsrv->trace_bits[i]) { continue; } ret++; total += fsrv->trace_bits[i]; - if (highest < fsrv->trace_bits[i]) highest = fsrv->trace_bits[i]; + if (highest < fsrv->trace_bits[i]) { highest = fsrv->trace_bits[i]; } if (cmin_mode) { - if (fsrv->last_run_timed_out) break; - if (!caa && child_crashed != cco) break; + if (fsrv->last_run_timed_out) { break; } + if (!caa && child_crashed != cco) { break; } fprintf(f, "%u%u\n", fsrv->trace_bits[i], i); - } else + } else { fprintf(f, "%06u:%u\n", i, fsrv->trace_bits[i]); + } + } fclose(f); @@ -251,11 +256,14 @@ static u32 read_file(u8 *in_file) { struct stat st; s32 fd = open(in_file, O_RDONLY); - if (fd < 0) WARNF("Unable to open '%s'", in_file); + if (fd < 0) { WARNF("Unable to open '%s'", in_file); } + + if (fstat(fd, &st) || !st.st_size) { - if (fstat(fd, &st) || !st.st_size) WARNF("Zero-sized input file '%s'.", in_file); + } + in_len = st.st_size; in_data = ck_alloc_nozero(in_len); @@ -276,13 +284,13 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { static struct itimerval it; int status = 0; - if (!quiet_mode) SAYF("-- Program output begins --\n" cRST); + if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); } MEM_BARRIER(); fsrv->child_pid = fork(); - if (fsrv->child_pid < 0) PFATAL("fork() failed"); + if (fsrv->child_pid < 0) { PFATAL("fork() failed"); } if (!fsrv->child_pid) { @@ -319,14 +327,19 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { } - if (!keep_cores) + if (!keep_cores) { + r.rlim_max = r.rlim_cur = 0; - else + + } else { + r.rlim_max = r.rlim_cur = RLIM_INFINITY; + } + setrlimit(RLIMIT_CORE, &r); /* Ignore errors */ - if (!getenv("LD_BIND_LAZY")) setenv("LD_BIND_NOW", "1", 0); + if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 0); } setsid(); @@ -349,7 +362,7 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { setitimer(ITIMER_REAL, &it, NULL); - if (waitpid(fsrv->child_pid, &status, 0) <= 0) FATAL("waitpid() failed"); + if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); } fsrv->child_pid = 0; it.it_value.tv_sec = 0; @@ -360,26 +373,39 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) { /* Clean up bitmap, analyze exit condition, etc. */ - if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) + if (*(u32 *)fsrv->trace_bits == EXEC_FAIL_SIG) { + FATAL("Unable to execute '%s'", argv[0]); + } + classify_counts(fsrv); - if (!quiet_mode) SAYF(cRST "-- Program output ends --\n"); + if (!quiet_mode) { SAYF(cRST "-- Program output ends --\n"); } + + if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) { - if (!fsrv->last_run_timed_out && !stop_soon && WIFSIGNALED(status)) child_crashed = 1; + } + if (!quiet_mode) { - if (fsrv->last_run_timed_out) + if (fsrv->last_run_timed_out) { + SAYF(cLRD "\n+++ Program timed off +++\n" cRST); - else if (stop_soon) + + } else if (stop_soon) { + SAYF(cLRD "\n+++ Program aborted by user +++\n" cRST); - else if (child_crashed) + + } else if (child_crashed) { + SAYF(cLRD "\n+++ Program killed by signal %u +++\n" cRST, WTERMSIG(status)); + } + } } @@ -421,20 +447,28 @@ static void set_up_environment(afl_forkserver_t *fsrv) { s32 i, afl_preload_size = strlen(afl_preload); for (i = 0; i < afl_preload_size; ++i) { - if (afl_preload[i] == ',') + if (afl_preload[i] == ',') { + PFATAL( "Comma (',') is not allowed in AFL_PRELOAD when -Q is " "specified!"); + } + } - if (qemu_preload) + if (qemu_preload) { + buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", qemu_preload, afl_preload, afl_preload); - else + + } else { + buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", afl_preload, afl_preload); + } + setenv("QEMU_SET_ENV", buf, 1); ck_free(buf); @@ -549,20 +583,20 @@ int main(int argc, char **argv_orig, char **envp) { doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH; - if (getenv("AFL_QUIET") != NULL) be_quiet = 1; + if (getenv("AFL_QUIET") != NULL) { be_quiet = 1; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) + while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqZQUWbcrh")) > 0) { switch (opt) { case 'i': - if (in_dir) FATAL("Multiple -i options not supported"); + if (in_dir) { FATAL("Multiple -i options not supported"); } in_dir = optarg; break; case 'o': - if (out_file) FATAL("Multiple -o options not supported"); + if (out_file) { FATAL("Multiple -o options not supported"); } out_file = optarg; break; @@ -570,10 +604,10 @@ int main(int argc, char **argv_orig, char **envp) { u8 suffix = 'M'; - if (mem_limit_given) FATAL("Multiple -m options not supported"); + if (mem_limit_given) { FATAL("Multiple -m options not supported"); } mem_limit_given = 1; - if (!optarg) FATAL("Wrong usage of -m"); + if (!optarg) { FATAL("Wrong usage of -m"); } if (!strcmp(optarg, "none")) { @@ -583,25 +617,39 @@ int main(int argc, char **argv_orig, char **envp) { } if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || - optarg[0] == '-') + optarg[0] == '-') { + FATAL("Bad syntax used for -m"); - switch (suffix) { + } - case 'T': fsrv->mem_limit *= 1024 * 1024; break; - case 'G': fsrv->mem_limit *= 1024; break; - case 'k': fsrv->mem_limit /= 1024; break; - case 'M': break; + switch (suffix) { - default: FATAL("Unsupported suffix or bad syntax for -m"); + case 'T': + fsrv->mem_limit *= 1024 * 1024; + break; + case 'G': + fsrv->mem_limit *= 1024; + break; + case 'k': + fsrv->mem_limit /= 1024; + break; + case 'M': + break; + + default: + FATAL("Unsupported suffix or bad syntax for -m"); } - if (fsrv->mem_limit < 5) FATAL("Dangerously low value of -m"); + if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); } + + if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) { - if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) FATAL("Value of -m out of range on 32-bit systems"); + } + } break; @@ -615,32 +663,35 @@ int main(int argc, char **argv_orig, char **envp) { case 't': - if (timeout_given) FATAL("Multiple -t options not supported"); + if (timeout_given) { FATAL("Multiple -t options not supported"); } timeout_given = 1; - if (!optarg) FATAL("Wrong usage of -t"); + if (!optarg) { FATAL("Wrong usage of -t"); } if (strcmp(optarg, "none")) { fsrv->exec_tmout = atoi(optarg); - if (fsrv->exec_tmout < 20 || optarg[0] == '-') + if (fsrv->exec_tmout < 20 || optarg[0] == '-') { + FATAL("Dangerously low value of -t"); + } + } break; case 'e': - if (edges_only) FATAL("Multiple -e options not supported"); - if (raw_instr_output) FATAL("-e and -r are mutually exclusive"); + if (edges_only) { FATAL("Multiple -e options not supported"); } + if (raw_instr_output) { FATAL("-e and -r are mutually exclusive"); } edges_only = 1; break; case 'q': - if (quiet_mode) FATAL("Multiple -q options not supported"); + if (quiet_mode) { FATAL("Multiple -q options not supported"); } quiet_mode = 1; break; @@ -660,27 +711,27 @@ int main(int argc, char **argv_orig, char **envp) { case 'Q': - if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported"); - if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU; + if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } + if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; } fsrv->qemu_mode = 1; break; case 'U': - if (unicorn_mode) FATAL("Multiple -U options not supported"); - if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_UNICORN; + if (unicorn_mode) { FATAL("Multiple -U options not supported"); } + if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; } unicorn_mode = 1; break; case 'W': /* Wine+QEMU mode */ - if (use_wine) FATAL("Multiple -W options not supported"); + if (use_wine) { FATAL("Multiple -W options not supported"); } fsrv->qemu_mode = 1; use_wine = 1; - if (!mem_limit_given) fsrv->mem_limit = 0; + if (!mem_limit_given) { fsrv->mem_limit = 0; } break; @@ -694,14 +745,14 @@ int main(int argc, char **argv_orig, char **envp) { case 'c': - if (keep_cores) FATAL("Multiple -c options not supported"); + if (keep_cores) { FATAL("Multiple -c options not supported"); } keep_cores = 1; break; case 'r': - if (raw_instr_output) FATAL("Multiple -r options not supported"); - if (edges_only) FATAL("-e and -r are mutually exclusive"); + if (raw_instr_output) { FATAL("Multiple -r options not supported"); } + if (edges_only) { FATAL("-e and -r are mutually exclusive"); } raw_instr_output = 1; break; @@ -710,11 +761,14 @@ int main(int argc, char **argv_orig, char **envp) { return -1; break; - default: usage(argv[0]); + default: + usage(argv[0]); } - if (optind == argc || !out_file) usage(argv[0]); + } + + if (optind == argc || !out_file) { usage(argv[0]); } check_environment_vars(envp); @@ -735,7 +789,7 @@ int main(int argc, char **argv_orig, char **envp) { if (in_dir) { - if (at_file) PFATAL("Options -A and -i are mutually exclusive"); + if (at_file) { PFATAL("Options -A and -i are mutually exclusive"); } detect_file_args(argv + optind, "", &fsrv->use_stdin); } else { @@ -744,22 +798,32 @@ int main(int argc, char **argv_orig, char **envp) { } - for (i = optind; i < argc; i++) - if (strcmp(argv[i], "@@") == 0) arg_offset = i; + for (i = optind; i < argc; i++) { + + if (strcmp(argv[i], "@@") == 0) { arg_offset = i; } + + } if (fsrv->qemu_mode) { - if (use_wine) + if (use_wine) { + use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); - else + + } else { + use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); - } else + } + + } else { use_argv = argv + optind; + } + if (in_dir) { DIR * dir_in, *dir_out; @@ -771,20 +835,30 @@ int main(int argc, char **argv_orig, char **envp) { #endif fsrv->dev_null_fd = open("/dev/null", O_RDWR); - if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null"); + if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } - if (!(dir_in = opendir(in_dir))) PFATAL("cannot open directory %s", in_dir); + if (!(dir_in = opendir(in_dir))) { + + PFATAL("cannot open directory %s", in_dir); + + } + + if (!(dir_out = opendir(out_file))) { + + if (mkdir(out_file, 0700)) { - if (!(dir_out = opendir(out_file))) - if (mkdir(out_file, 0700)) PFATAL("cannot create output directory %s", out_file); + } + + } + u8 *use_dir = "."; if (access(use_dir, R_OK | W_OK | X_OK)) { use_dir = get_afl_env("TMPDIR"); - if (!use_dir) use_dir = "/tmp"; + if (!use_dir) { use_dir = "/tmp"; } } @@ -792,7 +866,7 @@ int main(int argc, char **argv_orig, char **envp) { unlink(stdin_file); atexit(at_exit_handler); fsrv->out_fd = open(stdin_file, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file); + if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } if (arg_offset && argv[arg_offset] != stdin_file) { @@ -805,8 +879,12 @@ int main(int argc, char **argv_orig, char **envp) { int i = optind; SAYF(cMGN "[D]" cRST " %s:", fsrv->target_path); - while (argv[i] != NULL) + while (argv[i] != NULL) { + SAYF(" \"%s\"", argv[i++]); + + } + SAYF("\n"); SAYF(cMGN "[D]" cRST " %d - %d = %d, %s\n", arg_offset, optind, arg_offset - optind, infile); @@ -818,11 +896,19 @@ int main(int argc, char **argv_orig, char **envp) { while (done == 0 && (dir_ent = readdir(dir_in))) { - if (dir_ent->d_name[0] == '.') + if (dir_ent->d_name[0] == '.') { + continue; // skip anything that starts with '.' + } + #if defined(DT_REG) /* Posix and Solaris do not know d_type and DT_REG */ - if (dir_ent->d_type != DT_REG) continue; // only regular files + if (dir_ent->d_type != DT_REG) { + + continue; // only regular files + + } + #endif snprintf(infile, sizeof(infile), "%s/%s", in_dir, dir_ent->d_name); @@ -843,10 +929,10 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!quiet_mode) OKF("Processed %llu input files.", fsrv->total_execs); + if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); } closedir(dir_in); - if (dir_out) closedir(dir_out); + if (dir_out) { closedir(dir_out); } } else { @@ -857,7 +943,7 @@ int main(int argc, char **argv_orig, char **envp) { if (!quiet_mode) { - if (!tcnt) FATAL("No instrumentation detected" cRST); + if (!tcnt) { FATAL("No instrumentation detected" cRST); } OKF("Captured %u tuples (highest value %u, total values %u) in '%s'." cRST, tcnt, highest, total, out_file); @@ -875,13 +961,13 @@ int main(int argc, char **argv_orig, char **envp) { u32 ret = child_crashed * 2 + fsrv->last_run_timed_out; - if (fsrv->target_path) ck_free(fsrv->target_path); + if (fsrv->target_path) { ck_free(fsrv->target_path); } afl_fsrv_deinit(fsrv); - if (stdin_file) ck_free(stdin_file); + if (stdin_file) { ck_free(stdin_file); } argv_cpy_free(argv); - if (fsrv->qemu_mode) free(use_argv[2]); + if (fsrv->qemu_mode) { free(use_argv[2]); } exit(ret); diff --git a/src/afl-tmin.c b/src/afl-tmin.c index dab2a417..d6fbd493 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -108,7 +108,7 @@ static void apply_mask(u32 *mem, u32 *mask) { u32 i = (map_size >> 2); - if (!mask) return; + if (!mask) { return; } while (i--) { @@ -129,7 +129,7 @@ static void classify_counts(afl_forkserver_t *fsrv) { while (i--) { - if (*mem) *mem = 1; + if (*mem) { *mem = 1; } mem++; } @@ -154,8 +154,11 @@ static inline u8 anything_set(afl_forkserver_t *fsrv) { u32 *ptr = (u32 *)fsrv->trace_bits; u32 i = (map_size >> 2); - while (i--) - if (*(ptr++)) return 1; + while (i--) { + + if (*(ptr++)) { return 1; } + + } return 0; @@ -174,13 +177,16 @@ static void read_initial_file(void) { struct stat st; s32 fd = open(in_file, O_RDONLY); - if (fd < 0) PFATAL("Unable to open '%s'", in_file); + if (fd < 0) { PFATAL("Unable to open '%s'", in_file); } + + if (fstat(fd, &st) || !st.st_size) { FATAL("Zero-sized input file."); } - if (fstat(fd, &st) || !st.st_size) FATAL("Zero-sized input file."); + if (st.st_size >= TMIN_MAX_FILE) { - if (st.st_size >= TMIN_MAX_FILE) FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024); + } + in_len = st.st_size; in_data = ck_alloc_nozero(in_len); @@ -202,7 +208,7 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) { ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600); - if (ret < 0) PFATAL("Unable to create '%s'", path); + if (ret < 0) { PFATAL("Unable to create '%s'", path); } ck_write(ret, mem, len, path); @@ -223,7 +229,7 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, fsrv_run_result_t ret = afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon); - if (ret == FSRV_RUN_ERROR) FATAL("Couldn't run child"); + if (ret == FSRV_RUN_ERROR) { FATAL("Couldn't run child"); } if (stop_soon) { @@ -239,9 +245,14 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, switch (ret) { - case FSRV_RUN_TMOUT: return 1; - case FSRV_RUN_CRASH: missed_crashes++; return 0; - default: missed_hangs++; return 0; + case FSRV_RUN_TMOUT: + return 1; + case FSRV_RUN_CRASH: + missed_crashes++; + return 0; + default: + missed_hangs++; + return 0; } @@ -261,11 +272,11 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, if (ret == FSRV_RUN_CRASH) { - if (first_run) crash_mode = 1; + if (first_run) { crash_mode = 1; } if (crash_mode) { - if (!exact_mode) return 1; + if (!exact_mode) { return 1; } } else { @@ -287,13 +298,13 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len, } - if (ret == FSRV_RUN_NOINST) FATAL("Binary not instrumented?"); + if (ret == FSRV_RUN_NOINST) { FATAL("Binary not instrumented?"); } u32 cksum = hash32(fsrv->trace_bits, fsrv->map_size, HASH_CONST); - if (first_run) orig_cksum = cksum; + if (first_run) { orig_cksum = cksum; } - if (orig_cksum == cksum) return 1; + if (orig_cksum == cksum) { return 1; } missed_paths++; return 0; @@ -320,7 +331,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) { set_len = next_pow2(in_len / TMIN_SET_STEPS); set_pos = 0; - if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE; + if (set_len < TMIN_SET_MIN_SIZE) { set_len = TMIN_SET_MIN_SIZE; } ACTF(cBRI "Stage #0: " cRST "One-time block normalization..."); @@ -328,8 +339,11 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) { u32 use_len = MIN(set_len, in_len - set_pos); - for (i = 0; i < use_len; i++) - if (in_data[set_pos + i] != '0') break; + for (i = 0; i < use_len; i++) { + + if (in_data[set_pos + i] != '0') { break; } + + } if (i != use_len) { @@ -374,7 +388,7 @@ next_pass: next_del_blksize: - if (!del_len) del_len = 1; + if (!del_len) { del_len = 1; } del_pos = 0; prev_del = 1; @@ -387,7 +401,7 @@ next_del_blksize: s32 tail_len; tail_len = in_len - del_pos - del_len; - if (tail_len < 0) tail_len = 0; + if (tail_len < 0) { tail_len = 0; } /* If we have processed at least one full block (initially, prev_del == 1), and we did so without deleting the previous one, and we aren't at the @@ -420,10 +434,12 @@ next_del_blksize: changed_any = 1; - } else + } else { del_pos += del_len; + } + } if (del_len > 1 && in_len >= 1) { @@ -435,11 +451,14 @@ next_del_blksize: OKF("Block removal complete, %u bytes deleted.", stage_o_len - in_len); - if (!in_len && changed_any) + if (!in_len && changed_any) { + WARNF(cLRD "Down to zero bytes - check the command line and mem limit!" cRST); - if (cur_pass > 1 && !changed_any) goto finalize_all; + } + + if (cur_pass > 1 && !changed_any) { goto finalize_all; } /************************* * ALPHABET MINIMIZATION * @@ -453,7 +472,7 @@ next_del_blksize: for (i = 0; i < in_len; i++) { - if (!alpha_map[in_data[i]]) alpha_size++; + if (!alpha_map[in_data[i]]) { alpha_size++; } alpha_map[in_data[i]]++; } @@ -466,12 +485,15 @@ next_del_blksize: u32 r; u8 res; - if (i == '0' || !alpha_map[i]) continue; + if (i == '0' || !alpha_map[i]) { continue; } memcpy(tmp_buf, in_data, in_len); - for (r = 0; r < in_len; r++) - if (tmp_buf[r] == i) tmp_buf[r] = '0'; + for (r = 0; r < in_len; r++) { + + if (tmp_buf[r] == i) { tmp_buf[r] = '0'; } + + } res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); @@ -506,7 +528,7 @@ next_del_blksize: u8 res, orig = tmp_buf[i]; - if (orig == '0') continue; + if (orig == '0') { continue; } tmp_buf[i] = '0'; res = tmin_run_target(fsrv, argv, tmp_buf, in_len, 0); @@ -517,10 +539,12 @@ next_del_blksize: alpha_del2++; changed_any = 1; - } else + } else { tmp_buf[i] = orig; + } + } alpha_d_total += alpha_del2; @@ -528,11 +552,11 @@ next_del_blksize: OKF("Character minimization done, %u byte%s replaced.", alpha_del2, alpha_del2 == 1 ? "" : "s"); - if (changed_any) goto next_pass; + if (changed_any) { goto next_pass; } finalize_all: - if (tmp_buf) ck_free(tmp_buf); + if (tmp_buf) { ck_free(tmp_buf); } if (hang_mode) { @@ -558,9 +582,12 @@ finalize_all: missed_hangs ? cLRD : "", missed_hangs); if (fsrv->total_execs > 50 && missed_hangs * 10 > fsrv->total_execs && - !hang_mode) + !hang_mode) { + WARNF(cLRD "Frequent timeouts - results may be skewed." cRST); + } + } /* Handle Ctrl-C and the like. */ @@ -579,7 +606,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { u8 *x; fsrv->dev_null_fd = open("/dev/null", O_RDWR); - if (fsrv->dev_null_fd < 0) PFATAL("Unable to open /dev/null"); + if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); } if (!out_file) { @@ -588,7 +615,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { if (access(use_dir, R_OK | W_OK | X_OK)) { use_dir = get_afl_env("TMPDIR"); - if (!use_dir) use_dir = "/tmp"; + if (!use_dir) { use_dir = "/tmp"; } } @@ -600,7 +627,7 @@ static void set_up_environment(afl_forkserver_t *fsrv) { fsrv->out_fd = open(out_file, O_RDWR | O_CREAT | O_EXCL, 0600); - if (fsrv->out_fd < 0) PFATAL("Unable to create '%s'", out_file); + if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); } /* Set sane defaults... */ @@ -608,25 +635,37 @@ static void set_up_environment(afl_forkserver_t *fsrv) { if (x) { - if (!strstr(x, "abort_on_error=1")) + if (!strstr(x, "abort_on_error=1")) { + FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!"); - if (!strstr(x, "symbolize=0")) + } + + if (!strstr(x, "symbolize=0")) { + FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!"); + } + } x = get_afl_env("MSAN_OPTIONS"); if (x) { - if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) + if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) { + FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY( MSAN_ERROR) " - please fix!"); - if (!strstr(x, "symbolize=0")) + } + + if (!strstr(x, "symbolize=0")) { + FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!"); + } + } setenv("ASAN_OPTIONS", @@ -653,20 +692,28 @@ static void set_up_environment(afl_forkserver_t *fsrv) { s32 i, afl_preload_size = strlen(afl_preload); for (i = 0; i < afl_preload_size; ++i) { - if (afl_preload[i] == ',') + if (afl_preload[i] == ',') { + PFATAL( "Comma (',') is not allowed in AFL_PRELOAD when -Q is " "specified!"); + } + } - if (qemu_preload) + if (qemu_preload) { + buf = alloc_printf("%s,LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", qemu_preload, afl_preload, afl_preload); - else + + } else { + buf = alloc_printf("LD_PRELOAD=%s,DYLD_INSERT_LIBRARIES=%s", afl_preload, afl_preload); + } + setenv("QEMU_SET_ENV", buf, 1); ck_free(buf); @@ -772,40 +819,44 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) + while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeQUWHh")) > 0) { switch (opt) { case 'i': - if (in_file) FATAL("Multiple -i options not supported"); + if (in_file) { FATAL("Multiple -i options not supported"); } in_file = optarg; break; case 'o': - if (output_file) FATAL("Multiple -o options not supported"); + if (output_file) { FATAL("Multiple -o options not supported"); } output_file = optarg; break; case 'f': - if (out_file) FATAL("Multiple -f options not supported"); + if (out_file) { FATAL("Multiple -f options not supported"); } fsrv->use_stdin = 0; out_file = optarg; break; case 'e': - if (edges_only) FATAL("Multiple -e options not supported"); - if (hang_mode) + if (edges_only) { FATAL("Multiple -e options not supported"); } + if (hang_mode) { + FATAL("Edges only and hang mode are mutually exclusive."); + + } + edges_only = 1; break; case 'x': - if (exit_crash) FATAL("Multiple -x options not supported"); + if (exit_crash) { FATAL("Multiple -x options not supported"); } exit_crash = 1; break; @@ -813,10 +864,10 @@ int main(int argc, char **argv_orig, char **envp) { u8 suffix = 'M'; - if (mem_limit_given) FATAL("Multiple -m options not supported"); + if (mem_limit_given) { FATAL("Multiple -m options not supported"); } mem_limit_given = 1; - if (!optarg) FATAL("Wrong usage of -m"); + if (!optarg) { FATAL("Wrong usage of -m"); } if (!strcmp(optarg, "none")) { @@ -826,66 +877,83 @@ int main(int argc, char **argv_orig, char **envp) { } if (sscanf(optarg, "%llu%c", &fsrv->mem_limit, &suffix) < 1 || - optarg[0] == '-') + optarg[0] == '-') { + FATAL("Bad syntax used for -m"); - switch (suffix) { + } - case 'T': fsrv->mem_limit *= 1024 * 1024; break; - case 'G': fsrv->mem_limit *= 1024; break; - case 'k': fsrv->mem_limit /= 1024; break; - case 'M': break; + switch (suffix) { - default: FATAL("Unsupported suffix or bad syntax for -m"); + case 'T': + fsrv->mem_limit *= 1024 * 1024; + break; + case 'G': + fsrv->mem_limit *= 1024; + break; + case 'k': + fsrv->mem_limit /= 1024; + break; + case 'M': + break; + + default: + FATAL("Unsupported suffix or bad syntax for -m"); } - if (fsrv->mem_limit < 5) FATAL("Dangerously low value of -m"); + if (fsrv->mem_limit < 5) { FATAL("Dangerously low value of -m"); } + + if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) { - if (sizeof(rlim_t) == 4 && fsrv->mem_limit > 2000) FATAL("Value of -m out of range on 32-bit systems"); + } + } break; case 't': - if (timeout_given) FATAL("Multiple -t options not supported"); + if (timeout_given) { FATAL("Multiple -t options not supported"); } timeout_given = 1; - if (!optarg) FATAL("Wrong usage of -t"); + if (!optarg) { FATAL("Wrong usage of -t"); } fsrv->exec_tmout = atoi(optarg); - if (fsrv->exec_tmout < 10 || optarg[0] == '-') + if (fsrv->exec_tmout < 10 || optarg[0] == '-') { + FATAL("Dangerously low value of -t"); + } + break; case 'Q': - if (fsrv->qemu_mode) FATAL("Multiple -Q options not supported"); - if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_QEMU; + if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } + if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; } fsrv->qemu_mode = 1; break; case 'U': - if (unicorn_mode) FATAL("Multiple -Q options not supported"); - if (!mem_limit_given) fsrv->mem_limit = MEM_LIMIT_UNICORN; + if (unicorn_mode) { FATAL("Multiple -Q options not supported"); } + if (!mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; } unicorn_mode = 1; break; case 'W': /* Wine+QEMU mode */ - if (use_wine) FATAL("Multiple -W options not supported"); + if (use_wine) { FATAL("Multiple -W options not supported"); } fsrv->qemu_mode = 1; use_wine = 1; - if (!mem_limit_given) fsrv->mem_limit = 0; + if (!mem_limit_given) { fsrv->mem_limit = 0; } break; @@ -893,9 +961,13 @@ int main(int argc, char **argv_orig, char **envp) { /* Minimizes a testcase to the minimum that still times out */ - if (hang_mode) FATAL("Multipe -H options not supported"); - if (edges_only) + if (hang_mode) { FATAL("Multipe -H options not supported"); } + if (edges_only) { + FATAL("Edges only and hang mode are mutually exclusive."); + + } + hang_mode = 1; break; @@ -914,7 +986,7 @@ int main(int argc, char **argv_orig, char **envp) { The option may be extended and made more official if it proves to be useful. */ - if (mask_bitmap) FATAL("Multiple -B options not supported"); + if (mask_bitmap) { FATAL("Multiple -B options not supported"); } mask_bitmap = ck_alloc(map_size); read_bitmap(optarg, mask_bitmap, map_size); break; @@ -924,11 +996,14 @@ int main(int argc, char **argv_orig, char **envp) { return -1; break; - default: usage(argv[0]); + default: + usage(argv[0]); } - if (optind == argc || !in_file || !output_file) usage(argv[0]); + } + + if (optind == argc || !in_file || !output_file) { usage(argv[0]); } check_environment_vars(envp); @@ -945,17 +1020,24 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->qemu_mode) { - if (use_wine) + if (use_wine) { + use_argv = get_wine_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); - else + + } else { + use_argv = get_qemu_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); - } else + } + + } else { use_argv = argv + optind; + } + exact_mode = !!get_afl_env("AFL_TMIN_EXACT"); if (hang_mode && exact_mode) { @@ -977,17 +1059,23 @@ int main(int argc, char **argv_orig, char **envp) { tmin_run_target(fsrv, use_argv, in_data, in_len, 1); - if (hang_mode && !fsrv->last_run_timed_out) + if (hang_mode && !fsrv->last_run_timed_out) { + FATAL( "Target binary did not time out but hang minimization mode " "(-H) was set (-t %u).", fsrv->exec_tmout); - if (fsrv->last_run_timed_out && !hang_mode) + } + + if (fsrv->last_run_timed_out && !hang_mode) { + FATAL( "Target binary times out (adjusting -t may help). Use -H to minimize a " "hang."); + } + if (hang_mode) { OKF("Program hangs as expected, minimizing in " cCYA "hang" cRST " mode."); @@ -997,7 +1085,7 @@ int main(int argc, char **argv_orig, char **envp) { OKF("Program terminates normally, minimizing in " cCYA "instrumented" cRST " mode."); - if (!anything_set(fsrv)) FATAL("No instrumentation detected."); + if (!anything_set(fsrv)) { FATAL("No instrumentation detected."); } } else { @@ -1012,7 +1100,7 @@ int main(int argc, char **argv_orig, char **envp) { ACTF("Writing output to '%s'...", output_file); unlink(out_file); - if (out_file) ck_free(out_file); + if (out_file) { ck_free(out_file); } out_file = NULL; close(write_to_file(output_file, in_data, in_len)); @@ -1021,9 +1109,9 @@ int main(int argc, char **argv_orig, char **envp) { afl_shm_deinit(&shm); afl_fsrv_deinit(fsrv); - if (fsrv->target_path) ck_free(fsrv->target_path); - if (mask_bitmap) ck_free(mask_bitmap); - if (in_data) ck_free(in_data); + if (fsrv->target_path) { ck_free(fsrv->target_path); } + if (mask_bitmap) { ck_free(mask_bitmap); } + if (in_data) { ck_free(in_data); } argv_cpy_free(argv); -- 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(-) 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 b6a15d9719fd93ebbc885b9c53ae21f7bd325ee0 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 20 Apr 2020 11:32:44 +0200 Subject: switched to clang-format-10 --- .custom-format.py | 6 +++--- include/afl-fuzz.h | 5 +++-- include/android-ashmem.h | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/.custom-format.py b/.custom-format.py index e3779b68..164815b1 100755 --- a/.custom-format.py +++ b/.custom-format.py @@ -29,14 +29,14 @@ CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN") if CLANG_FORMAT_BIN is None: o = 0 try: - p = subprocess.Popen(["clang-format-8", "--version"], stdout=subprocess.PIPE) + p = subprocess.Popen(["clang-format-10", "--version"], stdout=subprocess.PIPE) o, _ = p.communicate() o = str(o, "utf-8") o = o[len("clang-format version "):].strip() o = o[:o.find(".")] o = int(o) except: - print ("clang-format-8 is needed. Aborted.") + print ("clang-format-10 is needed. Aborted.") exit(1) #if o < 7: # if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0: @@ -51,7 +51,7 @@ if CLANG_FORMAT_BIN is None: # print ("clang-format 7 or above is needed. Aborted.") # exit(1) else: - CLANG_FORMAT_BIN = 'clang-format-8' + CLANG_FORMAT_BIN = 'clang-format-10' COLUMN_LIMIT = 80 for line in fmt.split("\n"): diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 6c349ea7..428bfa8e 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -608,8 +608,9 @@ typedef struct afl_state { u8 * ex_buf; size_t ex_size; - /* this is a fixed buffer of size map_size that can be used by any function if they do not call another function */ - u8 * map_tmp_buf; + /* this is a fixed buffer of size map_size that can be used by any function if + * they do not call another function */ + u8 *map_tmp_buf; } afl_state_t; diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 5d99dd48..0dea0583 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -105,7 +105,7 @@ static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) { } -#endif /* __ANDROID__ */ +#endif /* __ANDROID__ */ #endif -- cgit 1.4.1 From 4f997665f176d5870ab53c028e5899ae1c520d54 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 20 Apr 2020 16:10:06 +0200 Subject: typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 49bc35c9..9ec7b6e7 100644 --- a/README.md +++ b/README.md @@ -161,7 +161,7 @@ These build targets exist: * 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 compiled, not downloads (unless not on a checkout) -* deelclean: cleans everything including downloads +* deepclean: 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) -- cgit 1.4.1 From 4ccd8c14003ba1645e05482ead7b1a7b1b998289 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 21:03:06 +0200 Subject: reset git on deepclean --- GNUmakefile | 1 + unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 21b5d2a1..78763ecf 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -435,6 +435,7 @@ endif deepclean: clean rm -rf qemu_mode/qemu-3.1.1.tar.xz rm -rf unicorn_mode/unicornafl + git reset --hard || true distrib: all radamsa -$(MAKE) -C llvm_mode diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 89fd1f66..214c526e 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 89fd1f66912c8e0918ba0658b16bda204607e44a +Subproject commit 214c526e4ca3adf867057858c909500e0678a789 -- cgit 1.4.1 From 67b39050df4776d6fedbd3c17b1d98718ae6b8f9 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 21:05:02 +0200 Subject: android ashmem fix --- include/android-ashmem.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/android-ashmem.h b/include/android-ashmem.h index 0dea0583..b46e244b 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -109,5 +109,3 @@ static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) { #endif -#endif - -- cgit 1.4.1 From 4be0ae20085a67fe708b102decee94c3776757b7 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 21:06:16 +0200 Subject: double include removed --- include/forkserver.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/forkserver.h b/include/forkserver.h index f07c5104..3c473572 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -30,9 +30,9 @@ #include #include -#include "types.h" #include "types.h" + typedef struct afl_forkserver { /* a program that includes afl-forkserver needs to define these */ -- 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(-) 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 c8f2ba5b49465fb644001e81bd3b0d322ca61db7 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 21:40:22 +0200 Subject: updated unicorn --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 2367cc00..5b152135 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -afl++2.64c +4325c8f diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 214c526e..4325c8fd 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 214c526e4ca3adf867057858c909500e0678a789 +Subproject commit 4325c8fd9c8b92986b1b0f75ac519a12726b6bd3 -- cgit 1.4.1 From ce159377170aa95cdbcce8e60503abb00fa8d068 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 21:54:55 +0200 Subject: code format --- src/afl-fuzz-mutators.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c index 1a279b2d..beb89092 100644 --- a/src/afl-fuzz-mutators.c +++ b/src/afl-fuzz-mutators.c @@ -70,8 +70,12 @@ void setup_custom_mutator(afl_state_t *afl) { } #else - if (afl->afl_env.afl_python_module) + if (afl->afl_env.afl_python_module) { + FATAL("Your AFL binary was built without Python support"); + + } + #endif } -- cgit 1.4.1 From 280374f7399e9e93f6e04a35fa1cb5e684f9a5d4 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 22:07:47 +0200 Subject: clang warning fixed --- src/afl-fuzz-redqueen.c | 3 +++ src/afl-showmap.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c index 3a3e6be1..7621d180 100644 --- a/src/afl-fuzz-redqueen.c +++ b/src/afl-fuzz-redqueen.c @@ -186,6 +186,9 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len, u32 exec_cksum) { } + ck_free(rng); + rng = NULL; + // save the input with the high entropy if (needs_write) { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 63b54851..af6c2b1a 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -157,6 +157,8 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) { u8 cco = !!getenv("AFL_CMIN_CRASHES_ONLY"), caa = !!getenv("AFL_CMIN_ALLOW_ANY"); + if (!outfile) { FATAL("Output filename not set (Bug in AFL++?)"); } + if (!strncmp(outfile, "/dev/", 5)) { fd = open(outfile, O_WRONLY); -- cgit 1.4.1 From e47c29e72847b780ffa54a3fdbadd0e01d8882d5 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 20 Apr 2020 22:14:41 +0200 Subject: dont error on git reset --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 78763ecf..2337b9e0 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -435,7 +435,7 @@ endif deepclean: clean rm -rf qemu_mode/qemu-3.1.1.tar.xz rm -rf unicorn_mode/unicornafl - git reset --hard || true + git reset --hard >/dev/null 2>&1 || true distrib: all radamsa -$(MAKE) -C llvm_mode -- cgit 1.4.1 From 3d52079a7caf018f6ecba9c6cf5f5ae944aa3138 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 22:18:26 +0200 Subject: removed done todo --- src/afl-sharedmem.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index 94fca09e..90754b75 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -66,7 +66,6 @@ static list_t shm_list = {.element_prealloc_count = 0}; void afl_shm_deinit(sharedmem_t *shm) { - // TODO: clang reports a potential UAF in this function/makro(?) list_remove(&shm_list, shm); #ifdef USEMMAP -- cgit 1.4.1 From 0ffef8c79d1e03ede8641eef21990f17335c08c1 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 23:11:11 +0200 Subject: script to update uc refs; new unicornafl version --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- unicorn_mode/update_uc_ref.sh | 25 +++++++++++++++++++++++++ 3 files changed, 27 insertions(+), 2 deletions(-) create mode 100755 unicorn_mode/update_uc_ref.sh diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 5b152135..cb597068 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -4325c8f +d51753b2 diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index 4325c8fd..d51753b2 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit 4325c8fd9c8b92986b1b0f75ac519a12726b6bd3 +Subproject commit d51753b29f2d2756ee74e83e5263ee34bb6decbf diff --git a/unicorn_mode/update_uc_ref.sh b/unicorn_mode/update_uc_ref.sh new file mode 100755 index 00000000..d198fa2a --- /dev/null +++ b/unicorn_mode/update_uc_ref.sh @@ -0,0 +1,25 @@ +#/bin/sh + +UC_VERSION_FILE='./UNICORNAFL_VERSION' + +NEW_VERSION="$1" +if [ -z "$NEW_VERSION" ]; then + echo "Internal script to update bound unicornafl version." + echo + echo "Usage: ./update_uc_ref.sh " + exit 1 +fi + +git submodule init && git submodule update || exit 1 +cd ./unicornafl +git fetch origin master 1>/dev/null || exit 1 +git stash 1>/dev/null 2>/dev/null +git stash drop 1>/dev/null 2>/dev/null +git checkout "$NEW_VERSION" || exit 1 + +cd .. + +rm "$UC_VERSION_FILE" +echo "$NEW_VERSION" > "$UC_VERSION_FILE" + +echo "Done. New unicornafl version is $NEW_VERSION." -- cgit 1.4.1 From e6fccdd9c1804e66db13e4b0d5faccc5a83d4116 Mon Sep 17 00:00:00 2001 From: David Mendenhall Date: Mon, 20 Apr 2020 14:24:47 -0700 Subject: Move comment about adding 8 bytes to buffer length to the line where we actually add 8 bytes Remove defunct TODO for posix_memalign as the function now exists Add wrapper for malloc_usable_size --- libdislocator/libdislocator.so.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c index 1fbfe9d6..72d280e6 100644 --- a/libdislocator/libdislocator.so.c +++ b/libdislocator/libdislocator.so.c @@ -183,6 +183,9 @@ static void *__dislocator_alloc(size_t len) { else rlen = len; + /* We will also store buffer length and a canary below the actual buffer, so + let's add 8 bytes for that. */ + tlen = (1 + PG_COUNT(rlen + 8)) * PAGE_SIZE; flags = MAP_PRIVATE | MAP_ANONYMOUS; fd = -1; @@ -200,9 +203,6 @@ static void *__dislocator_alloc(size_t len) { (void)sp; #endif - /* We will also store buffer length and a canary below the actual buffer, so - let's add 8 bytes for that. */ - ret = (u8 *)mmap(NULL, tlen, PROT_READ | PROT_WRITE, flags, fd, 0); #if defined(USEHUGEPAGE) /* We try one more time with regular call */ @@ -296,10 +296,6 @@ void *calloc(size_t elem_len, size_t elem_cnt) { } -/* TODO: add a wrapper for posix_memalign, otherwise apps who use it, - will fail when freeing the memory. -*/ - /* The wrapper for malloc(). Roughly the same, also clobbers the returned memory (unlike calloc(), malloc() is not guaranteed to return zeroed memory). */ @@ -468,6 +464,12 @@ void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) { } +size_t malloc_usable_size(void *ptr) { + + return PTR_L(ptr); + +} + __attribute__((constructor)) void __dislocator_init(void) { u8 *tmp = (u8 *)getenv("AFL_LD_LIMIT_MB"); @@ -492,4 +494,3 @@ __attribute__((constructor)) void __dislocator_init(void) { align_allocations = !!getenv("AFL_ALIGNED_ALLOC"); } - -- cgit 1.4.1 From 41b1787565b30fc4f7c46fb47af368e621c39e14 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 20 Apr 2020 23:27:09 +0200 Subject: add line --- include/android-ashmem.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/android-ashmem.h b/include/android-ashmem.h index b46e244b..77914c35 100644 --- a/include/android-ashmem.h +++ b/include/android-ashmem.h @@ -40,6 +40,7 @@ #define shmdt bionic_shmdt #define shmget bionic_shmget #endif + #include #undef shmat #undef shmctl -- cgit 1.4.1 From 8b319969f339aa2956a3cb733e3612df845b16e6 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Mon, 20 Apr 2020 23:49:12 +0200 Subject: unicornafl updated --- unicorn_mode/UNICORNAFL_VERSION | 2 +- unicorn_mode/unicornafl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index cb597068..0afcf291 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -d51753b2 +25ae270 diff --git a/unicorn_mode/unicornafl b/unicorn_mode/unicornafl index d51753b2..25ae270c 160000 --- a/unicorn_mode/unicornafl +++ b/unicorn_mode/unicornafl @@ -1 +1 @@ -Subproject commit d51753b29f2d2756ee74e83e5263ee34bb6decbf +Subproject commit 25ae270c1b949a5d1c2c5460b778f0a35bfe67d7 -- cgit 1.4.1 From 441b64b467e17d62056c3cf7eae9e9a381644db7 Mon Sep 17 00:00:00 2001 From: David Mendenhall Date: Mon, 20 Apr 2020 15:00:48 -0700 Subject: add NULL check to malloc_usable_size --- libdislocator/libdislocator.so.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c index 72d280e6..19e84d9f 100644 --- a/libdislocator/libdislocator.so.c +++ b/libdislocator/libdislocator.so.c @@ -466,7 +466,7 @@ void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) { size_t malloc_usable_size(void *ptr) { - return PTR_L(ptr); + return ptr ? PTR_L(ptr) : 0; } -- cgit 1.4.1 From f6c9acd5183b52e9dec0d810c51e3ca6649008fe Mon Sep 17 00:00:00 2001 From: David CARLIER Date: Tue, 21 Apr 2020 09:17:11 +0100 Subject: libdislocator android build fix. (#327) Fix function signature for bionic libc --- libdislocator/libdislocator.so.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c index 19e84d9f..8098de91 100644 --- a/libdislocator/libdislocator.so.c +++ b/libdislocator/libdislocator.so.c @@ -464,7 +464,11 @@ void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) { } +#if !defined(__ANDROID__) size_t malloc_usable_size(void *ptr) { +#else +size_t malloc_usable_size(const void *ptr) { +#endif return ptr ? PTR_L(ptr) : 0; -- cgit 1.4.1 From 059c9634674ab3912fede3f2e0f0627a8d7d54ab Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Tue, 21 Apr 2020 23:15:25 +0200 Subject: unicornafl build script: fix prerequisite search for setuptools --- unicorn_mode/build_unicorn_support.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index b2ac48f9..1e5b3ef4 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -107,7 +107,7 @@ for i in $PYTHONBIN automake autoconf git $MAKECMD $TARCMD; do done -if ! type $EASY_INSTALL > /dev/null; then +if ! command -v $EASY_INSTALL >/dev/null; then # work around for installs with executable easy_install EASY_INSTALL_FOUND=0 @@ -123,7 +123,7 @@ if ! type $EASY_INSTALL > /dev/null; then fi done - if [ '!' $EASY_INSTALL_FOUND ]; then + if [ "0" = $EASY_INSTALL_FOUND ]; then echo "[-] Error: Python setup-tools not found. Run 'sudo apt-get install python-setuptools'." PREREQ_NOTFOUND=1 -- cgit 1.4.1 From dcba2c36421315be1cca78c9ca78a2e15311cdef Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Wed, 22 Apr 2020 08:02:46 +0200 Subject: test.sh: custom mutator test; make it compilable with available instrumenting compiler --- test/test.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/test.sh b/test/test.sh index 5af35ec3..b8d4208f 100755 --- a/test/test.sh +++ b/test/test.sh @@ -951,7 +951,15 @@ test "1" = "`../afl-fuzz | grep -i 'without python' >/dev/null; echo $?`" && { test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && { unset AFL_CC # Compile the vulnerable program - ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1 + test -e ../afl-clang-fast && { + ../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1 + } || { + test -e ../afl-gcc-fast && { + ../afl-gcc-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1 + } || { + ../afl-gcc -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1 + } + } # Compile the custom mutator make -C ../examples/custom_mutators libexamplemutator.so > /dev/null 2>&1 test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && { -- cgit 1.4.1 From 6df21f3489ea482362983eda7e51c040d06e56f1 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Wed, 22 Apr 2020 08:40:04 +0200 Subject: GNUmakefile/unit tests: suppress compilation commandline output --- GNUmakefile | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 2337b9e0..8a030fd8 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -333,27 +333,27 @@ document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/ $(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS) test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES) - $(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES) - $(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o unit_maybe_alloc: test/unittests/unit_maybe_alloc.o - $(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka ./test/unittests/unit_maybe_alloc test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES) - $(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o unit_list: test/unittests/unit_list.o - $(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka ./test/unittests/unit_list test/unittests/preallocable.o : $(COMM_HDR) include/afl-prealloc.h test/unittests/preallocable.c $(AFL_FUZZ_FILES) - $(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/preallocable.o + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/preallocable.o unit_preallocable: test/unittests/unit_preallocable.o - $(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka + @$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka ./test/unittests/unit_preallocable unit_clean: -- cgit 1.4.1 From b8a25063f678c8afe3c1390d6a6ba130b0500e26 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Wed, 22 Apr 2020 13:51:36 +0200 Subject: fix sed errors in afl_shm_init when using mmap --- src/afl-sharedmem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index 01ba62aa..b5b443cf 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -129,11 +129,11 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { /* map the shared memory segment to the address space of the process */ shm->map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, - map_size->g_shm_fd, 0); - if (map_size->map == MAP_FAILED) { + shm->g_shm_fd, 0); + if (shm->map == MAP_FAILED) { - close(map_size->g_shm_fd); - map_size->g_shm_fd = -1; + close(shm->g_shm_fd); + shm->g_shm_fd = -1; PFATAL("mmap() failed"); } -- cgit 1.4.1 From 3502db1ac56028f2c35c34e21e70333239f398e1 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 23 Apr 2020 07:28:25 +0200 Subject: more sanitizer functions for blacklist --- llvm_mode/LLVMInsTrim.so.cc | 6 ++---- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 6 ++++-- llvm_mode/afl-llvm-lto-whitelist.so.cc | 3 ++- llvm_mode/afl-llvm-pass.so.cc | 6 ++---- llvm_mode/split-compares-pass.so.cc | 3 ++- llvm_mode/split-switches-pass.so.cc | 3 ++- 6 files changed, 14 insertions(+), 13 deletions(-) diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index 8b23942c..06fda187 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -112,10 +112,8 @@ struct InsTrim : public ModulePass { static const char *Blacklist[] = { - "asan.", - "llvm.", - "sancov.", - "__ubsan_handle_", + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." }; diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index ece3201f..eae60ccd 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -134,8 +134,8 @@ class AFLLTOPass : public ModulePass { static const char *Blacklist[] = { - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", - "__afl_", "_fini", "__libc_csu" + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." }; @@ -202,6 +202,8 @@ bool AFLLTOPass::runOnModule(Module &M) { for (auto &F : M) { + //fprintf(stderr, "DEBUG: Function %s\n", F.getName().str().c_str()); + if (F.size() < 2) continue; if (isBlacklisted(&F)) continue; diff --git a/llvm_mode/afl-llvm-lto-whitelist.so.cc b/llvm_mode/afl-llvm-lto-whitelist.so.cc index 48df76c3..045ff6c4 100644 --- a/llvm_mode/afl-llvm-lto-whitelist.so.cc +++ b/llvm_mode/afl-llvm-lto-whitelist.so.cc @@ -91,7 +91,8 @@ class AFLwhitelist : public ModulePass { static const SmallVector Blacklist = { - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign." + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." }; diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 71abcd05..0d15f5ec 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -97,10 +97,8 @@ class AFLCoverage : public ModulePass { static const char *Blacklist[] = { - "asan.", - "llvm.", - "sancov.", - "__ubsan_handle_", + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." }; diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index 7c657ebf..fab13b15 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -78,7 +78,8 @@ class SplitComparesTransform : public ModulePass { static const char *Blacklist[] = { - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign." + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." }; diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc index 980dcb12..18b791ac 100644 --- a/llvm_mode/split-switches-pass.so.cc +++ b/llvm_mode/split-switches-pass.so.cc @@ -83,7 +83,8 @@ class SplitSwitchesTransform : public ModulePass { static const char *Blacklist[] = { - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign." + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." }; -- cgit 1.4.1 From cce8c4dbaef89df66d97b1b7e2293ac971143bbd Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 23 Apr 2020 08:56:06 +0200 Subject: fixed map location support for LTO --- libdislocator/libdislocator.so.c | 5 +- llvm_mode/afl-llvm-lto-instrumentation.so.cc | 95 +++++++++++++++++++++++++--- llvm_mode/afl-llvm-rt.o.c | 45 +++++++++++-- src/afl-common.c | 9 +-- src/afl-sharedmem.c | 4 +- 5 files changed, 135 insertions(+), 23 deletions(-) diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c index 8098de91..6c8916d6 100644 --- a/libdislocator/libdislocator.so.c +++ b/libdislocator/libdislocator.so.c @@ -466,11 +466,13 @@ void *reallocarray(void *ptr, size_t elem_len, size_t elem_cnt) { #if !defined(__ANDROID__) size_t malloc_usable_size(void *ptr) { + #else size_t malloc_usable_size(const void *ptr) { + #endif - return ptr ? PTR_L(ptr) : 0; + return ptr ? PTR_L(ptr) : 0; } @@ -498,3 +500,4 @@ __attribute__((constructor)) void __dislocator_init(void) { align_allocations = !!getenv("AFL_ALIGNED_ALLOC"); } + diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index eae60ccd..dbd4a26e 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -154,6 +155,7 @@ class AFLLTOPass : public ModulePass { protected: int afl_global_id = 1, debug = 0, autodictionary = 0; uint32_t be_quiet = 0, inst_blocks = 0, inst_funcs = 0, total_instr = 0; + uint64_t map_addr = 0x10000; }; @@ -165,9 +167,11 @@ bool AFLLTOPass::runOnModule(Module &M) { std::vector dictionary; std::vector calls; DenseMap valueMap; + char * ptr; IntegerType *Int8Ty = IntegerType::getInt8Ty(C); IntegerType *Int32Ty = IntegerType::getInt32Ty(C); + IntegerType *Int64Ty = IntegerType::getInt64Ty(C); if (getenv("AFL_DEBUG")) debug = 1; @@ -186,12 +190,63 @@ bool AFLLTOPass::runOnModule(Module &M) { getenv("AFL_LLVM_LTO_AUTODICTIONARY")) autodictionary = 1; + if (getenv("AFL_LLVM_MAP_DYNAMIC")) map_addr = 0; + + if ((ptr = getenv("AFL_LLVM_MAP_ADDR"))) { + + uint64_t val; + if (!*ptr || !strcmp(ptr, "0") || !strcmp(ptr, "0x0")) { + + map_addr = 0; + + } else if (map_addr == 0) { + + FATAL( + "AFL_LLVM_MAP_ADDR and AFL_LLVM_MAP_DYNAMIC cannot be used together"); + + } else if (strncmp(ptr, "0x", 2) != 0) { + + map_addr = 0x10000; // the default + + } else { + + val = strtoull(ptr, NULL, 16); + if (val < 0x100 || val > 0xffffffff00000000) { + + FATAL( + "AFL_LLVM_MAP_ADDR must be a value between 0x100 and " + "0xffffffff00000000"); + + } + + map_addr = val; + + } + + } + + if (debug) { fprintf(stderr, "map address is %lu\n", map_addr); } + /* Get globals for the SHM region and the previous location. Note that __afl_prev_loc is thread-local. */ - GlobalVariable *AFLMapPtr = - new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, - GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); + GlobalVariable *AFLMapPtr = NULL; + ; + Value *MapPtrFixed = NULL; + + if (!map_addr) { + + AFLMapPtr = + new GlobalVariable(M, PointerType::get(Int8Ty, 0), false, + GlobalValue::ExternalLinkage, 0, "__afl_area_ptr"); + + } else { + + ConstantInt *MapAddr = ConstantInt::get(Int64Ty, map_addr); + MapPtrFixed = + ConstantExpr::getIntToPtr(MapAddr, PointerType::getUnqual(Int8Ty)); + + } ConstantInt *Zero = ConstantInt::get(Int8Ty, 0); ConstantInt *One = ConstantInt::get(Int8Ty, 1); @@ -202,7 +257,7 @@ bool AFLLTOPass::runOnModule(Module &M) { for (auto &F : M) { - //fprintf(stderr, "DEBUG: Function %s\n", F.getName().str().c_str()); + // fprintf(stderr, "DEBUG: Function %s\n", F.getName().str().c_str()); if (F.size() < 2) continue; if (isBlacklisted(&F)) continue; @@ -581,10 +636,20 @@ bool AFLLTOPass::runOnModule(Module &M) { /* Load SHM pointer */ - LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); - MapPtr->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(C, None)); - Value *MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); + Value *MapPtrIdx; + + if (map_addr) { + + MapPtrIdx = IRB.CreateGEP(MapPtrFixed, CurLoc); + + } else { + + LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr); + MapPtr->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + MapPtrIdx = IRB.CreateGEP(MapPtr, CurLoc); + + } /* Update bitmap */ @@ -629,7 +694,7 @@ bool AFLLTOPass::runOnModule(Module &M) { } - if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL || dictionary.size()) { + if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) { // yes we could create our own function, insert it into ctors ... // but this would be a pain in the butt ... so we use afl-llvm-rt-lto.o @@ -658,6 +723,18 @@ bool AFLLTOPass::runOnModule(Module &M) { BasicBlock::iterator IP = bb->getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); + if (map_addr) { + + GlobalVariable *AFLMapAddrFixed = new GlobalVariable( + M, Int64Ty, true, GlobalValue::ExternalLinkage, 0, "__afl_map_addr", + 0, GlobalVariable::GeneralDynamicTLSModel, 0, false); + ConstantInt *MapAddr = ConstantInt::get(Int64Ty, map_addr); + StoreInst * StoreMapAddr = IRB.CreateStore(MapAddr, AFLMapAddrFixed); + StoreMapAddr->setMetadata(M.getMDKindID("nosanitize"), + MDNode::get(C, None)); + + } + if (getenv("AFL_LLVM_LTO_DONTWRITEID") == NULL) { uint32_t write_loc = afl_global_id; diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index f286e66a..6da41192 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -52,6 +52,10 @@ #define CONST_PRIO 5 +//#ifndef MAP_FIXED_NOREPLACE +//#define MAP_FIXED_NOREPLACE MAP_FIXED +//#endif + #include #include @@ -69,12 +73,14 @@ u32 __afl_final_loc; u32 __afl_prev_ctx; u32 __afl_cmp_counter; u32 __afl_dictionary_len; +u64 __afl_map_addr; #else __thread PREV_LOC_T __afl_prev_loc[NGRAM_SIZE_MAX]; __thread u32 __afl_final_loc; __thread u32 __afl_prev_ctx; __thread u32 __afl_cmp_counter; __thread u32 __afl_dictionary_len; +__thread u64 __afl_map_addr; #endif struct cmp_map *__afl_cmp_map; @@ -87,7 +93,11 @@ static u8 is_persistent; static void __afl_map_shm(void) { - u8 *id_str = getenv(SHM_ENV_VAR); + u8 * id_str = getenv(SHM_ENV_VAR); + unsigned int map_size = MAP_SIZE; + + 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 @@ -99,10 +109,6 @@ static void __afl_map_shm(void) { const char * shm_file_path = id_str; int shm_fd = -1; unsigned char *shm_base = NULL; - unsigned int map_size = MAP_SIZE - - if (__afl_final_loc > 1 && __afl_final_loc < MAP_SIZE) map_size = - __afl_final_loc; /* create the shared memory segment as if it was a file */ shm_fd = shm_open(shm_file_path, O_RDWR, 0600); @@ -114,7 +120,18 @@ static void __afl_map_shm(void) { } /* map the shared memory segment to the address space of the process */ - shm_base = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + if (__afl_map_addr) { + + shm_base = mmap((void *)__afl_map_addr, map_size, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, shm_fd, 0); + + } else { + + shm_base = + mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0); + + } + if (shm_base == MAP_FAILED) { close(shm_fd); @@ -129,7 +146,8 @@ static void __afl_map_shm(void) { #else u32 shm_id = atoi(id_str); - __afl_area_ptr = shmat(shm_id, NULL, 0); + __afl_area_ptr = shmat(shm_id, (void *)__afl_map_addr, 0); + #endif /* Whooooops. */ @@ -141,6 +159,19 @@ static void __afl_map_shm(void) { __afl_area_ptr[0] = 1; + } 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); + if (__afl_area_ptr == MAP_FAILED) { + + fprintf(stderr, "can not aquire mmap for address %p\n", + (void *)__afl_map_addr); + exit(1); + + } + } id_str = getenv(CMPLOG_SHM_ENV_VAR); diff --git a/src/afl-common.c b/src/afl-common.c index 1dae8509..8d444876 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -67,10 +67,11 @@ char *afl_environment_variables[] = { "AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK", "AFL_LLVM_LAF_SPLIT_COMPARES", "AFL_LLVM_LAF_SPLIT_COMPARES_BITW", "AFL_LLVM_LAF_SPLIT_FLOATS", "AFL_LLVM_LAF_SPLIT_SWITCHES", "AFL_LLVM_LAF_TRANSFORM_COMPARES", - "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", - "AFL_LLVM_WHITELIST", "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", - "AFL_LLVM_LTO_DONTWRITEID", "AFL_NO_ARITH", "AFL_NO_BUILTIN", - "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON", + "AFL_LLVM_MAP_ADDR", "AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", + "AFL_NGRAM_SIZE", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_WHITELIST", + "AFL_NO_AFFINITY", "AFL_LLVM_LTO_STARTID", "AFL_LLVM_LTO_DONTWRITEID", + "AFL_NO_ARITH", "AFL_NO_BUILTIN", "AFL_NO_CPU_RED", "AFL_NO_FORKSRV", + "AFL_NO_UI", "AFL_NO_PYTHON", "AFL_NO_X86", // not really an env but we dont want to warn on it "AFL_MAP_SIZE", "AFL_MAPSIZE", "AFL_PATH", "AFL_PERFORMANCE_FILE", //"AFL_PERSISTENT", // not implemented anymore, so warn additionally diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c index e46c6f50..e024eb18 100644 --- a/src/afl-sharedmem.c +++ b/src/afl-sharedmem.c @@ -127,8 +127,8 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size, unsigned char dumb_mode) { } /* map the shared memory segment to the address space of the process */ - shm->map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, - shm->g_shm_fd, 0); + shm->map = + mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED, shm->g_shm_fd, 0); if (shm->map == MAP_FAILED) { close(shm->g_shm_fd); -- cgit 1.4.1 From 8ada9d06e8551821594bac13aedf6ff2406035ff Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 23 Apr 2020 11:51:32 +0200 Subject: fix make clean error --- GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/GNUmakefile b/GNUmakefile index 8a030fd8..e8e81c65 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -426,7 +426,7 @@ 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 + test -d unicorn_mode/unicornafl && $(MAKE) -C unicorn_mode/unicornafl clean || true else rm -rf qemu_mode/qemu-3.1.1.tar.xz rm -rf unicorn_mode/unicornafl -- cgit 1.4.1 From 5eb1f3a4c609851e7ee2127d29433b2ed6e56e56 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 23 Apr 2020 12:02:15 +0200 Subject: use mmap in llvm_mode if LTO is enabled --- llvm_mode/GNUmakefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 67c31f14..148210e8 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -68,6 +68,7 @@ endif ifeq "$(LLVM_MAJOR)" "11" $(info [+] llvm_mode detected llvm 11, enabling afl-clang-lto LTO implementation) LLVM_LTO = 1 + TEST_MMAP = 1 endif ifeq "$(LLVM_LTO)" "0" @@ -193,13 +194,13 @@ ifeq "$(shell echo '$(HASH)include @$(HASH)include @int ma else SHMAT_OK=0 CFLAGS+=-DUSEMMAP=1 - LDFLAGS += -lrt + LDFLAGS += -Wno-deprecated-declarations endif ifeq "$(TEST_MMAP)" "1" SHMAT_OK=0 CFLAGS+=-DUSEMMAP=1 - LDFLAGS += -lrt + LDFLAGS += -Wno-deprecated-declarations endif PROGS = ../afl-clang-fast ../afl-llvm-pass.so ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so -- 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 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 b6f9f4c436bc8c63f9039847d2a7b6e13da3515e Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 23 Apr 2020 16:08:36 +0200 Subject: minor changes --- README.md | 2 +- test/test-compcov.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 9ec7b6e7..222afab7 100644 --- a/README.md +++ b/README.md @@ -137,7 +137,7 @@ afl++ has many build options. The easiest is to build and install everything: ```shell -$ sudo apt install build-essential libtool-bin python3 automake bison libglib2.0-dev libpixman-1-dev clang python-setuptools +$ sudo apt install build-essential libtool-bin python3 automake bison libglib2.0-dev libpixman-1-dev clang python-setuptools llvm $ make distrib $ sudo make install ``` diff --git a/test/test-compcov.c b/test/test-compcov.c index f1743265..5278af93 100644 --- a/test/test-compcov.c +++ b/test/test-compcov.c @@ -25,11 +25,10 @@ int main(int argc, char **argv) { printf("your string was bugmenot\n"); else if (strcmp(input, "BUFFEROVERFLOW") == 0) { - buf = malloc(16); + buf = (char*)malloc(16); strcpy(buf, "TEST"); strcat(buf, input); printf("This will only crash with libdislocator: %s\n", buf); - return 0; } else if (*(unsigned int *)input == 0xabadcafe) -- cgit 1.4.1 From 82b6b8c87e1bc5394349fd2931b306f671c4da1a Mon Sep 17 00:00:00 2001 From: Rick van Schijndel Date: Thu, 23 Apr 2020 23:16:13 +0200 Subject: afl-gcc and afl-clang: fail when binary name can't be used to determine build mode This is a continuation of PR #318. The goal is to prevent issues where binaries with the wrong name will silently pass control to the C compiler instead of failing. This makes it more explicit that aflplusplus relies on the name of the binary for correct compiler execution. --- gcc_plugin/afl-gcc-fast.c | 8 +++++++- src/afl-gcc.c | 27 ++++++++++++++++++++++----- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/gcc_plugin/afl-gcc-fast.c b/gcc_plugin/afl-gcc-fast.c index 0e51ee62..164c72c2 100644 --- a/gcc_plugin/afl-gcc-fast.c +++ b/gcc_plugin/afl-gcc-fast.c @@ -123,11 +123,17 @@ static void edit_params(u32 argc, char **argv) { u8 *alt_cxx = getenv("AFL_CXX"); cc_params[0] = alt_cxx && *alt_cxx ? alt_cxx : (u8 *)AFL_GCC_CXX; - } else { + } else if (!strcmp(name, "afl-gcc-fast")) { u8 *alt_cc = getenv("AFL_CC"); cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)AFL_GCC_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++)-fast"); + } char *fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path); diff --git a/src/afl-gcc.c b/src/afl-gcc.c index 6c6bd1f1..ac6fdd62 100644 --- a/src/afl-gcc.c +++ b/src/afl-gcc.c @@ -149,11 +149,17 @@ static void edit_params(u32 argc, char **argv) { u8 *alt_cxx = getenv("AFL_CXX"); cc_params[0] = alt_cxx && *alt_cxx ? alt_cxx : (u8 *)"clang++"; - } else { + } else if (!strcmp(name, "afl-clang")) { u8 *alt_cc = getenv("AFL_CC"); cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)"clang"; + } else { + + fprintf(stderr, "Name of the binary: %s\n", argv[0]); + FATAL( + "Name of the binary is not a known name, expected afl-clang(++)"); + } } else { @@ -166,12 +172,17 @@ static void edit_params(u32 argc, char **argv) { #ifdef __APPLE__ - if (!strcmp(name, "afl-g++")) + if (!strcmp(name, "afl-g++")) { cc_params[0] = getenv("AFL_CXX"); - else if (!strcmp(name, "afl-gcj")) + } else if (!strcmp(name, "afl-gcj")) { cc_params[0] = getenv("AFL_GCJ"); - else + } 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"); + } if (!cc_params[0]) { @@ -199,11 +210,17 @@ static void edit_params(u32 argc, char **argv) { u8 *alt_cc = getenv("AFL_GCJ"); cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)"gcj"; - } else { + } else if (!strcmp(name, "afl-gcc")) { u8 *alt_cc = getenv("AFL_CC"); cc_params[0] = alt_cc && *alt_cc ? alt_cc : (u8 *)"gcc"; + } 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"); + } #endif /* __APPLE__ */ -- 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(-) 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 b3e77d3d500ea3c462b3eacdc338d57796f37c5d Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 24 Apr 2020 13:56:04 +0200 Subject: update documentation --- llvm_mode/README.lto.md | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/llvm_mode/README.lto.md b/llvm_mode/README.lto.md index 49407727..bb66b5e7 100644 --- a/llvm_mode/README.lto.md +++ b/llvm_mode/README.lto.md @@ -97,13 +97,12 @@ 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. +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. 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_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). @@ -122,12 +121,22 @@ Solution: ``` AR=llvm-ar RANLIB=llvm-ranlib CC=afl-clang-lto CXX=afl-clang-lto++ ./configure --disable-shared ``` -and on some target you have to to AR=/RANLIB= even for make as the configure script does not save it ... +and on some target you have to to AR=/RANLIB= even for make as the configure script does not save it. +Other targets ignore environment variables and need the parameters set via +`./configure --cc=... --cxx= --ranlib= ...` etc. (I am looking at you ffmpeg!). ### compiling programs still fail afl-clang-lto is still work in progress. -Please report issues at: + +Known issues: + * Anything that llvm11 cannot compile, afl-clang-lto can not compile either - obviously + * Anything that does not compile with LTO, afl-clang-lto can not compile either - obviously + +Hence if building a target with afl-clang-lto fails try to build it with llvm11 +and LTO enabled (`CC=clang-11` `CXX=clang++-11` `CFLAGS=-flto=full` and +`CXXFLAGS=-flto=full`). +If this succeeeds then there is an issue with afl-clang-lto. Please report at [https://github.com/AFLplusplus/AFLplusplus/issues/226](https://github.com/AFLplusplus/AFLplusplus/issues/226) ## Upcoming Work -- cgit 1.4.1 From 62aacf88ab57ff9fb3652c28c95b6bfdc6d72eec Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 24 Apr 2020 23:26:38 +0200 Subject: fix simple names --- src/afl-fuzz-bitmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c index 69fe6562..2289183c 100644 --- a/src/afl-fuzz-bitmap.c +++ b/src/afl-fuzz-bitmap.c @@ -721,7 +721,7 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) { #else snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir, - afl->unique_crashes, afl->kill_signal); + afl->unique_crashes, afl->last_kill_signal); #endif /* ^!SIMPLE_FILES */ -- cgit 1.4.1 From 5c017d7071c458193101ee864e055e68a13ed03d Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 12:48:48 +0200 Subject: travis Dockerfiles for testing and debugging --- test/travis/bionic/Dockerfile | 43 ++++++++++++++++++++++++++++++++++++++ test/travis/trusty/Dockerfile | 48 +++++++++++++++++++++++++++++++++++++++++++ test/travis/xenial/Dockerfile | 45 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 136 insertions(+) create mode 100644 test/travis/bionic/Dockerfile create mode 100644 test/travis/trusty/Dockerfile create mode 100644 test/travis/xenial/Dockerfile diff --git a/test/travis/bionic/Dockerfile b/test/travis/bionic/Dockerfile new file mode 100644 index 00000000..3883f775 --- /dev/null +++ b/test/travis/bionic/Dockerfile @@ -0,0 +1,43 @@ +# 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 \ + 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 + +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 new file mode 100644 index 00000000..7b86f3e7 --- /dev/null +++ b/test/travis/trusty/Dockerfile @@ -0,0 +1,48 @@ +# 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 \ + 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 new file mode 100644 index 00000000..a5f8d359 --- /dev/null +++ b/test/travis/xenial/Dockerfile @@ -0,0 +1,45 @@ +# 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 \ + 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"] -- cgit 1.4.1 From 232290108e2792034836193fa768562ef4476959 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 12:51:14 +0200 Subject: only build afl-gcc-fast if afl-gcc-pass could be build --- gcc_plugin/Makefile | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gcc_plugin/Makefile b/gcc_plugin/Makefile index 3da2e4f6..e81924e0 100644 --- a/gcc_plugin/Makefile +++ b/gcc_plugin/Makefile @@ -68,8 +68,7 @@ LDFLAGS_ADD=$(_LDFLAGS_ADD:0=-lrt) CFLAGS += $(CFLAGS_ADD) LDFLAGS += $(LDFLAGS_ADD) -PROGS = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o - +PROGS = ../afl-gcc-pass.so ../afl-gcc-fast ../afl-gcc-rt.o all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done -- cgit 1.4.1 From a3ee281e2ba364b618c056569222d70de036a3d7 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 12:55:01 +0200 Subject: fix python detection for Ubuntu and others --- .travis.yml | 2 +- GNUmakefile | 54 ++++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 41 insertions(+), 15 deletions(-) diff --git a/.travis.yml b/.travis.yml index 89d72c34..a360bd42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,7 +32,7 @@ jobs: - arch: arm64 env: - - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_STOP_MANUALLY=1 + - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 # - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_EXIT_WHEN_DONE=1 # TODO: test AFL_BENCH_UNTIL_CRASH once we have a target that crashes # - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_BENCH_JUST_ONE=1 diff --git a/GNUmakefile b/GNUmakefile index e8e81c65..0ba4a2b6 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -88,24 +88,50 @@ ifneq "$(shell command -v python3m 2>/dev/null)" "" endif endif -ifneq "$(shell command -v python3 2>/dev/null)" "" - ifneq "$(shell command -v python3-config 2>/dev/null)" "" - PYTHON_INCLUDE ?= $(shell python3-config --includes) - PYTHON_VERSION ?= $(strip $(shell python3 --version 2>&1)) - # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag. - ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1" - PYTHON_LIB ?= $(shell python3-config --libs --embed --ldflags) - else - PYTHON_LIB ?= $(shell python3-config --ldflags) +ifeq "$(PYTHON_INCLUDE)" "" + ifneq "$(shell command -v python3 2>/dev/null)" "" + ifneq "$(shell command -v python3-config 2>/dev/null)" "" + PYTHON_INCLUDE ?= $(shell python3-config --includes) + PYTHON_VERSION ?= $(strip $(shell python3 --version 2>&1)) + # Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag. + ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1" + PYTHON_LIB ?= $(shell python3-config --libs --embed --ldflags) + else + PYTHON_LIB ?= $(shell python3-config --ldflags) + endif + endif + endif +endif + +ifeq "$(PYTHON_INCLUDE)" "" + ifneq "$(shell command -v python 2>/dev/null)" "" + ifneq "$(shell command -v python-config 2>/dev/null)" "" + PYTHON_INCLUDE ?= $(shell python-config --includes) + PYTHON_LIB ?= $(shell python-config --ldflags) + PYTHON_VERSION ?= $(strip $(shell python --version 2>&1)) endif endif endif -ifneq "$(shell command -v python 2>/dev/null)" "" - ifneq "$(shell command -v python-config 2>/dev/null)" "" - PYTHON_INCLUDE ?= $(shell python-config --includes) - PYTHON_LIB ?= $(shell python-config --ldflags) - PYTHON_VERSION ?= $(strip $(shell python --version 2>&1)) +# Old Ubuntu and others dont have python/python3-config so we hardcode 3.7 +ifeq "$(PYTHON_INCLUDE)" "" + ifneq "$(shell command -v python3.7 2>/dev/null)" "" + ifneq "$(shell command -v python-config3.7-config 2>/dev/null)" "" + PYTHON_INCLUDE ?= $(shell python-config --includes) + PYTHON_LIB ?= $(shell python-config --ldflags) + PYTHON_VERSION ?= $(strip $(shell python --version 2>&1)) + endif + endif +endif + +# Old Ubuntu and others dont have python/python2-config so we hardcode 2.7 +ifeq "$(PYTHON_INCLUDE)" "" + ifneq "$(shell command -v python2.7 2>/dev/null)" "" + ifneq "$(shell command -v python-config2.7-config 2>/dev/null)" "" + PYTHON_INCLUDE ?= $(shell python-config --includes) + PYTHON_LIB ?= $(shell python-config --ldflags) + PYTHON_VERSION ?= $(strip $(shell python --version 2>&1)) + endif endif endif -- cgit 1.4.1 From 42017bbeda83f99979fc22a391b07ce6deebb824 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 12:57:45 +0200 Subject: fix python detection for Ubuntu and others --- GNUmakefile | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/GNUmakefile b/GNUmakefile index 0ba4a2b6..8811da03 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -116,10 +116,10 @@ endif # Old Ubuntu and others dont have python/python3-config so we hardcode 3.7 ifeq "$(PYTHON_INCLUDE)" "" ifneq "$(shell command -v python3.7 2>/dev/null)" "" - ifneq "$(shell command -v python-config3.7-config 2>/dev/null)" "" - PYTHON_INCLUDE ?= $(shell python-config --includes) - PYTHON_LIB ?= $(shell python-config --ldflags) - PYTHON_VERSION ?= $(strip $(shell python --version 2>&1)) + ifneq "$(shell command -v python3.7-config 2>/dev/null)" "" + PYTHON_INCLUDE ?= $(shell python3.7-config --includes) + PYTHON_LIB ?= $(shell python3.7-config --ldflags) + PYTHON_VERSION ?= $(strip $(shell python3.7 --version 2>&1)) endif endif endif @@ -127,10 +127,10 @@ endif # Old Ubuntu and others dont have python/python2-config so we hardcode 2.7 ifeq "$(PYTHON_INCLUDE)" "" ifneq "$(shell command -v python2.7 2>/dev/null)" "" - ifneq "$(shell command -v python-config2.7-config 2>/dev/null)" "" - PYTHON_INCLUDE ?= $(shell python-config --includes) - PYTHON_LIB ?= $(shell python-config --ldflags) - PYTHON_VERSION ?= $(strip $(shell python --version 2>&1)) + ifneq "$(shell command -v python2.7-config 2>/dev/null)" "" + PYTHON_INCLUDE ?= $(shell python2.7-config --includes) + PYTHON_LIB ?= $(shell python2.7-config --ldflags) + PYTHON_VERSION ?= $(strip $(shell python2.7 --version 2>&1)) endif endif endif -- cgit 1.4.1 From fa610270abeab4887396228a17db03a0aaedcd64 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 13:08:42 +0200 Subject: remove empty line --- docs/env_variables.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/env_variables.md b/docs/env_variables.md index f6f14dd2..41c8f12a 100644 --- a/docs/env_variables.md +++ b/docs/env_variables.md @@ -123,7 +123,6 @@ 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) -- 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(+) 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 From 0c3d06c41e2848f53db5caa881d624df87cec0d2 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sat, 25 Apr 2020 17:53:38 +0200 Subject: refactored whitelist and blacklist in llvm_mode --- libdislocator/libdislocator.so.c | 1 + llvm_mode/GNUmakefile | 40 ++--- llvm_mode/LLVMInsTrim.so.cc | 175 +--------------------- llvm_mode/afl-llvm-common.cc | 202 ++++++++++++++++++++++++++ llvm_mode/afl-llvm-common.h | 41 ++++++ llvm_mode/afl-llvm-lto-instrumentation.so.cc | 47 +----- llvm_mode/afl-llvm-lto-whitelist.so.cc | 22 +-- llvm_mode/afl-llvm-pass.so.cc | 210 +-------------------------- llvm_mode/cmplog-instructions-pass.cc | 134 +---------------- llvm_mode/cmplog-routines-pass.cc | 134 +---------------- llvm_mode/compare-transform-pass.so.cc | 134 +---------------- llvm_mode/split-compares-pass.so.cc | 153 +------------------ llvm_mode/split-switches-pass.so.cc | 152 +------------------ 13 files changed, 306 insertions(+), 1139 deletions(-) create mode 100644 llvm_mode/afl-llvm-common.cc create mode 100644 llvm_mode/afl-llvm-common.h diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c index 2a9c94f8..6c8916d6 100644 --- a/libdislocator/libdislocator.so.c +++ b/libdislocator/libdislocator.so.c @@ -500,3 +500,4 @@ __attribute__((constructor)) void __dislocator_init(void) { align_allocations = !!getenv("AFL_ALIGNED_ALLOC"); } + diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 148210e8..69b0875e 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -1,4 +1,3 @@ -# # american fuzzy lop++ - LLVM instrumentation # ----------------------------------------- # @@ -271,42 +270,45 @@ ifeq "$(LLVM_LTO)" "1" endif endif -../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps - -$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) +afl-llvm-common.o: afl-llvm-common.cc afl-llvm-common.h + $(CXX) $(CFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@ + +../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc afl-llvm-common.o | test_deps + -$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) afl-llvm-common.o -../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps +../afl-llvm-pass.so: afl-llvm-pass.so.cc afl-llvm-common.o | test_deps ifeq "$(LLVM_MIN_4_0_1)" "0" $(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER)) endif - $(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) + $(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o -../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc +../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc afl-llvm-common.o ifeq "$(LLVM_LTO)" "1" - $(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) + $(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o endif -../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc +../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc afl-llvm-common.o ifeq "$(LLVM_LTO)" "1" - $(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) + $(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o $(CC) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o @$(CC) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi @$(CC) $(CFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi endif # laf -../split-switches-pass.so: split-switches-pass.so.cc | test_deps - $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) -../compare-transform-pass.so: compare-transform-pass.so.cc | test_deps - $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) -../split-compares-pass.so: split-compares-pass.so.cc | test_deps - $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) +../split-switches-pass.so: split-switches-pass.so.cc afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o +../compare-transform-pass.so: compare-transform-pass.so.cc afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o +../split-compares-pass.so: split-compares-pass.so.cc afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o # /laf -../cmplog-routines-pass.so: cmplog-routines-pass.cc | test_deps - $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) +../cmplog-routines-pass.so: cmplog-routines-pass.cc afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o -../cmplog-instructions-pass.so: cmplog-instructions-pass.cc | test_deps - $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) +../cmplog-instructions-pass.so: cmplog-instructions-pass.cc afl-llvm-common.o | test_deps + $(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o ../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps $(CC) $(CFLAGS) -Wno-unused-result -fPIC -c $< -o $@ diff --git a/llvm_mode/LLVMInsTrim.so.cc b/llvm_mode/LLVMInsTrim.so.cc index 06fda187..98263ef1 100644 --- a/llvm_mode/LLVMInsTrim.so.cc +++ b/llvm_mode/LLVMInsTrim.so.cc @@ -40,6 +40,7 @@ typedef long double max_align_t; #include "debug.h" #include "MarkNodes.h" +#include "afl-llvm-common.h" using namespace llvm; @@ -53,9 +54,8 @@ namespace { struct InsTrim : public ModulePass { protected: - std::list myWhitelist; - uint32_t function_minimum_size = 1; - uint32_t debug = 0; + uint32_t function_minimum_size = 1; + uint32_t debug = 0; private: std::mt19937 generator; @@ -69,24 +69,10 @@ struct InsTrim : public ModulePass { public: static char ID; - InsTrim() : ModulePass(ID), generator(0) { - - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - myWhitelist.push_back(line); - getline(fileStream, line); + InsTrim() : ModulePass(ID), generator(0) { - } - - } + initWhitelist(); } @@ -107,26 +93,6 @@ struct InsTrim : public ModulePass { } - // ripped from aflgo - static bool isBlacklisted(const Function *F) { - - static const char *Blacklist[] = { - - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", - "_fini", "__libc_csu", "__asan", "__msan", "msan." - - }; - - for (auto const &BlacklistFunc : Blacklist) { - - if (F->getName().startswith(BlacklistFunc)) { return true; } - - } - - return false; - - } - bool runOnModule(Module &M) override { char be_quiet = 0; @@ -192,138 +158,11 @@ struct InsTrim : public ModulePass { } + if (!isInWhitelist(&F)) continue; + // if the function below our minimum size skip it (1 or 2) if (F.size() < function_minimum_size) { continue; } - if (!myWhitelist.empty()) { - - bool instrumentBlock = false; - DebugLoc Loc; - StringRef instFilename; - unsigned int instLine = 0; - -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - for (auto &BB : F) { - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); - if (!Loc) Loc = IP->getDebugLoc(); - - } - - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - instLine = cDILoc->getLine(); - instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#else - for (auto &BB : F) { - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - IRBuilder<> IRB(&(*IP)); - if (Loc.isUnknown()) Loc = IP->getDebugLoc(); - - } - - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - instLine = cDILoc.getLineNumber(); - instFilename = cDILoc.getFilename(); - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) { - - if (!be_quiet) { - - if (!instFilename.str().empty()) - SAYF(cYEL "[!] " cBRI - "Not in whitelist, skipping %s line %u...\n", - instFilename.str().c_str(), instLine); - else - SAYF(cYEL "[!] " cBRI - "No filename information found, skipping it"); - - } - - continue; - - } - - } - - if (isBlacklisted(&F)) continue; - std::unordered_set MS; if (!MarkSetOpt) { diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc new file mode 100644 index 00000000..9b7a444a --- /dev/null +++ b/llvm_mode/afl-llvm-common.cc @@ -0,0 +1,202 @@ +#define AFL_LLVM_PASS + +#include "config.h" +#include "debug.h" + +#include +#include +#include +#include + +#include +#include +#include + +#include "afl-llvm-common.h" + +using namespace llvm; + +static std::list myWhitelist; + +char *getBBName(const llvm::BasicBlock *BB) { + + static char *name; + + if (!BB->getName().empty()) { + + name = strdup(BB->getName().str().c_str()); + return name; + + } + + std::string Str; + raw_string_ostream OS(Str); + + BB->printAsOperand(OS, false); + name = strdup(OS.str().c_str()); + return name; + +} + +/* Function that we never instrument or analyze */ +/* Note: this blacklist check is also called in isInWhitelist() */ +bool isBlacklisted(const llvm::Function *F) { + + static const char *Blacklist[] = { + + "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", + "_fini", "__libc_csu", "__asan", "__msan", "msan." + + }; + + for (auto const &BlacklistFunc : Blacklist) { + + if (F->getName().startswith(BlacklistFunc)) { return true; } + + } + + return false; + +} + +void initWhitelist() { + + char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); + if (instWhiteListFilename) { + + std::string line; + std::ifstream fileStream; + fileStream.open(instWhiteListFilename); + if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); + getline(fileStream, line); + while (fileStream) { + + myWhitelist.push_back(line); + getline(fileStream, line); + + } + + } + +} + +bool isInWhitelist(llvm::Function *F) { + + // is this a function with code? If it is external we dont instrument it + // anyway and cant be in the whitelist. Or if it is blacklisted. + if (!F->size() || isBlacklisted(F)) return false; + + // if we do not have a whitelist return true + if (myWhitelist.empty()) return true; + + // let's try to get the filename for the function + auto bb = &F->getEntryBlock(); + BasicBlock::iterator IP = bb->getFirstInsertionPt(); + IRBuilder<> IRB(&(*IP)); + DebugLoc Loc = IP->getDebugLoc(); + +#if LLVM_VERSION_MAJOR >= 4 || \ + (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) + if (Loc) { + + DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); + + unsigned int instLine = cDILoc->getLine(); + StringRef instFilename = cDILoc->getFilename(); + + if (instFilename.str().empty()) { + + /* If the original location is empty, try using the inlined location + */ + DILocation *oDILoc = cDILoc->getInlinedAt(); + if (oDILoc) { + + instFilename = oDILoc->getFilename(); + instLine = oDILoc->getLine(); + + } + + } + + (void)instLine; + + /* Continue only if we know where we actually are */ + if (!instFilename.str().empty()) { + + for (std::list::iterator it = myWhitelist.begin(); + it != myWhitelist.end(); ++it) { + + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. */ + if (instFilename.str().length() >= it->length()) { + + if (instFilename.str().compare( + instFilename.str().length() - it->length(), it->length(), + *it) == 0) { + + return true; + + } + + } + + } + + } + + } + +#else + if (!Loc.isUnknown()) { + + DILocation cDILoc(Loc.getAsMDNode(C)); + + unsigned int instLine = cDILoc.getLineNumber(); + StringRef instFilename = cDILoc.getFilename(); + + (void)instLine; + /* Continue only if we know where we actually are */ + if (!instFilename.str().empty()) { + + for (std::list::iterator it = myWhitelist.begin(); + it != myWhitelist.end(); ++it) { + + /* We don't check for filename equality here because + * filenames might actually be full paths. Instead we + * check that the actual filename ends in the filename + * specified in the list. */ + if (instFilename.str().length() >= it->length()) { + + if (instFilename.str().compare( + instFilename.str().length() - it->length(), it->length(), + *it) == 0) { + + return true; + + } + + } + + } + + } + + } + +#endif + else { + + // we could not find out the location. in this case we say it is not + // in the whitelist + + return false; + + } + + // + return false; + +} + diff --git a/llvm_mode/afl-llvm-common.h b/llvm_mode/afl-llvm-common.h new file mode 100644 index 00000000..5b5e08d0 --- /dev/null +++ b/llvm_mode/afl-llvm-common.h @@ -0,0 +1,41 @@ +#ifndef __AFLLLVMCOMMON_H +#define __AFLLLVMCOMMON_H + +#include +#include +#include + +#include +#include +#include +#include + +#include "llvm/Config/llvm-config.h" +#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5 +typedef long double max_align_t; +#endif + +#include "llvm/IR/IRBuilder.h" +#include "llvm/IR/LegacyPassManager.h" +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Module.h" +#include "llvm/Support/Debug.h" +#include "llvm/Support/MathExtras.h" +#include "llvm/Transforms/IPO/PassManagerBuilder.h" + +#if LLVM_VERSION_MAJOR > 3 || \ + (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4) +#include "llvm/IR/DebugInfo.h" +#include "llvm/IR/CFG.h" +#else +#include "llvm/DebugInfo.h" +#include "llvm/Support/CFG.h" +#endif + +char *getBBName(const llvm::BasicBlock *BB); +bool isBlacklisted(const llvm::Function *F); +void initWhitelist(); +bool isInWhitelist(llvm::Function *F); + +#endif + diff --git a/llvm_mode/afl-llvm-lto-instrumentation.so.cc b/llvm_mode/afl-llvm-lto-instrumentation.so.cc index eefac629..118ada52 100644 --- a/llvm_mode/afl-llvm-lto-instrumentation.so.cc +++ b/llvm_mode/afl-llvm-lto-instrumentation.so.cc @@ -57,6 +57,7 @@ #include "llvm/Pass.h" #include +#include "afl-llvm-common.h" using namespace llvm; @@ -104,52 +105,6 @@ class AFLLTOPass : public ModulePass { } - // Get the internal llvm name of a basic block - // This is an ugly debug support so it is commented out :-) - /* - static char *getBBName(const BasicBlock *BB) { - - static char *name; - - if (!BB->getName().empty()) { - - name = strdup(BB->getName().str().c_str()); - return name; - - } - - std::string Str; - raw_string_ostream OS(Str); - - BB->printAsOperand(OS, false); - - name = strdup(OS.str().c_str()); - - return name; - - } - - */ - - static bool isBlacklisted(const Function *F) { - - static const char *Blacklist[] = { - - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", - "_fini", "__libc_csu", "__asan", "__msan", "msan." - - }; - - for (auto const &BlacklistFunc : Blacklist) { - - if (F->getName().startswith(BlacklistFunc)) { return true; } - - } - - return false; - - } - bool runOnModule(Module &M) override; protected: diff --git a/llvm_mode/afl-llvm-lto-whitelist.so.cc b/llvm_mode/afl-llvm-lto-whitelist.so.cc index 045ff6c4..5e157472 100644 --- a/llvm_mode/afl-llvm-lto-whitelist.so.cc +++ b/llvm_mode/afl-llvm-lto-whitelist.so.cc @@ -46,6 +46,8 @@ #include "llvm/Transforms/IPO/PassManagerBuilder.h" #include "llvm/IR/CFG.h" +#include "afl-llvm-common.h" + using namespace llvm; namespace { @@ -86,26 +88,6 @@ class AFLwhitelist : public ModulePass { } - // ripped from aflgo - static bool isBlacklisted(const Function *F) { - - static const SmallVector Blacklist = { - - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", - "_fini", "__libc_csu", "__asan", "__msan", "msan." - - }; - - for (auto const &BlacklistFunc : Blacklist) { - - if (F->getName().startswith(BlacklistFunc)) { return true; } - - } - - return false; - - } - bool runOnModule(Module &M) override; // StringRef getPassName() const override { diff --git a/llvm_mode/afl-llvm-pass.so.cc b/llvm_mode/afl-llvm-pass.so.cc index 0d15f5ec..9314c3d1 100644 --- a/llvm_mode/afl-llvm-pass.so.cc +++ b/llvm_mode/afl-llvm-pass.so.cc @@ -61,6 +61,7 @@ typedef long double max_align_t; #include "llvm/Support/CFG.h" #endif +#include "afl-llvm-common.h" #include "llvm-ngram-coverage.h" using namespace llvm; @@ -73,58 +74,17 @@ class AFLCoverage : public ModulePass { static char ID; AFLCoverage() : ModulePass(ID) { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - - } - - } - - } - - // ripped from aflgo - static bool isBlacklisted(const Function *F) { - - static const char *Blacklist[] = { - - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", - "_fini", "__libc_csu", "__asan", "__msan", "msan." - - }; - - for (auto const &BlacklistFunc : Blacklist) { - - if (F->getName().startswith(BlacklistFunc)) { return true; } - - } - - return false; + initWhitelist(); } bool runOnModule(Module &M) override; - // StringRef getPassName() const override { - - // return "American Fuzzy Lop Instrumentation"; - // } - protected: - std::list myWhitelist; - uint32_t ngram_size = 0; - uint32_t debug = 0; - uint32_t map_size = MAP_SIZE; - char * ctx_str = NULL; + uint32_t ngram_size = 0; + uint32_t debug = 0; + uint32_t map_size = MAP_SIZE; + char * ctx_str = NULL; }; @@ -334,9 +294,7 @@ bool AFLCoverage::runOnModule(Module &M) { fprintf(stderr, "FUNCTION: %s (%zu)\n", F.getName().str().c_str(), F.size()); - if (isBlacklisted(&F)) continue; - - // AllocaInst *CallingContext = nullptr; + if (!isInWhitelist(&F)) continue; if (ctx_str && F.size() > 1) { // Context sensitive coverage // load the context ID of the previous function and write to to a local @@ -391,115 +349,6 @@ bool AFLCoverage::runOnModule(Module &M) { BasicBlock::iterator IP = BB.getFirstInsertionPt(); IRBuilder<> IRB(&(*IP)); - if (!myWhitelist.empty()) { - - bool instrumentBlock = false; - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) continue; - - } - // in CTX mode we have to restore the original context for the caller - // she might be calling other functions which need the correct CTX if (ctx_str && has_calls) { @@ -628,54 +477,11 @@ bool AFLCoverage::runOnModule(Module &M) { * Counter + 1 -> {Counter, OverflowFlag} * Counter + OverflowFlag -> Counter */ - /* // we keep the old solutions just in case - // Solution #1 - if (neverZero_counters_str[0] == '1') { - - CallInst *AddOv = - IRB.CreateBinaryIntrinsic(Intrinsic::uadd_with_overflow, Counter, - ConstantInt::get(Int8Ty, 1)); - AddOv->setMetadata(M.getMDKindID("nosanitize"), - MDNode::get(C, None)); Value *SumWithOverflowBit = AddOv; Incr = - IRB.CreateAdd(IRB.CreateExtractValue(SumWithOverflowBit, 0), // sum - IRB.CreateZExt( // convert from one bit - type to 8 bits type IRB.CreateExtractValue(SumWithOverflowBit, 1), // - overflow Int8Ty)); - // Solution #2 - - } else if (neverZero_counters_str[0] == '2') { - - auto cf = IRB.CreateICmpEQ(Counter, - ConstantInt::get(Int8Ty, 255)); Value *HowMuch = - IRB.CreateAdd(ConstantInt::get(Int8Ty, 1), cf); Incr = - IRB.CreateAdd(Counter, HowMuch); - // Solution #3 - - } else if (neverZero_counters_str[0] == '3') { - - */ - // this is the solution we choose because llvm9 should do the right - // thing here + auto cf = IRB.CreateICmpEQ(Incr, Zero); auto carry = IRB.CreateZExt(cf, Int8Ty); Incr = IRB.CreateAdd(Incr, carry); -/* - // Solution #4 - - } else if (neverZero_counters_str[0] == '4') { - - auto cf = IRB.CreateICmpULT(Incr, ConstantInt::get(Int8Ty, 1)); - auto carry = IRB.CreateZExt(cf, Int8Ty); - Incr = IRB.CreateAdd(Incr, carry); - - } else { - - fprintf(stderr, "Error: unknown value for AFL_NZERO_COUNTS: %s - (valid is 1-4)\n", neverZero_counters_str); exit(-1); - - } -*/ #if LLVM_VERSION_MAJOR < 9 } diff --git a/llvm_mode/cmplog-instructions-pass.cc b/llvm_mode/cmplog-instructions-pass.cc index b0ab475d..628151c6 100644 --- a/llvm_mode/cmplog-instructions-pass.cc +++ b/llvm_mode/cmplog-instructions-pass.cc @@ -47,6 +47,7 @@ #endif #include +#include "afl-llvm-common.h" using namespace llvm; @@ -58,22 +59,7 @@ class CmpLogInstructions : public ModulePass { static char ID; CmpLogInstructions() : ModulePass(ID) { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - - } - - } + initWhitelist(); } @@ -91,8 +77,7 @@ class CmpLogInstructions : public ModulePass { } protected: - std::list myWhitelist; - int be_quiet = 0; + int be_quiet = 0; private: bool hookInstrs(Module &M); @@ -185,118 +170,9 @@ bool CmpLogInstructions::hookInstrs(Module &M) { /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { - for (auto &BB : F) { - - if (!myWhitelist.empty()) { - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - - bool instrumentBlock = false; - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } + if (!isInWhitelist(&F)) continue; - } - - } - - } - -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) continue; - - } + for (auto &BB : F) { for (auto &IN : BB) { diff --git a/llvm_mode/cmplog-routines-pass.cc b/llvm_mode/cmplog-routines-pass.cc index f58e351c..b74fb712 100644 --- a/llvm_mode/cmplog-routines-pass.cc +++ b/llvm_mode/cmplog-routines-pass.cc @@ -47,6 +47,7 @@ #endif #include +#include "afl-llvm-common.h" using namespace llvm; @@ -58,22 +59,7 @@ class CmpLogRoutines : public ModulePass { static char ID; CmpLogRoutines() : ModulePass(ID) { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - - } - - } + initWhitelist(); } @@ -91,8 +77,7 @@ class CmpLogRoutines : public ModulePass { } protected: - std::list myWhitelist; - int be_quiet = 0; + int be_quiet = 0; private: bool hookRtns(Module &M); @@ -132,118 +117,9 @@ bool CmpLogRoutines::hookRtns(Module &M) { /* iterate over all functions, bbs and instruction and add suitable calls */ for (auto &F : M) { - for (auto &BB : F) { - - if (!myWhitelist.empty()) { - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - - bool instrumentBlock = false; - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } + if (!isInWhitelist(&F)) continue; - } - - } - - } - -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) continue; - - } + for (auto &BB : F) { for (auto &IN : BB) { diff --git a/llvm_mode/compare-transform-pass.so.cc b/llvm_mode/compare-transform-pass.so.cc index 84a9b8d9..c871c1c4 100644 --- a/llvm_mode/compare-transform-pass.so.cc +++ b/llvm_mode/compare-transform-pass.so.cc @@ -47,6 +47,7 @@ #endif #include +#include "afl-llvm-common.h" using namespace llvm; @@ -58,22 +59,7 @@ class CompareTransform : public ModulePass { static char ID; CompareTransform() : ModulePass(ID) { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - - } - - } + initWhitelist(); } @@ -91,8 +77,7 @@ class CompareTransform : public ModulePass { } protected: - std::list myWhitelist; - int be_quiet = 0; + int be_quiet = 0; private: bool transformCmps(Module &M, const bool processStrcmp, @@ -140,118 +125,9 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp, * strcmp/memcmp/strncmp/strcasecmp/strncasecmp */ for (auto &F : M) { - for (auto &BB : F) { - - if (!myWhitelist.empty()) { - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - - bool instrumentBlock = false; - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); + if (!isInWhitelist(&F)) continue; - } - - } - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) continue; - - } + for (auto &BB : F) { for (auto &IN : BB) { diff --git a/llvm_mode/split-compares-pass.so.cc b/llvm_mode/split-compares-pass.so.cc index fab13b15..9c91e44f 100644 --- a/llvm_mode/split-compares-pass.so.cc +++ b/llvm_mode/split-compares-pass.so.cc @@ -46,6 +46,7 @@ #endif using namespace llvm; +#include "afl-llvm-common.h" namespace { @@ -55,41 +56,7 @@ class SplitComparesTransform : public ModulePass { static char ID; SplitComparesTransform() : ModulePass(ID) { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - - } - - } - - } - - static bool isBlacklisted(const Function *F) { - - static const char *Blacklist[] = { - - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", - "_fini", "__libc_csu", "__asan", "__msan", "msan." - - }; - - for (auto const &BlacklistFunc : Blacklist) { - - if (F->getName().startswith(BlacklistFunc)) { return true; } - - } - - return false; + initWhitelist(); } @@ -106,8 +73,7 @@ class SplitComparesTransform : public ModulePass { } protected: - std::list myWhitelist; - int be_quiet = 0; + int be_quiet = 0; private: int enableFPSplit; @@ -137,121 +103,10 @@ bool SplitComparesTransform::simplifyCompares(Module &M) { * all integer comparisons with >= and <= predicates to the icomps vector */ for (auto &F : M) { - if (isBlacklisted(&F)) continue; + if (!isInWhitelist(&F)) continue; for (auto &BB : F) { - if (!myWhitelist.empty()) { - - bool instrumentBlock = false; - - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) continue; - - } - for (auto &IN : BB) { CmpInst *selectcmpInst = nullptr; diff --git a/llvm_mode/split-switches-pass.so.cc b/llvm_mode/split-switches-pass.so.cc index 18b791ac..3444d6a1 100644 --- a/llvm_mode/split-switches-pass.so.cc +++ b/llvm_mode/split-switches-pass.so.cc @@ -49,6 +49,7 @@ #endif #include +#include "afl-llvm-common.h" using namespace llvm; @@ -60,41 +61,7 @@ class SplitSwitchesTransform : public ModulePass { static char ID; SplitSwitchesTransform() : ModulePass(ID) { - char *instWhiteListFilename = getenv("AFL_LLVM_WHITELIST"); - if (instWhiteListFilename) { - - std::string line; - std::ifstream fileStream; - fileStream.open(instWhiteListFilename); - if (!fileStream) report_fatal_error("Unable to open AFL_LLVM_WHITELIST"); - getline(fileStream, line); - while (fileStream) { - - myWhitelist.push_back(line); - getline(fileStream, line); - - } - - } - - } - - static bool isBlacklisted(const Function *F) { - - static const char *Blacklist[] = { - - "asan.", "llvm.", "sancov.", "__ubsan_handle_", "ign.", "__afl_", - "_fini", "__libc_csu", "__asan", "__msan", "msan." - - }; - - for (auto const &BlacklistFunc : Blacklist) { - - if (F->getName().startswith(BlacklistFunc)) { return true; } - - } - - return false; + initWhitelist(); } @@ -126,8 +93,7 @@ class SplitSwitchesTransform : public ModulePass { typedef std::vector CaseVector; protected: - std::list myWhitelist; - int be_quiet = 0; + int be_quiet = 0; private: bool splitSwitches(Module &M); @@ -347,122 +313,12 @@ bool SplitSwitchesTransform::splitSwitches(Module &M) { * all switches to switches vector for later processing */ for (auto &F : M) { - if (isBlacklisted(&F)) continue; + if (!isInWhitelist(&F)) continue; for (auto &BB : F) { SwitchInst *switchInst = nullptr; - if (!myWhitelist.empty()) { - - bool instrumentBlock = false; - BasicBlock::iterator IP = BB.getFirstInsertionPt(); - - /* Get the current location using debug information. - * For now, just instrument the block if we are not able - * to determine our location. */ - DebugLoc Loc = IP->getDebugLoc(); -#if LLVM_VERSION_MAJOR >= 4 || \ - (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7) - if (Loc) { - - DILocation *cDILoc = dyn_cast(Loc.getAsMDNode()); - - unsigned int instLine = cDILoc->getLine(); - StringRef instFilename = cDILoc->getFilename(); - - if (instFilename.str().empty()) { - - /* If the original location is empty, try using the inlined location - */ - DILocation *oDILoc = cDILoc->getInlinedAt(); - if (oDILoc) { - - instFilename = oDILoc->getFilename(); - instLine = oDILoc->getLine(); - - } - - } - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#else - if (!Loc.isUnknown()) { - - DILocation cDILoc(Loc.getAsMDNode(C)); - - unsigned int instLine = cDILoc.getLineNumber(); - StringRef instFilename = cDILoc.getFilename(); - - (void)instLine; - - /* Continue only if we know where we actually are */ - if (!instFilename.str().empty()) { - - for (std::list::iterator it = myWhitelist.begin(); - it != myWhitelist.end(); ++it) { - - /* We don't check for filename equality here because - * filenames might actually be full paths. Instead we - * check that the actual filename ends in the filename - * specified in the list. */ - if (instFilename.str().length() >= it->length()) { - - if (instFilename.str().compare( - instFilename.str().length() - it->length(), - it->length(), *it) == 0) { - - instrumentBlock = true; - break; - - } - - } - - } - - } - - } - -#endif - - /* Either we couldn't figure out our location or the location is - * not whitelisted, so we skip instrumentation. */ - if (!instrumentBlock) continue; - - } - if ((switchInst = dyn_cast(BB.getTerminator()))) { if (switchInst->getNumCases() < 1) continue; -- cgit 1.4.1 From 80916a3613c05b651eaab005caeb96bd80664d0f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 25 Apr 2020 18:13:11 +0100 Subject: Android supports arc4 api. --- include/types.h | 4 ++-- libdislocator/libdislocator.so.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/types.h b/include/types.h index f2a12953..a204294f 100644 --- a/include/types.h +++ b/include/types.h @@ -108,7 +108,7 @@ typedef int64_t s64; }) #ifdef AFL_LLVM_PASS -#if defined(__linux__) +#if defined(__linux__) || !defined(__ANDROID__) #define AFL_SR(s) (srandom(s)) #define AFL_R(x) (random() % (x)) #else @@ -116,7 +116,7 @@ typedef int64_t s64; #define AFL_R(x) (arc4random_uniform(x)) #endif #else -#if defined(__linux__) +#if defined(__linux__) || !defined(__ANDROID__) #define SR(s) (srandom(s)) #define R(x) (random() % (x)) #else diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c index 6c8916d6..73ddc292 100644 --- a/libdislocator/libdislocator.so.c +++ b/libdislocator/libdislocator.so.c @@ -37,7 +37,7 @@ #include #endif -#ifdef __linux__ +#if defined(__linux__) && !defined(__ANDROID__) #include #include #ifdef __NR_getrandom -- cgit 1.4.1 From 2a60ceb6944a7ca273057ddf64dcf837bf7f9521 Mon Sep 17 00:00:00 2001 From: hexcoder Date: Sat, 25 Apr 2020 21:29:19 +0200 Subject: fix issue #333 --- libdislocator/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libdislocator/Makefile b/libdislocator/Makefile index 37fd4fd6..f9c4cb65 100644 --- a/libdislocator/Makefile +++ b/libdislocator/Makefile @@ -39,5 +39,5 @@ clean: install: all install -m 755 -d $${DESTDIR}$(HELPER_PATH) install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH) - install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH) + install -m 644 -T README.md $${DESTDIR}$(HELPER_PATH)/README.dislocator.md -- cgit 1.4.1 From 646aeb2b18f91c562fa8de656c87f3cb205ce99f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 26 Apr 2020 00:54:02 +0200 Subject: try unicorn build without -j --- unicorn_mode/build_unicorn_support.sh | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index 1e5b3ef4..d84d8635 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -182,7 +182,8 @@ echo "[+] Configuration complete." echo "[*] Attempting to build unicornafl (fingers crossed!)..." $MAKECMD clean # make doesn't seem to work for unicorn -UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD -j$CORES || exit 1 +#UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD -j$CORES || exit 1 +UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD || exit 1 echo "[+] Build process successful!" -- cgit 1.4.1 From b26ee09f71907e1bcaca0a73cee3accd11580c9f Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 26 Apr 2020 01:59:38 +0200 Subject: minor fixes --- src/afl-forkserver.c | 6 ++---- unicorn_mode/build_unicorn_support.sh | 4 ++-- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 555b82a4..d5a60077 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -53,9 +53,7 @@ /* Describe integer as memory size. */ -list_t fsrv_list = {.element_prealloc_count = 0}; - -void report_error_and_exit(int error); +static list_t fsrv_list = {.element_prealloc_count = 0}; static void fsrv_exec_child(afl_forkserver_t *fsrv, char **argv) { @@ -203,7 +201,7 @@ 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) { +static void report_error_and_exit(int error) { switch (error) { diff --git a/unicorn_mode/build_unicorn_support.sh b/unicorn_mode/build_unicorn_support.sh index d84d8635..965d7614 100755 --- a/unicorn_mode/build_unicorn_support.sh +++ b/unicorn_mode/build_unicorn_support.sh @@ -182,8 +182,8 @@ echo "[+] Configuration complete." echo "[*] Attempting to build unicornafl (fingers crossed!)..." $MAKECMD clean # make doesn't seem to work for unicorn -#UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD -j$CORES || exit 1 -UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD || exit 1 +# Fixed to 1 core for now as there is a race condition in the makefile +UNICORN_QEMU_FLAGS="--python=$PYTHONBIN" $MAKECMD -j1 || exit 1 echo "[+] Build process successful!" -- cgit 1.4.1 From 85627516a40d75746e00427710dd16c1161f2532 Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 26 Apr 2020 02:05:17 +0200 Subject: map_size one liner --- src/afl-fuzz-state.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 9f48182b..af6fc11f 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -81,15 +81,7 @@ 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; - - } else { - - afl->shm.map_size = map_size; - - } + afl->shm.map_size = map_size ? map_size : MAP_SIZE; afl->w_init = 0.9; afl->w_end = 0.3; -- cgit 1.4.1 From 66eee34709be9b91808601c7e3e638ffacb858db Mon Sep 17 00:00:00 2001 From: Dominik Maier Date: Sun, 26 Apr 2020 02:32:09 +0200 Subject: refactored global lists --- include/afl-fuzz.h | 13 ++++++++----- include/common.h | 2 +- src/afl-common.c | 2 +- src/afl-fuzz-init.c | 13 +++---------- src/afl-fuzz-state.c | 33 ++++++++++++++++++++++++++++++++- test/unittests/unit_list.c | 2 +- 6 files changed, 46 insertions(+), 19 deletions(-) diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h index 428bfa8e..2203cfdf 100644 --- a/include/afl-fuzz.h +++ b/include/afl-fuzz.h @@ -614,11 +614,6 @@ typedef struct afl_state { } afl_state_t; -/* A global pointer to all instances is needed (for now) for signals to arrive - */ - -extern list_t afl_states; - struct custom_mutator { const char *name; @@ -800,6 +795,14 @@ struct custom_mutator { void afl_state_init(afl_state_t *, uint32_t map_size); void afl_state_deinit(afl_state_t *); + +/* Set stop_soon flag on all childs, kill all childs */ +void afl_states_stop(void); +/* Set clear_screen flag on all states */ +void afl_states_clear_screen(void); +/* Sets the skip flag on all states */ +void afl_states_request_skip(void); + void read_afl_environment(afl_state_t *, char **); /**** Prototypes ****/ diff --git a/include/common.h b/include/common.h index 70ff0744..4aed9572 100644 --- a/include/common.h +++ b/include/common.h @@ -115,7 +115,7 @@ u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms); u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, volatile u8 *stop_soon_p); -u32 get_map_size(); +u32 get_map_size(void); #endif diff --git a/src/afl-common.c b/src/afl-common.c index 8ae03113..dda62219 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -918,7 +918,7 @@ u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms, } -u32 get_map_size() { +u32 get_map_size(void) { uint32_t map_size = MAP_SIZE; char * ptr; diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 4dd31ac9..32481887 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -1903,7 +1903,7 @@ void fix_up_sync(afl_state_t *afl) { static void handle_resize(int sig) { - LIST_FOREACH(&afl_states, afl_state_t, { el->clear_screen = 1; }); + afl_states_clear_screen(); } @@ -1954,14 +1954,7 @@ void check_asan_opts(void) { static void handle_stop_sig(int sig) { - LIST_FOREACH(&afl_states, afl_state_t, { - - el->stop_soon = 1; - - if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, SIGKILL); - if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, SIGKILL); - - }); + afl_states_stop(); } @@ -1969,7 +1962,7 @@ static void handle_stop_sig(int sig) { static void handle_skipreq(int sig) { - LIST_FOREACH(&afl_states, afl_state_t, { el->skip_requested = 1; }); + afl_states_request_skip(); } diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index af6fc11f..4f5389e3 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -71,7 +71,7 @@ static void init_mopt_globals(afl_state_t *afl) { /* A global pointer to all instances is needed (for now) for signals to arrive */ -list_t afl_states = {.element_prealloc_count = 0}; +static list_t afl_states = {.element_prealloc_count = 0}; /* Initializes an afl_state_t. */ @@ -398,3 +398,34 @@ void afl_state_deinit(afl_state_t *afl) { } +void afl_states_stop(void) { + + /* We may be inside a signal handler. + Set flags first, send kill signals to child proceses later. */ + LIST_FOREACH(&afl_states, afl_state_t, { + + el->stop_soon = 1; + + }); + + LIST_FOREACH(&afl_states, afl_state_t, { + + if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, SIGKILL); + if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, SIGKILL); + + }); + +} + +void afl_states_clear_screen(void) { + + LIST_FOREACH(&afl_states, afl_state_t, { el->clear_screen = 1; }); + +} + +void afl_states_request_skip(void) { + + LIST_FOREACH(&afl_states, afl_state_t, { el->skip_requested = 1; }); + +} + diff --git a/test/unittests/unit_list.c b/test/unittests/unit_list.c index 90700a11..df4864e4 100644 --- a/test/unittests/unit_list.c +++ b/test/unittests/unit_list.c @@ -40,7 +40,7 @@ int __wrap_printf(const char *format, ...) { return 1; } -list_t testlist; +static list_t testlist = {.element_prealloc_count = 0}; static void test_contains(void **state) { -- cgit 1.4.1 From ea876e59a8c1abc979ea05aa4dbe660608aaa9ba Mon Sep 17 00:00:00 2001 From: van Hauser Date: Sun, 26 Apr 2020 14:45:00 +0200 Subject: moved defines to type --- include/config.h | 23 ----------------------- include/types.h | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 23 deletions(-) diff --git a/include/config.h b/include/config.h index dca5a8f0..c21d775a 100644 --- a/include/config.h +++ b/include/config.h @@ -400,28 +400,5 @@ #endif #endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */ -/* 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 > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) - #endif /* ! _HAVE_CONFIG_H */ diff --git a/include/types.h b/include/types.h index a204294f..e7ff131d 100644 --- a/include/types.h +++ b/include/types.h @@ -30,6 +30,29 @@ typedef uint8_t u8; typedef uint16_t u16; typedef uint32_t u32; +/* 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 > FS_OPT_MAX_MAPSIZE ? 0 : ((x - 1) << 1)) + /* Ugh. There is an unintended compiler / glibc #include glitch caused by -- cgit 1.4.1