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