1 /*
2    american fuzzy lop - test case minimizer
3    ----------------------------------------
4 
5    Written and maintained by Michal Zalewski <lcamtuf@google.com>
6 
7    Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
8 
9    Licensed under the Apache License, Version 2.0 (the "License");
10    you may not use this file except in compliance with the License.
11    You may obtain a copy of the License at:
12 
13      http://www.apache.org/licenses/LICENSE-2.0
14 
15    A simple test case minimizer that takes an input file and tries to remove
16    as much data as possible while keeping the binary in a crashing state
17    *or* producing consistent instrumentation output (the mode is auto-selected
18    based on the initially observed behavior).
19 
20  */
21 
22 #define AFL_MAIN
23 
24 #include "config.h"
25 #include "types.h"
26 #include "debug.h"
27 #include "alloc-inl.h"
28 #include "hash.h"
29 
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <time.h>
35 #include <errno.h>
36 #include <signal.h>
37 #include <dirent.h>
38 #include <fcntl.h>
39 
40 #include <sys/wait.h>
41 #include <sys/time.h>
42 #include <sys/shm.h>
43 #include <sys/stat.h>
44 #include <sys/types.h>
45 #include <sys/resource.h>
46 
47 static s32 child_pid;                 /* PID of the tested program         */
48 
49 static u8 *trace_bits,                /* SHM with instrumentation bitmap   */
50           *mask_bitmap;               /* Mask for trace bits (-B)          */
51 
52 static u8 *in_file,                   /* Minimizer input test case         */
53           *out_file,                  /* Minimizer output file             */
54           *prog_in,                   /* Targeted program input file       */
55           *target_path,               /* Path to target binary             */
56           *doc_path;                  /* Path to docs                      */
57 
58 static u8* in_data;                   /* Input data for trimming           */
59 
60 static u32 in_len,                    /* Input data length                 */
61            orig_cksum,                /* Original checksum                 */
62            total_execs,               /* Total number of execs             */
63            missed_hangs,              /* Misses due to hangs               */
64            missed_crashes,            /* Misses due to crashes             */
65            missed_paths,              /* Misses due to exec path diffs     */
66            exec_tmout = EXEC_TIMEOUT; /* Exec timeout (ms)                 */
67 
68 static u64 mem_limit = MEM_LIMIT;     /* Memory limit (MB)                 */
69 
70 static s32 shm_id,                    /* ID of the SHM region              */
71            dev_null_fd = -1;          /* FD to /dev/null                   */
72 
73 static u8  crash_mode,                /* Crash-centric mode?               */
74            exit_crash,                /* Treat non-zero exit as crash?     */
75            edges_only,                /* Ignore hit counts?                */
76            exact_mode,                /* Require path match for crashes?   */
77            use_stdin = 1;             /* Use stdin for program input?      */
78 
79 static volatile u8
80            stop_soon,                 /* Ctrl-C pressed?                   */
81            child_timed_out;           /* Child timed out?                  */
82 
83 
84 /* Classify tuple counts. This is a slow & naive version, but good enough here. */
85 
86 static const u8 count_class_lookup[256] = {
87 
88   [0]           = 0,
89   [1]           = 1,
90   [2]           = 2,
91   [3]           = 4,
92   [4 ... 7]     = 8,
93   [8 ... 15]    = 16,
94   [16 ... 31]   = 32,
95   [32 ... 127]  = 64,
96   [128 ... 255] = 128
97 
98 };
99 
classify_counts(u8 * mem)100 static void classify_counts(u8* mem) {
101 
102   u32 i = MAP_SIZE;
103 
104   if (edges_only) {
105 
106     while (i--) {
107       if (*mem) *mem = 1;
108       mem++;
109     }
110 
111   } else {
112 
113     while (i--) {
114       *mem = count_class_lookup[*mem];
115       mem++;
116     }
117 
118   }
119 
120 }
121 
122 
123 /* Apply mask to classified bitmap (if set). */
124 
apply_mask(u32 * mem,u32 * mask)125 static void apply_mask(u32* mem, u32* mask) {
126 
127   u32 i = (MAP_SIZE >> 2);
128 
129   if (!mask) return;
130 
131   while (i--) {
132 
133     *mem &= ~*mask;
134     mem++;
135     mask++;
136 
137   }
138 
139 }
140 
141 
142 /* See if any bytes are set in the bitmap. */
143 
anything_set(void)144 static inline u8 anything_set(void) {
145 
146   u32* ptr = (u32*)trace_bits;
147   u32  i   = (MAP_SIZE >> 2);
148 
149   while (i--) if (*(ptr++)) return 1;
150 
151   return 0;
152 
153 }
154 
155 
156 
157 /* Get rid of shared memory and temp files (atexit handler). */
158 
remove_shm(void)159 static void remove_shm(void) {
160 
161   if (prog_in) unlink(prog_in); /* Ignore errors */
162   shmctl(shm_id, IPC_RMID, NULL);
163 
164 }
165 
166 
167 /* Configure shared memory. */
168 
setup_shm(void)169 static void setup_shm(void) {
170 
171   u8* shm_str;
172 
173   shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
174 
175   if (shm_id < 0) PFATAL("shmget() failed");
176 
177   atexit(remove_shm);
178 
179   shm_str = alloc_printf("%d", shm_id);
180 
181   setenv(SHM_ENV_VAR, shm_str, 1);
182 
183   ck_free(shm_str);
184 
185   trace_bits = shmat(shm_id, NULL, 0);
186 
187   if (!trace_bits) PFATAL("shmat() failed");
188 
189 }
190 
191 
192 /* Read initial file. */
193 
read_initial_file(void)194 static void read_initial_file(void) {
195 
196   struct stat st;
197   s32 fd = open(in_file, O_RDONLY);
198 
199   if (fd < 0) PFATAL("Unable to open '%s'", in_file);
200 
201   if (fstat(fd, &st) || !st.st_size)
202     FATAL("Zero-sized input file.");
203 
204   if (st.st_size >= TMIN_MAX_FILE)
205     FATAL("Input file is too large (%u MB max)", TMIN_MAX_FILE / 1024 / 1024);
206 
207   in_len  = st.st_size;
208   in_data = ck_alloc_nozero(in_len);
209 
210   ck_read(fd, in_data, in_len, in_file);
211 
212   close(fd);
213 
214   OKF("Read %u byte%s from '%s'.", in_len, in_len == 1 ? "" : "s", in_file);
215 
216 }
217 
218 
219 /* Write output file. */
220 
write_to_file(u8 * path,u8 * mem,u32 len)221 static s32 write_to_file(u8* path, u8* mem, u32 len) {
222 
223   s32 ret;
224 
225   unlink(path); /* Ignore errors */
226 
227   ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
228 
229   if (ret < 0) PFATAL("Unable to create '%s'", path);
230 
231   ck_write(ret, mem, len, path);
232 
233   lseek(ret, 0, SEEK_SET);
234 
235   return ret;
236 
237 }
238 
239 
240 /* Handle timeout signal. */
241 
handle_timeout(int sig)242 static void handle_timeout(int sig) {
243 
244   child_timed_out = 1;
245   if (child_pid > 0) kill(child_pid, SIGKILL);
246 
247 }
248 
249 
250 /* Execute target application. Returns 0 if the changes are a dud, or
251    1 if they should be kept. */
252 
run_target(char ** argv,u8 * mem,u32 len,u8 first_run)253 static u8 run_target(char** argv, u8* mem, u32 len, u8 first_run) {
254 
255   static struct itimerval it;
256   int status = 0;
257 
258   s32 prog_in_fd;
259   u32 cksum;
260 
261   memset(trace_bits, 0, MAP_SIZE);
262   MEM_BARRIER();
263 
264   prog_in_fd = write_to_file(prog_in, mem, len);
265 
266   child_pid = fork();
267 
268   if (child_pid < 0) PFATAL("fork() failed");
269 
270   if (!child_pid) {
271 
272     struct rlimit r;
273 
274     if (dup2(use_stdin ? prog_in_fd : dev_null_fd, 0) < 0 ||
275         dup2(dev_null_fd, 1) < 0 ||
276         dup2(dev_null_fd, 2) < 0) {
277 
278       *(u32*)trace_bits = EXEC_FAIL_SIG;
279       PFATAL("dup2() failed");
280 
281     }
282 
283     close(dev_null_fd);
284     close(prog_in_fd);
285 
286     setsid();
287 
288     if (mem_limit) {
289 
290       r.rlim_max = r.rlim_cur = ((rlim_t)mem_limit) << 20;
291 
292 #ifdef RLIMIT_AS
293 
294       setrlimit(RLIMIT_AS, &r); /* Ignore errors */
295 
296 #else
297 
298       setrlimit(RLIMIT_DATA, &r); /* Ignore errors */
299 
300 #endif /* ^RLIMIT_AS */
301 
302     }
303 
304     r.rlim_max = r.rlim_cur = 0;
305     setrlimit(RLIMIT_CORE, &r); /* Ignore errors */
306 
307     execv(target_path, argv);
308 
309     *(u32*)trace_bits = EXEC_FAIL_SIG;
310     exit(0);
311 
312   }
313 
314   close(prog_in_fd);
315 
316   /* Configure timeout, wait for child, cancel timeout. */
317 
318   child_timed_out = 0;
319   it.it_value.tv_sec = (exec_tmout / 1000);
320   it.it_value.tv_usec = (exec_tmout % 1000) * 1000;
321 
322   setitimer(ITIMER_REAL, &it, NULL);
323 
324   if (waitpid(child_pid, &status, 0) <= 0) FATAL("waitpid() failed");
325 
326   child_pid = 0;
327   it.it_value.tv_sec = 0;
328   it.it_value.tv_usec = 0;
329 
330   setitimer(ITIMER_REAL, &it, NULL);
331 
332   MEM_BARRIER();
333 
334   /* Clean up bitmap, analyze exit condition, etc. */
335 
336   if (*(u32*)trace_bits == EXEC_FAIL_SIG)
337     FATAL("Unable to execute '%s'", argv[0]);
338 
339   classify_counts(trace_bits);
340   apply_mask((u32*)trace_bits, (u32*)mask_bitmap);
341   total_execs++;
342 
343   if (stop_soon) {
344 
345     SAYF(cRST cLRD "\n+++ Minimization aborted by user +++\n" cRST);
346     close(write_to_file(out_file, in_data, in_len));
347     exit(1);
348 
349   }
350 
351   /* Always discard inputs that time out. */
352 
353   if (child_timed_out) {
354 
355     missed_hangs++;
356     return 0;
357 
358   }
359 
360   /* Handle crashing inputs depending on current mode. */
361 
362   if (WIFSIGNALED(status) ||
363       (WIFEXITED(status) && WEXITSTATUS(status) == MSAN_ERROR) ||
364       (WIFEXITED(status) && WEXITSTATUS(status) && exit_crash)) {
365 
366     if (first_run) crash_mode = 1;
367 
368     if (crash_mode) {
369 
370       if (!exact_mode) return 1;
371 
372     } else {
373 
374       missed_crashes++;
375       return 0;
376 
377     }
378 
379   } else
380 
381   /* Handle non-crashing inputs appropriately. */
382 
383   if (crash_mode) {
384 
385     missed_paths++;
386     return 0;
387 
388   }
389 
390   cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);
391 
392   if (first_run) orig_cksum = cksum;
393 
394   if (orig_cksum == cksum) return 1;
395 
396   missed_paths++;
397   return 0;
398 
399 }
400 
401 
402 /* Find first power of two greater or equal to val. */
403 
next_p2(u32 val)404 static u32 next_p2(u32 val) {
405 
406   u32 ret = 1;
407   while (val > ret) ret <<= 1;
408   return ret;
409 
410 }
411 
412 
413 /* Actually minimize! */
414 
minimize(char ** argv)415 static void minimize(char** argv) {
416 
417   static u32 alpha_map[256];
418 
419   u8* tmp_buf = ck_alloc_nozero(in_len);
420   u32 orig_len = in_len, stage_o_len;
421 
422   u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
423   u32 syms_removed, alpha_del0 = 0, alpha_del1, alpha_del2, alpha_d_total = 0;
424   u8  changed_any, prev_del;
425 
426   /***********************
427    * BLOCK NORMALIZATION *
428    ***********************/
429 
430   set_len    = next_p2(in_len / TMIN_SET_STEPS);
431   set_pos    = 0;
432 
433   if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE;
434 
435   ACTF(cBRI "Stage #0: " cRST "One-time block normalization...");
436 
437   while (set_pos < in_len) {
438 
439     u8  res;
440     u32 use_len = MIN(set_len, in_len - set_pos);
441 
442     for (i = 0; i < use_len; i++)
443       if (in_data[set_pos + i] != '0') break;
444 
445     if (i != use_len) {
446 
447       memcpy(tmp_buf, in_data, in_len);
448       memset(tmp_buf + set_pos, '0', use_len);
449 
450       res = run_target(argv, tmp_buf, in_len, 0);
451 
452       if (res) {
453 
454         memset(in_data + set_pos, '0', use_len);
455         changed_any = 1;
456         alpha_del0 += use_len;
457 
458       }
459 
460     }
461 
462     set_pos += set_len;
463 
464   }
465 
466   alpha_d_total += alpha_del0;
467 
468   OKF("Block normalization complete, %u byte%s replaced.", alpha_del0,
469       alpha_del0 == 1 ? "" : "s");
470 
471 next_pass:
472 
473   ACTF(cYEL "--- " cBRI "Pass #%u " cYEL "---", ++cur_pass);
474   changed_any = 0;
475 
476   /******************
477    * BLOCK DELETION *
478    ******************/
479 
480   del_len = next_p2(in_len / TRIM_START_STEPS);
481   stage_o_len = in_len;
482 
483   ACTF(cBRI "Stage #1: " cRST "Removing blocks of data...");
484 
485 next_del_blksize:
486 
487   if (!del_len) del_len = 1;
488   del_pos  = 0;
489   prev_del = 1;
490 
491   SAYF(cGRA "    Block length = %u, remaining size = %u\n" cRST,
492        del_len, in_len);
493 
494   while (del_pos < in_len) {
495 
496     u8  res;
497     s32 tail_len;
498 
499     tail_len = in_len - del_pos - del_len;
500     if (tail_len < 0) tail_len = 0;
501 
502     /* If we have processed at least one full block (initially, prev_del == 1),
503        and we did so without deleting the previous one, and we aren't at the
504        very end of the buffer (tail_len > 0), and the current block is the same
505        as the previous one... skip this step as a no-op. */
506 
507     if (!prev_del && tail_len && !memcmp(in_data + del_pos - del_len,
508         in_data + del_pos, del_len)) {
509 
510       del_pos += del_len;
511       continue;
512 
513     }
514 
515     prev_del = 0;
516 
517     /* Head */
518     memcpy(tmp_buf, in_data, del_pos);
519 
520     /* Tail */
521     memcpy(tmp_buf + del_pos, in_data + del_pos + del_len, tail_len);
522 
523     res = run_target(argv, tmp_buf, del_pos + tail_len, 0);
524 
525     if (res) {
526 
527       memcpy(in_data, tmp_buf, del_pos + tail_len);
528       prev_del = 1;
529       in_len   = del_pos + tail_len;
530 
531       changed_any = 1;
532 
533     } else del_pos += del_len;
534 
535   }
536 
537   if (del_len > 1 && in_len >= 1) {
538 
539     del_len /= 2;
540     goto next_del_blksize;
541 
542   }
543 
544   OKF("Block removal complete, %u bytes deleted.", stage_o_len - in_len);
545 
546   if (!in_len && changed_any)
547     WARNF(cLRD "Down to zero bytes - check the command line and mem limit!" cRST);
548 
549   if (cur_pass > 1 && !changed_any) goto finalize_all;
550 
551   /*************************
552    * ALPHABET MINIMIZATION *
553    *************************/
554 
555   alpha_size   = 0;
556   alpha_del1   = 0;
557   syms_removed = 0;
558 
559   memset(alpha_map, 0, 256 * sizeof(u32));
560 
561   for (i = 0; i < in_len; i++) {
562     if (!alpha_map[in_data[i]]) alpha_size++;
563     alpha_map[in_data[i]]++;
564   }
565 
566   ACTF(cBRI "Stage #2: " cRST "Minimizing symbols (%u code point%s)...",
567        alpha_size, alpha_size == 1 ? "" : "s");
568 
569   for (i = 0; i < 256; i++) {
570 
571     u32 r;
572     u8 res;
573 
574     if (i == '0' || !alpha_map[i]) continue;
575 
576     memcpy(tmp_buf, in_data, in_len);
577 
578     for (r = 0; r < in_len; r++)
579       if (tmp_buf[r] == i) tmp_buf[r] = '0';
580 
581     res = run_target(argv, tmp_buf, in_len, 0);
582 
583     if (res) {
584 
585       memcpy(in_data, tmp_buf, in_len);
586       syms_removed++;
587       alpha_del1 += alpha_map[i];
588       changed_any = 1;
589 
590     }
591 
592   }
593 
594   alpha_d_total += alpha_del1;
595 
596   OKF("Symbol minimization finished, %u symbol%s (%u byte%s) replaced.",
597       syms_removed, syms_removed == 1 ? "" : "s",
598       alpha_del1, alpha_del1 == 1 ? "" : "s");
599 
600   /**************************
601    * CHARACTER MINIMIZATION *
602    **************************/
603 
604   alpha_del2 = 0;
605 
606   ACTF(cBRI "Stage #3: " cRST "Character minimization...");
607 
608   memcpy(tmp_buf, in_data, in_len);
609 
610   for (i = 0; i < in_len; i++) {
611 
612     u8 res, orig = tmp_buf[i];
613 
614     if (orig == '0') continue;
615     tmp_buf[i] = '0';
616 
617     res = run_target(argv, tmp_buf, in_len, 0);
618 
619     if (res) {
620 
621       in_data[i] = '0';
622       alpha_del2++;
623       changed_any = 1;
624 
625     } else tmp_buf[i] = orig;
626 
627   }
628 
629   alpha_d_total += alpha_del2;
630 
631   OKF("Character minimization done, %u byte%s replaced.",
632       alpha_del2, alpha_del2 == 1 ? "" : "s");
633 
634   if (changed_any) goto next_pass;
635 
636 finalize_all:
637 
638   SAYF("\n"
639        cGRA "     File size reduced by : " cRST "%0.02f%% (to %u byte%s)\n"
640        cGRA "    Characters simplified : " cRST "%0.02f%%\n"
641        cGRA "     Number of execs done : " cRST "%u\n"
642        cGRA "          Fruitless execs : " cRST "path=%u crash=%u hang=%s%u\n\n",
643        100 - ((double)in_len) * 100 / orig_len, in_len, in_len == 1 ? "" : "s",
644        ((double)(alpha_d_total)) * 100 / (in_len ? in_len : 1),
645        total_execs, missed_paths, missed_crashes, missed_hangs ? cLRD : "",
646        missed_hangs);
647 
648   if (total_execs > 50 && missed_hangs * 10 > total_execs)
649     WARNF(cLRD "Frequent timeouts - results may be skewed." cRST);
650 
651 }
652 
653 
654 
655 /* Handle Ctrl-C and the like. */
656 
handle_stop_sig(int sig)657 static void handle_stop_sig(int sig) {
658 
659   stop_soon = 1;
660 
661   if (child_pid > 0) kill(child_pid, SIGKILL);
662 
663 }
664 
665 
666 /* Do basic preparations - persistent fds, filenames, etc. */
667 
set_up_environment(void)668 static void set_up_environment(void) {
669 
670   u8* x;
671 
672   dev_null_fd = open("/dev/null", O_RDWR);
673   if (dev_null_fd < 0) PFATAL("Unable to open /dev/null");
674 
675   if (!prog_in) {
676 
677     u8* use_dir = ".";
678 
679     if (access(use_dir, R_OK | W_OK | X_OK)) {
680 
681       use_dir = getenv("TMPDIR");
682       if (!use_dir) use_dir = "/tmp";
683 
684     }
685 
686     prog_in = alloc_printf("%s/.afl-tmin-temp-%u", use_dir, getpid());
687 
688   }
689 
690   /* Set sane defaults... */
691 
692   x = getenv("ASAN_OPTIONS");
693 
694   if (x) {
695 
696     if (!strstr(x, "abort_on_error=1"))
697       FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
698 
699     if (!strstr(x, "symbolize=0"))
700       FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
701 
702   }
703 
704   x = getenv("MSAN_OPTIONS");
705 
706   if (x) {
707 
708     if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR)))
709       FATAL("Custom MSAN_OPTIONS set without exit_code="
710             STRINGIFY(MSAN_ERROR) " - please fix!");
711 
712     if (!strstr(x, "symbolize=0"))
713       FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
714 
715   }
716 
717   setenv("ASAN_OPTIONS", "abort_on_error=1:"
718                          "detect_leaks=0:"
719                          "symbolize=0:"
720                          "allocator_may_return_null=1", 0);
721 
722   setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
723                          "symbolize=0:"
724                          "abort_on_error=1:"
725                          "allocator_may_return_null=1:"
726                          "msan_track_origins=0", 0);
727 
728   if (getenv("AFL_PRELOAD")) {
729     setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
730     setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
731   }
732 
733 }
734 
735 
736 /* Setup signal handlers, duh. */
737 
setup_signal_handlers(void)738 static void setup_signal_handlers(void) {
739 
740   struct sigaction sa;
741 
742   sa.sa_handler   = NULL;
743   sa.sa_flags     = SA_RESTART;
744   sa.sa_sigaction = NULL;
745 
746   sigemptyset(&sa.sa_mask);
747 
748   /* Various ways of saying "stop". */
749 
750   sa.sa_handler = handle_stop_sig;
751   sigaction(SIGHUP, &sa, NULL);
752   sigaction(SIGINT, &sa, NULL);
753   sigaction(SIGTERM, &sa, NULL);
754 
755   /* Exec timeout notifications. */
756 
757   sa.sa_handler = handle_timeout;
758   sigaction(SIGALRM, &sa, NULL);
759 
760 }
761 
762 
763 /* Detect @@ in args. */
764 
detect_file_args(char ** argv)765 static void detect_file_args(char** argv) {
766 
767   u32 i = 0;
768   u8* cwd = getcwd(NULL, 0);
769 
770   if (!cwd) PFATAL("getcwd() failed");
771 
772   while (argv[i]) {
773 
774     u8* aa_loc = strstr(argv[i], "@@");
775 
776     if (aa_loc) {
777 
778       u8 *aa_subst, *n_arg;
779 
780       /* Be sure that we're always using fully-qualified paths. */
781 
782       if (prog_in[0] == '/') aa_subst = prog_in;
783       else aa_subst = alloc_printf("%s/%s", cwd, prog_in);
784 
785       /* Construct a replacement argv value. */
786 
787       *aa_loc = 0;
788       n_arg = alloc_printf("%s%s%s", argv[i], aa_subst, aa_loc + 2);
789       argv[i] = n_arg;
790       *aa_loc = '@';
791 
792       if (prog_in[0] != '/') ck_free(aa_subst);
793 
794     }
795 
796     i++;
797 
798   }
799 
800   free(cwd); /* not tracked */
801 
802 }
803 
804 
805 /* Display usage hints. */
806 
usage(u8 * argv0)807 static void usage(u8* argv0) {
808 
809   SAYF("\n%s [ options ] -- /path/to/target_app [ ... ]\n\n"
810 
811        "Required parameters:\n\n"
812 
813        "  -i file       - input test case to be shrunk by the tool\n"
814        "  -o file       - final output location for the minimized data\n\n"
815 
816        "Execution control settings:\n\n"
817 
818        "  -f file       - input file read by the tested program (stdin)\n"
819        "  -t msec       - timeout for each run (%u ms)\n"
820        "  -m megs       - memory limit for child process (%u MB)\n"
821        "  -Q            - use binary-only instrumentation (QEMU mode)\n\n"
822 
823        "Minimization settings:\n\n"
824 
825        "  -e            - solve for edge coverage only, ignore hit counts\n"
826        "  -x            - treat non-zero exit codes as crashes\n\n"
827 
828        "For additional tips, please consult %s/README.\n\n",
829 
830        argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
831 
832   exit(1);
833 
834 }
835 
836 
837 /* Find binary. */
838 
find_binary(u8 * fname)839 static void find_binary(u8* fname) {
840 
841   u8* env_path = 0;
842   struct stat st;
843 
844   if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
845 
846     target_path = ck_strdup(fname);
847 
848     if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
849         !(st.st_mode & 0111) || st.st_size < 4)
850       FATAL("Program '%s' not found or not executable", fname);
851 
852   } else {
853 
854     while (env_path) {
855 
856       u8 *cur_elem, *delim = strchr(env_path, ':');
857 
858       if (delim) {
859 
860         cur_elem = ck_alloc(delim - env_path + 1);
861         memcpy(cur_elem, env_path, delim - env_path);
862         delim++;
863 
864       } else cur_elem = ck_strdup(env_path);
865 
866       env_path = delim;
867 
868       if (cur_elem[0])
869         target_path = alloc_printf("%s/%s", cur_elem, fname);
870       else
871         target_path = ck_strdup(fname);
872 
873       ck_free(cur_elem);
874 
875       if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
876           (st.st_mode & 0111) && st.st_size >= 4) break;
877 
878       ck_free(target_path);
879       target_path = 0;
880 
881     }
882 
883     if (!target_path) FATAL("Program '%s' not found or not executable", fname);
884 
885   }
886 
887 }
888 
889 
890 /* Fix up argv for QEMU. */
891 
get_qemu_argv(u8 * own_loc,char ** argv,int argc)892 static char** get_qemu_argv(u8* own_loc, char** argv, int argc) {
893 
894   char** new_argv = ck_alloc(sizeof(char*) * (argc + 4));
895   u8 *tmp, *cp, *rsl, *own_copy;
896 
897   /* Workaround for a QEMU stability glitch. */
898 
899   setenv("QEMU_LOG", "nochain", 1);
900 
901   memcpy(new_argv + 3, argv + 1, sizeof(char*) * argc);
902 
903   /* Now we need to actually find qemu for argv[0]. */
904 
905   new_argv[2] = target_path;
906   new_argv[1] = "--";
907 
908   tmp = getenv("AFL_PATH");
909 
910   if (tmp) {
911 
912     cp = alloc_printf("%s/afl-qemu-trace", tmp);
913 
914     if (access(cp, X_OK))
915       FATAL("Unable to find '%s'", tmp);
916 
917     target_path = new_argv[0] = cp;
918     return new_argv;
919 
920   }
921 
922   own_copy = ck_strdup(own_loc);
923   rsl = strrchr(own_copy, '/');
924 
925   if (rsl) {
926 
927     *rsl = 0;
928 
929     cp = alloc_printf("%s/afl-qemu-trace", own_copy);
930     ck_free(own_copy);
931 
932     if (!access(cp, X_OK)) {
933 
934       target_path = new_argv[0] = cp;
935       return new_argv;
936 
937     }
938 
939   } else ck_free(own_copy);
940 
941   if (!access(BIN_PATH "/afl-qemu-trace", X_OK)) {
942 
943     target_path = new_argv[0] = BIN_PATH "/afl-qemu-trace";
944     return new_argv;
945 
946   }
947 
948   FATAL("Unable to find 'afl-qemu-trace'.");
949 
950 }
951 
952 
953 /* Read mask bitmap from file. This is for the -B option. */
954 
read_bitmap(u8 * fname)955 static void read_bitmap(u8* fname) {
956 
957   s32 fd = open(fname, O_RDONLY);
958 
959   if (fd < 0) PFATAL("Unable to open '%s'", fname);
960 
961   ck_read(fd, mask_bitmap, MAP_SIZE, fname);
962 
963   close(fd);
964 
965 }
966 
967 
968 
969 /* Main entry point */
970 
main(int argc,char ** argv)971 int main(int argc, char** argv) {
972 
973   s32 opt;
974   u8  mem_limit_given = 0, timeout_given = 0, qemu_mode = 0;
975   char** use_argv;
976 
977   doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
978 
979   SAYF(cCYA "afl-tmin " cBRI VERSION cRST " by <lcamtuf@google.com>\n");
980 
981   while ((opt = getopt(argc,argv,"+i:o:f:m:t:B:xeQ")) > 0)
982 
983     switch (opt) {
984 
985       case 'i':
986 
987         if (in_file) FATAL("Multiple -i options not supported");
988         in_file = optarg;
989         break;
990 
991       case 'o':
992 
993         if (out_file) FATAL("Multiple -o options not supported");
994         out_file = optarg;
995         break;
996 
997       case 'f':
998 
999         if (prog_in) FATAL("Multiple -f options not supported");
1000         use_stdin = 0;
1001         prog_in   = optarg;
1002         break;
1003 
1004       case 'e':
1005 
1006         if (edges_only) FATAL("Multiple -e options not supported");
1007         edges_only = 1;
1008         break;
1009 
1010       case 'x':
1011 
1012         if (exit_crash) FATAL("Multiple -x options not supported");
1013         exit_crash = 1;
1014         break;
1015 
1016       case 'm': {
1017 
1018           u8 suffix = 'M';
1019 
1020           if (mem_limit_given) FATAL("Multiple -m options not supported");
1021           mem_limit_given = 1;
1022 
1023           if (!strcmp(optarg, "none")) {
1024 
1025             mem_limit = 0;
1026             break;
1027 
1028           }
1029 
1030           if (sscanf(optarg, "%llu%c", &mem_limit, &suffix) < 1 ||
1031               optarg[0] == '-') FATAL("Bad syntax used for -m");
1032 
1033           switch (suffix) {
1034 
1035             case 'T': mem_limit *= 1024 * 1024; break;
1036             case 'G': mem_limit *= 1024; break;
1037             case 'k': mem_limit /= 1024; break;
1038             case 'M': break;
1039 
1040             default:  FATAL("Unsupported suffix or bad syntax for -m");
1041 
1042           }
1043 
1044           if (mem_limit < 5) FATAL("Dangerously low value of -m");
1045 
1046           if (sizeof(rlim_t) == 4 && mem_limit > 2000)
1047             FATAL("Value of -m out of range on 32-bit systems");
1048 
1049         }
1050 
1051         break;
1052 
1053       case 't':
1054 
1055         if (timeout_given) FATAL("Multiple -t options not supported");
1056         timeout_given = 1;
1057 
1058         exec_tmout = atoi(optarg);
1059 
1060         if (exec_tmout < 10 || optarg[0] == '-')
1061           FATAL("Dangerously low value of -t");
1062 
1063         break;
1064 
1065       case 'Q':
1066 
1067         if (qemu_mode) FATAL("Multiple -Q options not supported");
1068         if (!mem_limit_given) mem_limit = MEM_LIMIT_QEMU;
1069 
1070         qemu_mode = 1;
1071         break;
1072 
1073       case 'B': /* load bitmap */
1074 
1075         /* This is a secret undocumented option! It is speculated to be useful
1076            if you have a baseline "boring" input file and another "interesting"
1077            file you want to minimize.
1078 
1079            You can dump a binary bitmap for the boring file using
1080            afl-showmap -b, and then load it into afl-tmin via -B. The minimizer
1081            will then minimize to preserve only the edges that are unique to
1082            the interesting input file, but ignoring everything from the
1083            original map.
1084 
1085            The option may be extended and made more official if it proves
1086            to be useful. */
1087 
1088         if (mask_bitmap) FATAL("Multiple -B options not supported");
1089         mask_bitmap = ck_alloc(MAP_SIZE);
1090         read_bitmap(optarg);
1091         break;
1092 
1093       default:
1094 
1095         usage(argv[0]);
1096 
1097     }
1098 
1099   if (optind == argc || !in_file || !out_file) usage(argv[0]);
1100 
1101   setup_shm();
1102   setup_signal_handlers();
1103 
1104   set_up_environment();
1105 
1106   find_binary(argv[optind]);
1107   detect_file_args(argv + optind);
1108 
1109   if (qemu_mode)
1110     use_argv = get_qemu_argv(argv[0], argv + optind, argc - optind);
1111   else
1112     use_argv = argv + optind;
1113 
1114   exact_mode = !!getenv("AFL_TMIN_EXACT");
1115 
1116   SAYF("\n");
1117 
1118   read_initial_file();
1119 
1120   ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
1121        mem_limit, exec_tmout, edges_only ? ", edges only" : "");
1122 
1123   run_target(use_argv, in_data, in_len, 1);
1124 
1125   if (child_timed_out)
1126     FATAL("Target binary times out (adjusting -t may help).");
1127 
1128   if (!crash_mode) {
1129 
1130      OKF("Program terminates normally, minimizing in "
1131          cCYA "instrumented" cRST " mode.");
1132 
1133      if (!anything_set()) FATAL("No instrumentation detected.");
1134 
1135   } else {
1136 
1137      OKF("Program exits with a signal, minimizing in " cMGN "%scrash" cRST
1138          " mode.", exact_mode ? "EXACT " : "");
1139 
1140   }
1141 
1142   minimize(use_argv);
1143 
1144   ACTF("Writing output to '%s'...", out_file);
1145 
1146   unlink(prog_in);
1147   prog_in = NULL;
1148 
1149   close(write_to_file(out_file, in_data, in_len));
1150 
1151   OKF("We're done here. Have a nice day!\n");
1152 
1153   exit(0);
1154 
1155 }
1156 
1157