diff options
Diffstat (limited to 'llvm_mode')
-rw-r--r-- | llvm_mode/GNUmakefile | 13 | ||||
-rw-r--r-- | llvm_mode/README.persistent_mode.md | 2 | ||||
-rw-r--r-- | llvm_mode/README.whitelist.md | 4 | ||||
-rw-r--r-- | llvm_mode/afl-clang-fast.c | 9 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-common.cc | 19 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-lto-whitelist.so.cc | 6 | ||||
-rw-r--r-- | llvm_mode/afl-llvm-rt.o.c | 75 |
7 files changed, 97 insertions, 31 deletions
diff --git a/llvm_mode/GNUmakefile b/llvm_mode/GNUmakefile index 50a6be2b..5efe1e12 100644 --- a/llvm_mode/GNUmakefile +++ b/llvm_mode/GNUmakefile @@ -226,6 +226,10 @@ endif ifeq "$(shell uname)" "OpenBSD" CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so + CLANG_CFL += -mno-retpoline + CFLAGS += -mno-retpoline + # Needed for unwind symbols + LDFLAGS += -lc++abi endif ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1" @@ -354,16 +358,21 @@ endif ../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 +document: + $(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o + @$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + @$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + ../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps $(CLANG_BIN) $(CFLAGS) -Wno-unused-result -fPIC -c $< -o $@ ../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps @printf "[*] Building 32-bit variant of the runtime (-m32)... " - @$(CC_SAVE) $(CFLAGS) -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + @$(CLANG_BIN) $(CFLAGS) -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi ../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps @printf "[*] Building 64-bit variant of the runtime (-m64)... " - @$(CC_SAVE) $(CFLAGS) -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi + @$(CLANG_BIN) $(CFLAGS) -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi test_build: $(PROGS) @echo "[*] Testing the CC wrapper and instrumentation output..." diff --git a/llvm_mode/README.persistent_mode.md b/llvm_mode/README.persistent_mode.md index 7aae8faa..83cc7f4d 100644 --- a/llvm_mode/README.persistent_mode.md +++ b/llvm_mode/README.persistent_mode.md @@ -55,7 +55,7 @@ The speed increase is usually x10 to x20. ## 3) deferred initialization AFL tries to optimize performance by executing the targeted binary just once, -stopping it just before main(), and then cloning this "master" process to get +stopping it just before main(), and then cloning this "main" process to get a steady supply of targets to fuzz. Although this approach eliminates much of the OS-, linker- and libc-level diff --git a/llvm_mode/README.whitelist.md b/llvm_mode/README.whitelist.md index 72fb5d09..6393fae8 100644 --- a/llvm_mode/README.whitelist.md +++ b/llvm_mode/README.whitelist.md @@ -73,3 +73,7 @@ For old LLVM versions this feature might require to be compiled with debug information (-g), however at least from llvm version 6.0 onwards this is not required anymore (and might hurt performance and crash detection, so better not use -g). + +## 4) UNIX-style filename pattern matching +You can add UNIX-style pattern matching in the whitelist entries. See `man +fnmatch` for the syntax. We do not set any of the `fnmatch` flags. diff --git a/llvm_mode/afl-clang-fast.c b/llvm_mode/afl-clang-fast.c index 0b081ae6..75504ea5 100644 --- a/llvm_mode/afl-clang-fast.c +++ b/llvm_mode/afl-clang-fast.c @@ -176,7 +176,8 @@ static void edit_params(u32 argc, char **argv, char **envp) { "Using afl-clang-lto is not possible because Makefile magic did not " "identify the correct -flto flag"); - if (!strcmp(name, "afl-clang-fast++") || !strcmp(name, "afl-clang-lto++")) { + if (!strcmp(name, "afl-clang-fast++") || !strcmp(name, "afl-clang-lto++") || + !strcmp(name, "afl-clang++")) { u8 *alt_cxx = getenv("AFL_CXX"); if (USE_BINDIR) @@ -188,7 +189,7 @@ static void edit_params(u32 argc, char **argv, char **envp) { } else if (!strcmp(name, "afl-clang-fast") || - !strcmp(name, "afl-clang-lto")) { + !strcmp(name, "afl-clang-lto") || !strcmp(name, "afl-clang")) { u8 *alt_cc = getenv("AFL_CC"); if (USE_BINDIR) @@ -494,14 +495,14 @@ static void edit_params(u32 argc, char **argv, char **envp) { cc_params[cc_par_cnt++] = "-D__AFL_FUZZ_INIT()=" "int __afl_sharedmem_fuzzing = 1;" - "extern unsigned int __afl_fuzz_len;" + "extern unsigned int *__afl_fuzz_len;" "extern unsigned char *__afl_fuzz_ptr;" "unsigned char *__afl_fuzz_alt_ptr;"; cc_params[cc_par_cnt++] = "-D__AFL_FUZZ_TESTCASE_BUF=(__afl_fuzz_ptr ? __afl_fuzz_ptr : " "(__afl_fuzz_alt_ptr = malloc(1 * 1024 * 1024)))"; cc_params[cc_par_cnt++] = - "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? __afl_fuzz_len : read(0, " + "-D__AFL_FUZZ_TESTCASE_LEN=(__afl_fuzz_ptr ? *__afl_fuzz_len : read(0, " "__afl_fuzz_alt_ptr, 1 * 1024 * 1024))"; cc_params[cc_par_cnt++] = diff --git a/llvm_mode/afl-llvm-common.cc b/llvm_mode/afl-llvm-common.cc index 35eabbf0..6c7222cd 100644 --- a/llvm_mode/afl-llvm-common.cc +++ b/llvm_mode/afl-llvm-common.cc @@ -7,6 +7,7 @@ #include <stdlib.h> #include <unistd.h> #include <sys/time.h> +#include <fnmatch.h> #include <list> #include <string> @@ -152,12 +153,13 @@ bool isInWhitelist(llvm::Function *F) { /* 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. */ + * specified in the list. We also allow UNIX-style pattern + * matching */ + if (instFilename.str().length() >= it->length()) { - if (instFilename.str().compare( - instFilename.str().length() - it->length(), it->length(), - *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { return true; @@ -189,12 +191,13 @@ bool isInWhitelist(llvm::Function *F) { /* 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. */ + * specified in the list. We also allow UNIX-style pattern + * matching */ + if (instFilename.str().length() >= it->length()) { - if (instFilename.str().compare( - instFilename.str().length() - it->length(), it->length(), - *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { return true; diff --git a/llvm_mode/afl-llvm-lto-whitelist.so.cc b/llvm_mode/afl-llvm-lto-whitelist.so.cc index 8856ce21..33d40da8 100644 --- a/llvm_mode/afl-llvm-lto-whitelist.so.cc +++ b/llvm_mode/afl-llvm-lto-whitelist.so.cc @@ -36,6 +36,7 @@ #include <string> #include <fstream> #include <sys/time.h> +#include <fnmatch.h> #include "llvm/IR/DebugInfo.h" #include "llvm/IR/BasicBlock.h" @@ -175,9 +176,8 @@ bool AFLwhitelist::runOnModule(Module &M) { * specified in the list. */ if (instFilename.str().length() >= it->length()) { - if (instFilename.str().compare( - instFilename.str().length() - it->length(), it->length(), - *it) == 0) { + if (fnmatch(("*" + *it).c_str(), instFilename.str().c_str(), 0) == + 0) { instrumentFunction = true; break; diff --git a/llvm_mode/afl-llvm-rt.o.c b/llvm_mode/afl-llvm-rt.o.c index 3a0584e4..4bca3d37 100644 --- a/llvm_mode/afl-llvm-rt.o.c +++ b/llvm_mode/afl-llvm-rt.o.c @@ -74,10 +74,11 @@ u8 __afl_area_initial[MAP_INITIAL_SIZE]; #else u8 __afl_area_initial[MAP_SIZE]; #endif -u8 *__afl_area_ptr = __afl_area_initial; -u8 *__afl_dictionary; -u8 *__afl_fuzz_ptr; -u32 __afl_fuzz_len; +u8 * __afl_area_ptr = __afl_area_initial; +u8 * __afl_dictionary; +u8 * __afl_fuzz_ptr; +u32 __afl_fuzz_len_dummy; +u32 *__afl_fuzz_len = &__afl_fuzz_len_dummy; u32 __afl_final_loc; u32 __afl_map_size = MAP_SIZE; @@ -136,18 +137,18 @@ static void __afl_map_shm_fuzz() { } - __afl_fuzz_ptr = mmap(0, MAX_FILE, PROT_READ, MAP_SHARED, shm_fd, 0); + __afl_fuzz_len = (u32 *)mmap(0, MAX_FILE, PROT_READ, MAP_SHARED, shm_fd, 0); #else u32 shm_id = atoi(id_str); - __afl_fuzz_ptr = shmat(shm_id, NULL, 0); + __afl_fuzz_len = (u32 *)shmat(shm_id, NULL, 0); #endif /* Whooooops. */ - if (__afl_fuzz_ptr == (void *)-1) { + if (__afl_fuzz_len == (void *)-1) { fprintf(stderr, "Error: could not access fuzzing shared memory\n"); exit(1); @@ -164,6 +165,8 @@ static void __afl_map_shm_fuzz() { } + __afl_fuzz_ptr = (u8 *)(__afl_fuzz_len + sizeof(int)); + } /* SHM setup. */ @@ -420,7 +423,7 @@ static void __afl_start_snapshots(void) { } else { - // uh this forkserver master does not understand extended option passing + // uh this forkserver does not understand extended option passing // or does not want the dictionary if (!__afl_fuzz_ptr) already_read_first = 1; @@ -443,8 +446,31 @@ static void __afl_start_snapshots(void) { } - __afl_fuzz_len = (was_killed >> 8); - was_killed = (was_killed & 0xff); + #ifdef _AFL_DOCUMENT_MUTATIONS + if (__afl_fuzz_ptr) { + + static uint32_t counter = 0; + char fn[32]; + sprintf(fn, "%09u:forkserver", counter); + s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd_doc >= 0) { + + if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) { + + fprintf(stderr, "write of mutation file failed: %s\n", fn); + unlink(fn); + + } + + close(fd_doc); + + } + + counter++; + + } + + #endif /* If we stopped the child in persistent mode, but there was a race condition and afl-fuzz already issued SIGKILL, write off the old @@ -596,7 +622,7 @@ static void __afl_start_forkserver(void) { } else { - // uh this forkserver master does not understand extended option passing + // uh this forkserver does not understand extended option passing // or does not want the dictionary if (!__afl_fuzz_ptr) already_read_first = 1; @@ -620,8 +646,31 @@ static void __afl_start_forkserver(void) { } - __afl_fuzz_len = (was_killed >> 8); - was_killed = (was_killed & 0xff); +#ifdef _AFL_DOCUMENT_MUTATIONS + if (__afl_fuzz_ptr) { + + static uint32_t counter = 0; + char fn[32]; + sprintf(fn, "%09u:forkserver", counter); + s32 fd_doc = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd_doc >= 0) { + + if (write(fd_doc, __afl_fuzz_ptr, *__afl_fuzz_len) != *__afl_fuzz_len) { + + fprintf(stderr, "write of mutation file failed: %s\n", fn); + unlink(fn); + + } + + close(fd_doc); + + } + + counter++; + + } + +#endif /* If we stopped the child in persistent mode, but there was a race condition and afl-fuzz already issued SIGKILL, write off the old |