OSDN Git Service

Sort the remaining #include lines in include/... and lib/....
[android-x86/external-llvm.git] / lib / Fuzzer / afl / afl_driver.cpp
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 <stddef.h>
16 #include <stdint.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 <errno.h>
54 #include <signal.h>
55 #include <stdint.h>
56 #include <stdio.h>
57 #include <stdlib.h>
58 #include <string.h>
59 #include <sys/resource.h>
60 #include <sys/time.h>
61 #include <unistd.h>
62
63 #include <fstream>
64 #include <iostream>
65 #include <vector>
66
67 // Platform detection. Copied from FuzzerInternal.h
68 #ifdef __linux__
69 #define LIBFUZZER_LINUX 1
70 #define LIBFUZZER_APPLE 0
71 #elif __APPLE__
72 #define LIBFUZZER_LINUX 0
73 #define LIBFUZZER_APPLE 1
74 #else
75 #error "Support for your platform has not been implemented"
76 #endif
77
78 // Used to avoid repeating error checking boilerplate. If cond is false, a
79 // fatal error has occured in the program. In this event print error_message
80 // to stderr and abort(). Otherwise do nothing. Note that setting
81 // AFL_DRIVER_STDERR_DUPLICATE_FILENAME may cause error_message to be appended
82 // to the file as well, if the error occurs after the duplication is performed.
83 #define CHECK_ERROR(cond, error_message)                                       \
84   if (!(cond)) {                                                               \
85     fprintf(stderr, (error_message));                                          \
86     abort();                                                                   \
87   }
88
89 // libFuzzer interface is thin, so we don't include any libFuzzer headers.
90 extern "C" {
91 int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size);
92 __attribute__((weak)) int LLVMFuzzerInitialize(int *argc, char ***argv);
93 }
94
95 // Notify AFL about persistent mode.
96 static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
97 extern "C" int __afl_persistent_loop(unsigned int);
98 static volatile char suppress_warning2 = AFL_PERSISTENT[0];
99
100 // Notify AFL about deferred forkserver.
101 static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
102 extern "C" void  __afl_manual_init();
103 static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
104
105 // Input buffer.
106 static const size_t kMaxAflInputSize = 1 << 20;
107 static uint8_t AflInputBuf[kMaxAflInputSize];
108
109 // Variables we need for writing to the extra stats file.
110 static FILE *extra_stats_file = NULL;
111 static uint32_t previous_peak_rss = 0;
112 static time_t slowest_unit_time_secs = 0;
113 static const int kNumExtraStats = 2;
114 static const char *kExtraStatsFormatString = "peak_rss_mb            : %u\n"
115                                              "slowest_unit_time_sec  : %u\n";
116
117 // Copied from FuzzerUtil.cpp.
118 size_t GetPeakRSSMb() {
119   struct rusage usage;
120   if (getrusage(RUSAGE_SELF, &usage))
121     return 0;
122   if (LIBFUZZER_LINUX) {
123     // ru_maxrss is in KiB
124     return usage.ru_maxrss >> 10;
125   } else if (LIBFUZZER_APPLE) {
126     // ru_maxrss is in bytes
127     return usage.ru_maxrss >> 20;
128   }
129   assert(0 && "GetPeakRSSMb() is not implemented for your platform");
130   return 0;
131 }
132
133 // Based on SetSigaction in FuzzerUtil.cpp
134 static void SetSigaction(int signum,
135                          void (*callback)(int, siginfo_t *, void *)) {
136   struct sigaction sigact;
137   memset(&sigact, 0, sizeof(sigact));
138   sigact.sa_sigaction = callback;
139   if (sigaction(signum, &sigact, 0)) {
140     fprintf(stderr, "libFuzzer: sigaction failed with %d\n", errno);
141     exit(1);
142   }
143 }
144
145 // Write extra stats to the file specified by the user. If none is specified
146 // this function will never be called.
147 static void write_extra_stats() {
148   uint32_t peak_rss = GetPeakRSSMb();
149
150   if (peak_rss < previous_peak_rss)
151     peak_rss = previous_peak_rss;
152
153   int chars_printed = fprintf(extra_stats_file, kExtraStatsFormatString,
154                               peak_rss, slowest_unit_time_secs);
155
156   CHECK_ERROR(chars_printed != 0, "Failed to write extra_stats_file");
157
158   CHECK_ERROR(fclose(extra_stats_file) == 0,
159               "Failed to close extra_stats_file");
160 }
161
162 // Call write_extra_stats before we exit.
163 static void crash_handler(int, siginfo_t *, void *) {
164   // Make sure we don't try calling write_extra_stats again if we crashed while
165   // trying to call it.
166   static bool first_crash = true;
167   CHECK_ERROR(first_crash,
168               "Crashed in crash signal handler. This is a bug in the fuzzer.");
169
170   first_crash = false;
171   write_extra_stats();
172 }
173
174 // If the user has specified an extra_stats_file through the environment
175 // variable AFL_DRIVER_EXTRA_STATS_FILENAME, then perform necessary set up
176 // to write stats to it on exit. If no file is specified, do nothing. Otherwise
177 // install signal and exit handlers to write to the file when the process exits.
178 // Then if the file doesn't exist create it and set extra stats to 0. But if it
179 // does exist then read the initial values of the extra stats from the file
180 // and check that the file is writable.
181 static void maybe_initialize_extra_stats() {
182   // If AFL_DRIVER_EXTRA_STATS_FILENAME isn't set then we have nothing to do.
183   char *extra_stats_filename = getenv("AFL_DRIVER_EXTRA_STATS_FILENAME");
184   if (!extra_stats_filename)
185     return;
186
187   // Open the file and find the previous peak_rss_mb value.
188   // This is necessary because the fuzzing process is restarted after N
189   // iterations are completed. So we may need to get this value from a previous
190   // process to be accurate.
191   extra_stats_file = fopen(extra_stats_filename, "r");
192
193   // If extra_stats_file already exists: read old stats from it.
194   if (extra_stats_file) {
195     int matches = fscanf(extra_stats_file, kExtraStatsFormatString,
196                          &previous_peak_rss, &slowest_unit_time_secs);
197
198     // Make sure we have read a real extra stats file and that we have used it
199     // to set slowest_unit_time_secs and previous_peak_rss.
200     CHECK_ERROR(matches == kNumExtraStats, "Extra stats file is corrupt");
201
202     CHECK_ERROR(fclose(extra_stats_file) == 0, "Failed to close file");
203
204     // Now open the file for writing.
205     extra_stats_file = fopen(extra_stats_filename, "w");
206     CHECK_ERROR(extra_stats_file,
207                 "Failed to open extra stats file for writing");
208   } else {
209     // Looks like this is the first time in a fuzzing job this is being called.
210     extra_stats_file = fopen(extra_stats_filename, "w+");
211     CHECK_ERROR(extra_stats_file, "failed to create extra stats file");
212   }
213
214   // Make sure that crash_handler gets called on any kind of fatal error.
215   int crash_signals[] = {SIGSEGV, SIGBUS, SIGABRT, SIGILL, SIGFPE,  SIGINT,
216                          SIGTERM};
217
218   const size_t num_signals = sizeof(crash_signals) / sizeof(crash_signals[0]);
219
220   for (size_t idx = 0; idx < num_signals; idx++)
221     SetSigaction(crash_signals[idx], crash_handler);
222
223   // Make sure it gets called on other kinds of exits.
224   atexit(write_extra_stats);
225 }
226
227 // If the user asks us to duplicate stderr, then do it.
228 static void maybe_duplicate_stderr() {
229   char* stderr_duplicate_filename =
230       getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
231
232   if (!stderr_duplicate_filename)
233     return;
234
235   FILE* stderr_duplicate_stream =
236       freopen(stderr_duplicate_filename, "a+", stderr);
237
238   if (!stderr_duplicate_stream) {
239     fprintf(
240         stderr,
241         "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
242     abort();
243   }
244 }
245
246 // Define LLVMFuzzerMutate to avoid link failures for targets that use it
247 // with libFuzzer's LLVMFuzzerCustomMutator.
248 extern "C" size_t LLVMFuzzerMutate(uint8_t *Data, size_t Size, size_t MaxSize) {
249   assert(false && "LLVMFuzzerMutate should not be called from afl_driver");
250   return 0;
251 }
252
253 // Execute any files provided as parameters.
254 int ExecuteFilesOnyByOne(int argc, char **argv) {
255   for (int i = 1; i < argc; i++) {
256     std::ifstream in(argv[i]);
257     in.seekg(0, in.end);
258     size_t length = in.tellg();
259     in.seekg (0, in.beg);
260     std::cout << "Reading " << length << " bytes from " << argv[i] << std::endl;
261     // Allocate exactly length bytes so that we reliably catch buffer overflows.
262     std::vector<char> bytes(length);
263     in.read(bytes.data(), bytes.size());
264     assert(in);
265     LLVMFuzzerTestOneInput(reinterpret_cast<const uint8_t *>(bytes.data()),
266                            bytes.size());
267     std::cout << "Execution successfull" << std::endl;
268   }
269   return 0;
270 }
271
272 int main(int argc, char **argv) {
273   fprintf(stderr,
274       "======================= INFO =========================\n"
275       "This binary is built for AFL-fuzz.\n"
276       "To run the target function on individual input(s) execute this:\n"
277       "  %s < INPUT_FILE\n"
278       "or\n"
279       "  %s INPUT_FILE1 [INPUT_FILE2 ... ]\n"
280       "To fuzz with afl-fuzz execute this:\n"
281       "  afl-fuzz [afl-flags] %s [-N]\n"
282       "afl-fuzz will run N iterations before "
283       "re-spawning the process (default: 1000)\n"
284       "======================================================\n",
285           argv[0], argv[0], argv[0]);
286   if (LLVMFuzzerInitialize)
287     LLVMFuzzerInitialize(&argc, &argv);
288   // Do any other expensive one-time initialization here.
289
290   maybe_duplicate_stderr();
291   maybe_initialize_extra_stats();
292
293   __afl_manual_init();
294
295   int N = 1000;
296   if (argc == 2 && argv[1][0] == '-')
297       N = atoi(argv[1] + 1);
298   else if(argc == 2 && (N = atoi(argv[1])) > 0)
299       fprintf(stderr, "WARNING: using the deprecated call style `%s %d`\n",
300               argv[0], N);
301   else if (argc > 1)
302     return ExecuteFilesOnyByOne(argc, argv);
303
304   assert(N > 0);
305   time_t unit_time_secs;
306   int num_runs = 0;
307   while (__afl_persistent_loop(N)) {
308     ssize_t n_read = read(0, AflInputBuf, kMaxAflInputSize);
309     if (n_read > 0) {
310       // Copy AflInputBuf into a separate buffer to let asan find buffer
311       // overflows. Don't use unique_ptr/etc to avoid extra dependencies.
312       uint8_t *copy = new uint8_t[n_read];
313       memcpy(copy, AflInputBuf, n_read);
314
315       struct timeval unit_start_time;
316       CHECK_ERROR(gettimeofday(&unit_start_time, NULL) == 0,
317                   "Calling gettimeofday failed");
318
319       num_runs++;
320       LLVMFuzzerTestOneInput(copy, n_read);
321
322       struct timeval unit_stop_time;
323       CHECK_ERROR(gettimeofday(&unit_stop_time, NULL) == 0,
324                   "Calling gettimeofday failed");
325
326       // Update slowest_unit_time_secs if we see a new max.
327       unit_time_secs = unit_stop_time.tv_sec - unit_start_time.tv_sec;
328       if (slowest_unit_time_secs < unit_time_secs)
329         slowest_unit_time_secs = unit_time_secs;
330
331       delete[] copy;
332     }
333   }
334   fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs);
335 }