about summary refs log tree commit diff
path: root/utils/aflpp_driver
diff options
context:
space:
mode:
Diffstat (limited to 'utils/aflpp_driver')
-rw-r--r--utils/aflpp_driver/GNUmakefile23
-rw-r--r--utils/aflpp_driver/aflpp_driver.c130
-rw-r--r--utils/aflpp_driver/aflpp_driver_test.c17
3 files changed, 121 insertions, 49 deletions
diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile
index 234a1c31..b973f96a 100644
--- a/utils/aflpp_driver/GNUmakefile
+++ b/utils/aflpp_driver/GNUmakefile
@@ -8,9 +8,14 @@ ifeq "$(shell uname -s)" "Darwin"
   LDFLAGS += $(SDK_LD)
 endif
 
+ifeq "" "$(LLVM_CONFIG)"
+  LLVM_CONFIG := llvm-config
+endif
 LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
 ifneq "" "$(LLVM_BINDIR)"
-  LLVM_BINDIR := $(LLVM_BINDIR)/
+  ifeq "$(shell test -x $(LLVM_BINDIR)/clang && echo 1)" "1"
+    CC := $(LLVM_BINDIR)/clang
+  endif
 endif
 
 CFLAGS := -O3 -funroll-loops -g -fPIC
@@ -18,31 +23,31 @@ CFLAGS := -O3 -funroll-loops -g -fPIC
 all:	libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so
 
 aflpp_driver.o:	aflpp_driver.c
-	-$(LLVM_BINDIR)clang -I. -I../../include $(CFLAGS) -c aflpp_driver.c
+	-$(CC) -I. -I../../include $(CFLAGS) -c aflpp_driver.c
 
 libAFLDriver.a:	aflpp_driver.o
 	@ar rc libAFLDriver.a aflpp_driver.o
 	@cp -vf libAFLDriver.a ../../
 
 debug:
-	$(LLVM_BINDIR)clang -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c
-	$(LLVM_BINDIR)clang -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c
-	#$(LLVM_BINDIR)clang -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c
-	#$(LLVM_BINDIR)clang -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c
+	$(CC) -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.o ../../src/afl-performance.c
+	$(CC) -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c
+	#$(CC) -S -emit-llvm -Wno-deprecated -I../../include $(CFLAGS) -D_DEBUG=\"1\" -c -o afl-performance.ll ../../src/afl-performance.c
+	#$(CC) -S -emit-llvm -I../../include -D_DEBUG=\"1\" -g -funroll-loops -c aflpp_driver.c
 	ar rc libAFLDriver.a afl-performance.o aflpp_driver.o
 
 aflpp_qemu_driver.o:	aflpp_qemu_driver.c
-	-$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c
+	-$(CC) $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c
 
 libAFLQemuDriver.a:	aflpp_qemu_driver.o
 	@-ar rc libAFLQemuDriver.a aflpp_qemu_driver.o
 	@-cp -vf libAFLQemuDriver.a ../../
 
 aflpp_qemu_driver_hook.so:	aflpp_qemu_driver_hook.o
-	@-test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built."
+	@-test -e aflpp_qemu_driver_hook.o && $(CC) $(LDFLAGS) -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built."
 
 aflpp_qemu_driver_hook.o:	aflpp_qemu_driver_hook.c
-	@-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built."
+	@-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(CC) $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built."
 
 test:	debug
 	#clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c
diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c
index 4e4ea129..4e8f466d 100644
--- a/utils/aflpp_driver/aflpp_driver.c
+++ b/utils/aflpp_driver/aflpp_driver.c
@@ -1,12 +1,16 @@
-//===- afl_driver.cpp - a glue between AFL++ and libFuzzer ------*- C++ -* ===//
-//===----------------------------------------------------------------------===//
+//
+// afl_driver.cpp - a glue between AFL++ and LLVMFuzzerTestOneInput harnesses
+//
 
-/* This file allows to fuzz libFuzzer-style target functions
+/*
+
+ This file allows to fuzz libFuzzer-style target functions
  (LLVMFuzzerTestOneInput) with AFL++ using persistent in-memory fuzzing.
 
 Usage:
-################################################################################
-cat << EOF > test_fuzzer.cc
+
+# Example target:
+$ cat << EOF > test_fuzzer.cc
 #include <stddef.h>
 #include <stdint.h>
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
@@ -20,21 +24,24 @@ extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
 }
 
 EOF
-# Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
-clang -c aflpp_driver.c
-# Build afl-compiler-rt.o.c from the AFL distribution.
-clang -c $AFL_HOME/instrumentation/afl-compiler-rt.o.c
-# Build this file, link it with afl-compiler-rt.o.o and the target code.
-afl-clang-fast -o test_fuzzer test_fuzzer.cc afl-compiler-rt.o aflpp_driver.o
+
+# Build your target with afl-cc -fsanitize=fuzzer
+$ afl-c++ -fsanitize=fuzzer -o test_fuzzer test_fuzzer.cc
 # Run AFL:
-rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
-$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
-################################################################################
+$ mkdir -p in ; echo z > in/foo;
+$ afl-fuzz -i in -o out -- ./test_fuzzer
+
 */
 
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+
 #include <assert.h>
 #include <errno.h>
 #include <stdarg.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -57,15 +64,26 @@ $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
   #include "hash.h"
 #endif
 
+// AFL++ shared memory fuzz cases
 int                   __afl_sharedmem_fuzzing = 1;
 extern unsigned int  *__afl_fuzz_len;
 extern unsigned char *__afl_fuzz_ptr;
 
-// libFuzzer interface is thin, so we don't include any libFuzzer headers.
-int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
-__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
+// AFL++ coverage map
+extern unsigned char *__afl_area_ptr;
+extern unsigned int   __afl_map_size;
 
-// Default nop ASan hooks for manual posisoning when not linking the ASan
+// libFuzzer interface is thin, so we don't include any libFuzzer headers.
+/* Using the weak attributed on LLVMFuzzerTestOneInput() breaks oss-fuzz but
+   on the other hand this is what Google needs to make LLVMFuzzerRunDriver()
+   work. Choose your poison Google! */
+/*__attribute__((weak))*/ int LLVMFuzzerTestOneInput(const uint8_t *Data,
+                                                     size_t         Size);
+__attribute__((weak)) int     LLVMFuzzerInitialize(int *argc, char ***argv);
+__attribute__((weak)) int     LLVMFuzzerRunDriver(
+        int *argc, char ***argv, int (*callback)(const uint8_t *data, size_t size));
+
+// Default nop ASan hooks for manual poisoning when not linking the ASan
 // runtime
 // https://github.com/google/sanitizers/wiki/AddressSanitizerManualPoisoning
 __attribute__((weak)) void __asan_poison_memory_region(
@@ -187,7 +205,8 @@ static void maybe_close_fd_mask() {
 
 // Define LLVMFuzzerMutate to avoid link failures for targets that use it
 // with libFuzzer's LLVMFuzzerCustomMutator.
-size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
+__attribute__((weak)) size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size,
+                                              size_t MaxSize) {
 
   // assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
   return 0;
@@ -195,7 +214,9 @@ size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
 }
 
 // Execute any files provided as parameters.
-static int ExecuteFilesOnyByOne(int argc, char **argv) {
+static int ExecuteFilesOnyByOne(int argc, char **argv,
+                                int (*callback)(const uint8_t *data,
+                                                size_t         size)) {
 
   unsigned char *buf = (unsigned char *)malloc(MAX_FILE);
 
@@ -231,7 +252,7 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
       prev_length = length;
 
       printf("Reading %zu bytes from %s\n", length, argv[i]);
-      LLVMFuzzerTestOneInput(buf, length);
+      callback(buf, length);
       printf("Execution successful.\n");
 
     }
@@ -245,7 +266,18 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) {
 
 }
 
-int main(int argc, char **argv) {
+__attribute__((weak)) int main(int argc, char **argv) {
+
+  // Enable if LLVMFuzzerTestOneInput() has the weak attribute
+  /*
+    if (!LLVMFuzzerTestOneInput) {
+
+      fprintf(stderr, "Error: function LLVMFuzzerTestOneInput() not found!\n");
+      abort();
+
+    }
+
+  */
 
   if (argc < 2 || strncmp(argv[1], "-h", 2) == 0)
     printf(
@@ -265,6 +297,17 @@ int main(int argc, char **argv) {
         "===================================================================\n",
         argv[0], argv[0]);
 
+  return LLVMFuzzerRunDriver(&argc, &argv, LLVMFuzzerTestOneInput);
+
+}
+
+__attribute__((weak)) int LLVMFuzzerRunDriver(
+    int *argcp, char ***argvp,
+    int (*callback)(const uint8_t *data, size_t size)) {
+
+  int    argc = *argcp;
+  char **argv = *argvp;
+
   if (getenv("AFL_GDB")) {
 
     char cmd[64];
@@ -275,6 +318,12 @@ int main(int argc, char **argv) {
 
   }
 
+  bool in_afl = !(!getenv(SHM_FUZZ_ENV_VAR) || !getenv(SHM_ENV_VAR) ||
+                  fcntl(FORKSRV_FD, F_GETFD) == -1 ||
+                  fcntl(FORKSRV_FD + 1, F_GETFD) == -1);
+
+  if (!in_afl) { __afl_sharedmem_fuzzing = 0; }
+
   output_file = stderr;
   maybe_duplicate_stderr();
   maybe_close_fd_mask();
@@ -295,27 +344,28 @@ int main(int argc, char **argv) {
 
   int N = INT_MAX;
 
-  if (argc == 2 && !strcmp(argv[1], "-")) {
+  if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) {
 
-    __afl_sharedmem_fuzzing = 0;
     __afl_manual_init();
-    return ExecuteFilesOnyByOne(argc, argv);
+    return ExecuteFilesOnyByOne(argc, argv, callback);
 
-  } else if (argc == 2 && argv[1][0] == '-') {
+  } else if (argc == 2 && argv[1][0] == '-' && argv[1][1]) {
 
     N = atoi(argv[1] + 1);
 
-  } else if (argc == 2 && (N = atoi(argv[1])) > 0) {
+  } else if (argc == 2 && argv[1][0] != '-' && (N = atoi(argv[1])) > 0) {
 
     printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
 
-  } else if (argc > 1) {
-
-    __afl_sharedmem_fuzzing = 0;
+  } else if (!in_afl && argc > 1 && argv[1][0] != '-') {
 
     if (argc == 2) { __afl_manual_init(); }
 
-    return ExecuteFilesOnyByOne(argc, argv);
+    return ExecuteFilesOnyByOne(argc, argv, callback);
+
+  } else {
+
+    N = INT_MAX;
 
   }
 
@@ -325,7 +375,7 @@ int main(int argc, char **argv) {
 
   // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
   // on the first execution of LLVMFuzzerTestOneInput is ignored.
-  LLVMFuzzerTestOneInput(dummy_input, 4);
+  callback(dummy_input, 4);
 
   __asan_poison_memory_region(__afl_fuzz_ptr, MAX_FILE);
   size_t prev_length = 0;
@@ -352,7 +402,13 @@ int main(int argc, char **argv) {
         }
 
         prev_length = length;
-        LLVMFuzzerTestOneInput(__afl_fuzz_ptr, length);
+
+        if (unlikely(callback(__afl_fuzz_ptr, length) == -1)) {
+
+          memset(__afl_area_ptr, 0, __afl_map_size);
+          __afl_area_ptr[0] = 1;
+
+        }
 
       }
 
@@ -362,7 +418,7 @@ int main(int argc, char **argv) {
 
     while (__afl_persistent_loop(N)) {
 
-      LLVMFuzzerTestOneInput(__afl_fuzz_ptr, *__afl_fuzz_len);
+      callback(__afl_fuzz_ptr, *__afl_fuzz_len);
 
     }
 
@@ -372,3 +428,9 @@ int main(int argc, char **argv) {
 
 }
 
+#ifdef __cplusplus
+
+}
+
+#endif
+
diff --git a/utils/aflpp_driver/aflpp_driver_test.c b/utils/aflpp_driver/aflpp_driver_test.c
index 527ba57b..32119485 100644
--- a/utils/aflpp_driver/aflpp_driver_test.c
+++ b/utils/aflpp_driver/aflpp_driver_test.c
@@ -2,23 +2,28 @@
 #include <stdlib.h>
 #include <stdint.h>
 
-void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
+char *foo = NULL;
 
-  if (Size < 5) return;
+int __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
+
+  if (Size < 5) return -1;
 
   if (Data[0] == 'F')
     if (Data[1] == 'A')
       if (Data[2] == '$')
         if (Data[3] == '$')
-          if (Data[4] == '$') abort();
+          if (Data[4] == '$') *foo = 1;
+
+  return 0;
 
 }
 
 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
 
-  if (Size) crashme(Data, Size);
-
-  return 0;
+  if (Size)
+    return crashme(Data, Size);
+  else
+    return -1;
 
 }