13cab2bb3Spatrick //===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===//
23cab2bb3Spatrick //
33cab2bb3Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
43cab2bb3Spatrick // See https://llvm.org/LICENSE.txt for license information.
53cab2bb3Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
63cab2bb3Spatrick //===----------------------------------------------------------------------===//
73cab2bb3Spatrick
83cab2bb3Spatrick /* This file allows to fuzz libFuzzer-style target functions
93cab2bb3Spatrick (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode.
103cab2bb3Spatrick
113cab2bb3Spatrick Usage:
123cab2bb3Spatrick ################################################################################
133cab2bb3Spatrick cat << EOF > test_fuzzer.cc
143cab2bb3Spatrick #include <stddef.h>
153cab2bb3Spatrick #include <stdint.h>
163cab2bb3Spatrick extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
173cab2bb3Spatrick if (size > 0 && data[0] == 'H')
183cab2bb3Spatrick if (size > 1 && data[1] == 'I')
193cab2bb3Spatrick if (size > 2 && data[2] == '!')
203cab2bb3Spatrick __builtin_trap();
213cab2bb3Spatrick return 0;
223cab2bb3Spatrick }
233cab2bb3Spatrick EOF
243cab2bb3Spatrick # Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang.
253cab2bb3Spatrick clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c
263cab2bb3Spatrick # Build afl-llvm-rt.o.c from the AFL distribution.
273cab2bb3Spatrick clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c
283cab2bb3Spatrick # Build this file, link it with afl-llvm-rt.o.o and the target code.
293cab2bb3Spatrick clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o
303cab2bb3Spatrick # Run AFL:
313cab2bb3Spatrick rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
323cab2bb3Spatrick $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
333cab2bb3Spatrick ################################################################################
343cab2bb3Spatrick AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
353cab2bb3Spatrick specified. If the file does not exist, it is created. This is useful for getting
363cab2bb3Spatrick stack traces (when using ASAN for example) or original error messages on hard
373cab2bb3Spatrick to reproduce bugs. Note that any content written to stderr will be written to
383cab2bb3Spatrick this file instead of stderr's usual location.
393cab2bb3Spatrick
403cab2bb3Spatrick AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option.
413cab2bb3Spatrick If 1, close stdout at startup. If 2 close stderr; if 3 close both.
423cab2bb3Spatrick
433cab2bb3Spatrick */
443cab2bb3Spatrick #include <assert.h>
453cab2bb3Spatrick #include <errno.h>
463cab2bb3Spatrick #include <stdarg.h>
473cab2bb3Spatrick #include <stdint.h>
483cab2bb3Spatrick #include <stdio.h>
493cab2bb3Spatrick #include <stdlib.h>
503cab2bb3Spatrick #include <string.h>
513cab2bb3Spatrick #include <unistd.h>
523cab2bb3Spatrick
533cab2bb3Spatrick #include <fstream>
543cab2bb3Spatrick #include <iostream>
553cab2bb3Spatrick #include <vector>
563cab2bb3Spatrick
573cab2bb3Spatrick // Platform detection. Copied from FuzzerInternal.h
583cab2bb3Spatrick #ifdef __linux__
593cab2bb3Spatrick #define LIBFUZZER_LINUX 1
603cab2bb3Spatrick #define LIBFUZZER_APPLE 0
613cab2bb3Spatrick #define LIBFUZZER_NETBSD 0
623cab2bb3Spatrick #define LIBFUZZER_FREEBSD 0
633cab2bb3Spatrick #elif __APPLE__
643cab2bb3Spatrick #define LIBFUZZER_LINUX 0
653cab2bb3Spatrick #define LIBFUZZER_APPLE 1
663cab2bb3Spatrick #define LIBFUZZER_NETBSD 0
673cab2bb3Spatrick #define LIBFUZZER_FREEBSD 0
683cab2bb3Spatrick #elif __NetBSD__
693cab2bb3Spatrick #define LIBFUZZER_LINUX 0
703cab2bb3Spatrick #define LIBFUZZER_APPLE 0
713cab2bb3Spatrick #define LIBFUZZER_NETBSD 1
723cab2bb3Spatrick #define LIBFUZZER_FREEBSD 0
733cab2bb3Spatrick #elif __FreeBSD__
743cab2bb3Spatrick #define LIBFUZZER_LINUX 0
753cab2bb3Spatrick #define LIBFUZZER_APPLE 0
763cab2bb3Spatrick #define LIBFUZZER_NETBSD 0
773cab2bb3Spatrick #define LIBFUZZER_FREEBSD 1
783cab2bb3Spatrick #else
793cab2bb3Spatrick #error "Support for your platform has not been implemented"
803cab2bb3Spatrick #endif
813cab2bb3Spatrick
823cab2bb3Spatrick // libFuzzer interface is thin, so we don't include any libFuzzer headers.
833cab2bb3Spatrick extern "C" {
843cab2bb3Spatrick int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
853cab2bb3Spatrick __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
863cab2bb3Spatrick }
873cab2bb3Spatrick
883cab2bb3Spatrick // Notify AFL about persistent mode.
893cab2bb3Spatrick static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
903cab2bb3Spatrick extern "C" int __afl_persistent_loop(unsigned int);
913cab2bb3Spatrick static volatile char suppress_warning2 = AFL_PERSISTENT[0];
923cab2bb3Spatrick
933cab2bb3Spatrick // Notify AFL about deferred forkserver.
943cab2bb3Spatrick static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
953cab2bb3Spatrick extern "C" void __afl_manual_init();
963cab2bb3Spatrick static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
973cab2bb3Spatrick
983cab2bb3Spatrick // Input buffer.
993cab2bb3Spatrick static const size_t kMaxAflInputSize = 1 << 20;
1003cab2bb3Spatrick static uint8_t AflInputBuf[kMaxAflInputSize];
1013cab2bb3Spatrick
1023cab2bb3Spatrick // Use this optionally defined function to output sanitizer messages even if
1033cab2bb3Spatrick // user asks to close stderr.
104*1f9cb04fSpatrick extern "C" __attribute__((weak)) void __sanitizer_set_report_fd(void *);
1053cab2bb3Spatrick
1063cab2bb3Spatrick // Keep track of where stderr content is being written to, so that
1073cab2bb3Spatrick // dup_and_close_stderr can use the correct one.
1083cab2bb3Spatrick static FILE *output_file = stderr;
1093cab2bb3Spatrick
1103cab2bb3Spatrick // Experimental feature to use afl_driver without AFL's deferred mode.
1113cab2bb3Spatrick // Needs to run before __afl_auto_init.
__decide_deferred_forkserver(void)1123cab2bb3Spatrick __attribute__((constructor(0))) static void __decide_deferred_forkserver(void) {
1133cab2bb3Spatrick if (getenv("AFL_DRIVER_DONT_DEFER")) {
1143cab2bb3Spatrick if (unsetenv("__AFL_DEFER_FORKSRV")) {
1153cab2bb3Spatrick perror("Failed to unset __AFL_DEFER_FORKSRV");
1163cab2bb3Spatrick abort();
1173cab2bb3Spatrick }
1183cab2bb3Spatrick }
1193cab2bb3Spatrick }
1203cab2bb3Spatrick
1213cab2bb3Spatrick // If the user asks us to duplicate stderr, then do it.
maybe_duplicate_stderr()1223cab2bb3Spatrick static void maybe_duplicate_stderr() {
1233cab2bb3Spatrick char *stderr_duplicate_filename =
1243cab2bb3Spatrick getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
1253cab2bb3Spatrick
1263cab2bb3Spatrick if (!stderr_duplicate_filename)
1273cab2bb3Spatrick return;
1283cab2bb3Spatrick
1293cab2bb3Spatrick FILE *stderr_duplicate_stream =
1303cab2bb3Spatrick freopen(stderr_duplicate_filename, "a+", stderr);
1313cab2bb3Spatrick
1323cab2bb3Spatrick if (!stderr_duplicate_stream) {
1333cab2bb3Spatrick fprintf(
1343cab2bb3Spatrick stderr,
1353cab2bb3Spatrick "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
1363cab2bb3Spatrick abort();
1373cab2bb3Spatrick }
1383cab2bb3Spatrick output_file = stderr_duplicate_stream;
1393cab2bb3Spatrick }
1403cab2bb3Spatrick
1413cab2bb3Spatrick // Most of these I/O functions were inspired by/copied from libFuzzer's code.
discard_output(int fd)1423cab2bb3Spatrick static void discard_output(int fd) {
1433cab2bb3Spatrick FILE *temp = fopen("/dev/null", "w");
1443cab2bb3Spatrick if (!temp)
1453cab2bb3Spatrick abort();
1463cab2bb3Spatrick dup2(fileno(temp), fd);
1473cab2bb3Spatrick fclose(temp);
1483cab2bb3Spatrick }
1493cab2bb3Spatrick
close_stdout()1503cab2bb3Spatrick static void close_stdout() { discard_output(STDOUT_FILENO); }
1513cab2bb3Spatrick
1523cab2bb3Spatrick // Prevent the targeted code from writing to "stderr" but allow sanitizers and
1533cab2bb3Spatrick // this driver to do so.
dup_and_close_stderr()1543cab2bb3Spatrick static void dup_and_close_stderr() {
1553cab2bb3Spatrick int output_fileno = fileno(output_file);
1563cab2bb3Spatrick int output_fd = dup(output_fileno);
1573cab2bb3Spatrick if (output_fd <= 0)
1583cab2bb3Spatrick abort();
1593cab2bb3Spatrick FILE *new_output_file = fdopen(output_fd, "w");
1603cab2bb3Spatrick if (!new_output_file)
1613cab2bb3Spatrick abort();
1623cab2bb3Spatrick if (!__sanitizer_set_report_fd)
1633cab2bb3Spatrick return;
1643cab2bb3Spatrick __sanitizer_set_report_fd(reinterpret_cast<void *>(output_fd));
1653cab2bb3Spatrick discard_output(output_fileno);
1663cab2bb3Spatrick }
1673cab2bb3Spatrick
Printf(const char * Fmt,...)1683cab2bb3Spatrick static void Printf(const char *Fmt, ...) {
1693cab2bb3Spatrick va_list ap;
1703cab2bb3Spatrick va_start(ap, Fmt);
1713cab2bb3Spatrick vfprintf(output_file, Fmt, ap);
1723cab2bb3Spatrick va_end(ap);
1733cab2bb3Spatrick fflush(output_file);
1743cab2bb3Spatrick }
1753cab2bb3Spatrick
1763cab2bb3Spatrick // Close stdout and/or stderr if user asks for it.
maybe_close_fd_mask()1773cab2bb3Spatrick static void maybe_close_fd_mask() {
1783cab2bb3Spatrick char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK");
1793cab2bb3Spatrick if (!fd_mask_str)
1803cab2bb3Spatrick return;
1813cab2bb3Spatrick int fd_mask = atoi(fd_mask_str);
1823cab2bb3Spatrick if (fd_mask & 2)
1833cab2bb3Spatrick dup_and_close_stderr();
1843cab2bb3Spatrick if (fd_mask & 1)
1853cab2bb3Spatrick close_stdout();
1863cab2bb3Spatrick }
1873cab2bb3Spatrick
1883cab2bb3Spatrick // Define LLVMFuzzerMutate to avoid link failures for targets that use it
1893cab2bb3Spatrick // with libFuzzer's LLVMFuzzerCustomMutator.
LLVMFuzzerMutate(uint8_t * Data,size_t Size,size_t MaxSize)1903cab2bb3Spatrick extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
1913cab2bb3Spatrick assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
1923cab2bb3Spatrick return 0;
1933cab2bb3Spatrick }
1943cab2bb3Spatrick
1953cab2bb3Spatrick // Execute any files provided as parameters.
ExecuteFilesOnyByOne(int argc,char ** argv)1963cab2bb3Spatrick static int ExecuteFilesOnyByOne(int argc, char **argv) {
1973cab2bb3Spatrick for (int i = 1; i < argc; i++) {
1983cab2bb3Spatrick std::ifstream in(argv[i], std::ios::binary);
1993cab2bb3Spatrick in.seekg(0, in.end);
2003cab2bb3Spatrick size_t length = in.tellg();
2013cab2bb3Spatrick in.seekg (0, in.beg);
2023cab2bb3Spatrick std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
2033cab2bb3Spatrick // Allocate exactly length bytes so that we reliably catch buffer overflows.
2043cab2bb3Spatrick std::vector<char> bytes(length);
2053cab2bb3Spatrick in.read(bytes.data(), bytes.size());
2063cab2bb3Spatrick assert(in);
2073cab2bb3Spatrick LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes.data()),
2083cab2bb3Spatrick bytes.size());
2093cab2bb3Spatrick std::cout << "Execution successful" << std::endl;
2103cab2bb3Spatrick }
2113cab2bb3Spatrick return 0;
2123cab2bb3Spatrick }
2133cab2bb3Spatrick
main(int argc,char ** argv)2143cab2bb3Spatrick int main(int argc, char **argv) {
2153cab2bb3Spatrick Printf(
2163cab2bb3Spatrick "======================= INFO =========================\n"
2173cab2bb3Spatrick "This binary is built for AFL-fuzz.\n"
2183cab2bb3Spatrick "To run the target function on individual input(s) execute this:\n"
2193cab2bb3Spatrick " %s < INPUT_FILE\n"
2203cab2bb3Spatrick "or\n"
2213cab2bb3Spatrick " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
2223cab2bb3Spatrick "To fuzz with afl-fuzz execute this:\n"
2233cab2bb3Spatrick " afl-fuzz [afl-flags] %s [-N]\n"
2243cab2bb3Spatrick "afl-fuzz will run N iterations before "
2253cab2bb3Spatrick "re-spawning the process (default: 1000)\n"
2263cab2bb3Spatrick "======================================================\n",
2273cab2bb3Spatrick argv[0], argv[0], argv[0]);
2283cab2bb3Spatrick
2293cab2bb3Spatrick maybe_duplicate_stderr();
2303cab2bb3Spatrick maybe_close_fd_mask();
2313cab2bb3Spatrick if (LLVMFuzzerInitialize)
2323cab2bb3Spatrick LLVMFuzzerInitialize(&argc, &argv);
2333cab2bb3Spatrick // Do any other expensive one-time initialization here.
2343cab2bb3Spatrick
2353cab2bb3Spatrick if (!getenv("AFL_DRIVER_DONT_DEFER"))
2363cab2bb3Spatrick __afl_manual_init();
2373cab2bb3Spatrick
2383cab2bb3Spatrick int N = 1000;
2393cab2bb3Spatrick if (argc == 2 && argv[1][0] == '-')
2403cab2bb3Spatrick N = atoi(argv[1] + 1);
2413cab2bb3Spatrick else if(argc == 2 && (N = atoi(argv[1])) > 0)
2423cab2bb3Spatrick Printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
2433cab2bb3Spatrick else if (argc > 1)
2443cab2bb3Spatrick return ExecuteFilesOnyByOne(argc, argv);
2453cab2bb3Spatrick
2463cab2bb3Spatrick assert(N > 0);
2473cab2bb3Spatrick
2483cab2bb3Spatrick // Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
2493cab2bb3Spatrick // on the first execution of LLVMFuzzerTestOneInput is ignored.
2503cab2bb3Spatrick uint8_t dummy_input[1] = {0};
2513cab2bb3Spatrick LLVMFuzzerTestOneInput(dummy_input, 1);
2523cab2bb3Spatrick
2533cab2bb3Spatrick int num_runs = 0;
2543cab2bb3Spatrick while (__afl_persistent_loop(N)) {
2553cab2bb3Spatrick ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
2563cab2bb3Spatrick if (n_read > 0) {
2573cab2bb3Spatrick // Copy AflInputBuf into a separate buffer to let asan find buffer
2583cab2bb3Spatrick // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
2593cab2bb3Spatrick uint8_t *copy = new uint8_t[n_read];
2603cab2bb3Spatrick memcpy(copy, AflInputBuf, n_read);
2613cab2bb3Spatrick num_runs++;
2623cab2bb3Spatrick LLVMFuzzerTestOneInput(copy, n_read);
2633cab2bb3Spatrick delete[] copy;
2643cab2bb3Spatrick }
2653cab2bb3Spatrick }
2663cab2bb3Spatrick Printf("%s: successfully executed %d input(s)\n", argv[0], num_runs);
2673cab2bb3Spatrick }
268