1de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===- afl_driver.cpp - a glue between AFL and libFuzzer --------*- C++ -* ===// 2de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 3de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// The LLVM Compiler Infrastructure 4de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// 5de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// This file is distributed under the University of Illinois Open Source 6de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// License. See LICENSE.TXT for details. 7de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar//===----------------------------------------------------------------------===// 8de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 9de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar/* This file allows to fuzz libFuzzer-style target functions 10de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar (LLVMFuzzerTestOneInput) with AFL using AFL's persistent (in-process) mode. 11de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 12de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarUsage: 13de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar################################################################################ 14de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarcat << EOF > test_fuzzer.cc 15de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdint.h> 16de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stddef.h> 17de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { 18de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (size > 0 && data[0] == 'H') 19de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (size > 1 && data[1] == 'I') 20de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (size > 2 && data[2] == '!') 21de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar __builtin_trap(); 22de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return 0; 23de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 24de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarEOF 25de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Build your target with -fsanitize-coverage=trace-pc using fresh clang. 26de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclang -g -fsanitize-coverage=trace-pc test_fuzzer.cc -c 27de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Build afl-llvm-rt.o.c from the AFL distribution. 28de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c 29de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Build this file, link it with afl-llvm-rt.o.o and the target code. 30de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarclang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o 31de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar# Run AFL: 32de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarrm -rf IN OUT; mkdir IN OUT; echo z > IN/z; 33de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar$AFL_HOME/afl-fuzz -i IN -o OUT ./a.out 34de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar################################################################################ 35de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarEnvironment Variables: 36de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarThere are a few environment variables that can be set to use features that 37de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarafl-fuzz doesn't have. 38de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 39de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarAFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file 40de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarspecified. If the file does not exist, it is created. This is useful for getting 41de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstack traces (when using ASAN for example) or original error messages on hard to 42de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarreproduce bugs. 43de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 44de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga NainarAFL_DRIVER_EXTRA_STATS_FILENAME: Setting this causes afl_driver to write extra 45de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatistics to the file specified. Currently these are peak_rss_mb 46de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar(the peak amount of virtual memory used in MB) and slowest_unit_time_secs. If 47de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarthe file does not exist it is created. If the file does exist then 48de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarafl_driver assumes it was restarted by afl-fuzz and will try to read old 49de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatistics from the file. If that fails then the process will quit. 50de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 51de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar*/ 52de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <assert.h> 53de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdio.h> 54de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdint.h> 55de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <stdlib.h> 56de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <string.h> 57de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <unistd.h> 58de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <errno.h> 59de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <signal.h> 60de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <sys/resource.h> 61de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#include <sys/time.h> 62de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Platform detection. Copied from FuzzerInternal.h 63de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#ifdef __linux__ 64de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_LINUX 1 65de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_APPLE 0 66de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#elif __APPLE__ 67de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_LINUX 0 68de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define LIBFUZZER_APPLE 1 69de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#else 70de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#error "Support for your platform has not been implemented" 71de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#endif 72de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 73de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Used to avoid repeating error checking boilerplate. If cond is false, a 74de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// fatal error has occured in the program. In this event print error_message 75de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// to stderr and abort(). Otherwise do nothing. Note that setting 76de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended 77de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// to the file as well, if the error occurs after the duplication is performed. 78de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar#define CHECK_ERROR(cond, error_message) \ 79de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!(cond)) { \ 80de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar fprintf(stderr, (error_message)); \ 81de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar abort(); \ 82de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 83de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 84de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// libFuzzer interface is thin, so we don't include any libFuzzer headers. 85de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" { 86de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarint LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size); 87de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar__attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv); 88de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 89de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 90de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Notify AFL about persistent mode. 91de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##"; 92de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" int __afl_persistent_loop(unsigned int); 93de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char suppress_warning2 = AFL_PERSISTENT[0]; 94de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 95de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Notify AFL about deferred forkserver. 96de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##"; 97de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarextern "C" void __afl_manual_init(); 98de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0]; 99de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 100de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Input buffer. 101de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const size_t kMaxAflInputSize = 1 << 20; 102de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic uint8_t AflInputBuf[kMaxAflInputSize]; 103de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 104de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Variables we need for writing to the extra stats file. 105de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic FILE *extra_stats_file = NULL; 106de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic uint32_t previous_peak_rss = 0; 107de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic time_t slowest_unit_time_secs = 0; 108de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const int kNumExtraStats = 2; 109de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic const char *kExtraStatsFormatString = "peak_rss_mb : %u\n" 110de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "slowest_unit_time_sec : %u\n"; 111de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 112de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Copied from FuzzerUtil.cpp. 113de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarsize_t GetPeakRSSMb() { 114de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar struct rusage usage; 115de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (getrusage(RUSAGE_SELF, &usage)) 116de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return 0; 117de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (LIBFUZZER_LINUX) { 118de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // ru_maxrss is in KiB 119de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return usage.ru_maxrss >> 10; 120de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else if (LIBFUZZER_APPLE) { 121de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // ru_maxrss is in bytes 122de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return usage.ru_maxrss >> 20; 123de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 124de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(0 && "GetPeakRSSMb() is not implemented for your platform"); 125de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return 0; 126de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 127de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 128de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Based on SetSigaction in FuzzerUtil.cpp 129de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void SetSigaction(int signum, 130de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar void (*callback)(int, siginfo_t *, void *)) { 131de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar struct sigaction sigact; 132de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memset(&sigact, 0, sizeof(sigact)); 133de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar sigact.sa_sigaction = callback; 134de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (sigaction(signum, &sigact, 0)) { 135de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno); 136de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar exit(1); 137de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 138de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 139de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 140de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Write extra stats to the file specified by the user. If none is specified 141de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// this function will never be called. 142de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void write_extra_stats() { 143de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint32_t peak_rss = GetPeakRSSMb(); 144de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 145de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (peak_rss < previous_peak_rss) 146de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar peak_rss = previous_peak_rss; 147de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 148de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString, 149de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar peak_rss, slowest_unit_time_secs); 150de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 151de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file"); 152de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 153de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(fclose(extra_stats_file) == 0, 154de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Failed to close extra_stats_file"); 155de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 156de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 157de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Call write_extra_stats before we exit. 158de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void crash_handler(int, siginfo_t *, void *) { 159de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Make sure we don't try calling write_extra_stats again if we crashed while 160de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // trying to call it. 161de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar static bool first_crash = true; 162de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(first_crash, 163de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Crashed in crash signal handler. This is a bug in the fuzzer."); 164de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 165de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar first_crash = false; 166de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar write_extra_stats(); 167de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 168de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 169de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// If the user has specified an extra_stats_file through the environment 170de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up 171de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// to write stats to it on exit. If no file is specified, do nothing. Otherwise 172de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// install signal and exit handlers to write to the file when the process exits. 173de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// Then if the file doesn't exist create it and set extra stats to 0. But if it 174de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// does exist then read the initial values of the extra stats from the file 175de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// and check that the file is writable. 176de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void maybe_initialize_extra_stats() { 177de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do. 178de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME"); 179de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!extra_stats_filename) 180de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return; 181de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 182de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Open the file and find the previous peak_rss_mb value. 183de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // This is necessary because the fuzzing process is restarted after N 184de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // iterations are completed. So we may need to get this value from a previous 185de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // process to be accurate. 186de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar extra_stats_file = fopen(extra_stats_filename, "r"); 187de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 188de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // If extra_stats_file already exists: read old stats from it. 189de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (extra_stats_file) { 190de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int matches = fscanf(extra_stats_file, kExtraStatsFormatString, 191de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar &previous_peak_rss, &slowest_unit_time_secs); 192de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 193de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Make sure we have read a real extra stats file and that we have used it 194de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // to set slowest_unit_time_secs and previous_peak_rss. 195de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt"); 196de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 197de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file"); 198de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 199de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Now open the file for writing. 200de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar extra_stats_file = fopen(extra_stats_filename, "w"); 201de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(extra_stats_file, 202de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Failed to open extra stats file for writing"); 203de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } else { 204de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Looks like this is the first time in a fuzzing job this is being called. 205de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar extra_stats_file = fopen(extra_stats_filename, "w+"); 206de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(extra_stats_file, "failed to create extra stats file"); 207de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 208de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 209de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Make sure that crash_handler gets called on any kind of fatal error. 210de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE, SIGINT, 211de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SIGTERM}; 212de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 213de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]); 214de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 215de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar for (size_t idx = 0; idx < num_signals; idx++) 216de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar SetSigaction(crash_signals[idx], crash_handler); 217de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 218de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Make sure it gets called on other kinds of exits. 219de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar atexit(write_extra_stats); 220de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 221de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 222de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar// If the user asks us to duplicate stderr, then do it. 223de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarstatic void maybe_duplicate_stderr() { 224de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar char* stderr_duplicate_filename = 225de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); 226de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 227de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!stderr_duplicate_filename) 228de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar return; 229de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 230de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar FILE* stderr_duplicate_stream = 231de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar freopen(stderr_duplicate_filename, "a+", stderr); 232de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 233de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (!stderr_duplicate_stream) { 234de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar fprintf( 235de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar stderr, 236de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME"); 237de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar abort(); 238de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 239de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 240de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 241de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainarint main(int argc, char **argv) { 242de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar fprintf(stderr, "Running in AFl-fuzz mode\nUsage:\n" 243de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "afl-fuzz [afl-flags] %s [N] " 244de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "-- run N fuzzing iterations before " 245de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "re-spawning the process (default: 1000)\n", 246de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar argv[0]); 247de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (LLVMFuzzerInitialize) 248de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LLVMFuzzerInitialize(&argc, &argv); 249de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Do any other expensive one-time initialization here. 250de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 251de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar maybe_duplicate_stderr(); 252de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar maybe_initialize_extra_stats(); 253de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 254de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar __afl_manual_init(); 255de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 256de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar int N = 1000; 257de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (argc >= 2) 258de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar N = atoi(argv[1]); 259de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar assert(N > 0); 260de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar time_t unit_time_secs; 261de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar while (__afl_persistent_loop(N)) { 262de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize); 263de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (n_read > 0) { 264de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Copy AflInputBuf into a separate buffer to let asan find buffer 265de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // overflows. Don't use unique_ptr/etc to avoid extra dependencies. 266de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar uint8_t *copy = new uint8_t[n_read]; 267de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar memcpy(copy, AflInputBuf, n_read); 268de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 269de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar struct timeval unit_start_time; 270de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0, 271de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Calling gettimeofday failed"); 272de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 273de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar LLVMFuzzerTestOneInput(copy, n_read); 274de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 275de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar struct timeval unit_stop_time; 276de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0, 277de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar "Calling gettimeofday failed"); 278de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 279de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar // Update slowest_unit_time_secs if we see a new max. 280de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec; 281de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar if (slowest_unit_time_secs < unit_time_secs) 282de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar slowest_unit_time_secs = unit_time_secs; 283de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar 284de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar delete[] copy; 285de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 286de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar } 287de2d8694e25a814696358e95141f4b1aa4d8847ePirama Arumuga Nainar} 288