xref: /aosp_15_r20/external/AFLplusplus/src/afl-fuzz-init.c (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
1 /*
2    american fuzzy lop++ - initialization related routines
3    ------------------------------------------------------
4 
5    Originally written by Michal Zalewski
6 
7    Now maintained by Marc Heuse <[email protected]>,
8                         Heiko Eißfeldt <[email protected]> and
9                         Andrea Fioraldi <[email protected]>
10 
11    Copyright 2016, 2017 Google Inc. All rights reserved.
12    Copyright 2019-2024 AFLplusplus Project. All rights reserved.
13 
14    Licensed under the Apache License, Version 2.0 (the "License");
15    you may not use this file except in compliance with the License.
16    You may obtain a copy of the License at:
17 
18      https://www.apache.org/licenses/LICENSE-2.0
19 
20    This is the real deal: the program takes an instrumented binary and
21    attempts a variety of basic fuzzing tricks, paying close attention to
22    how they affect the execution path.
23 
24  */
25 
26 #include "afl-fuzz.h"
27 #include "common.h"
28 #include <limits.h>
29 #include <string.h>
30 #include "cmplog.h"
31 
32 #ifdef HAVE_AFFINITY
33 
34 /* bind process to a specific cpu. Returns 0 on failure. */
35 
bind_cpu(afl_state_t * afl,s32 cpuid)36 static u8 bind_cpu(afl_state_t *afl, s32 cpuid) {
37 
38   #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
39   cpu_set_t c;
40   #elif defined(__NetBSD__)
41   cpuset_t *c;
42   #elif defined(__sun)
43   psetid_t c;
44   #endif
45 
46   afl->cpu_aff = cpuid;
47 
48   #if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
49 
50   CPU_ZERO(&c);
51   CPU_SET(cpuid, &c);
52 
53   #elif defined(__NetBSD__)
54 
55   c = cpuset_create();
56   if (c == NULL) { PFATAL("cpuset_create failed"); }
57   cpuset_set(cpuid, c);
58 
59   #elif defined(__sun)
60 
61   pset_create(&c);
62   if (pset_assign(c, cpuid, NULL)) { PFATAL("pset_assign failed"); }
63 
64   #endif
65 
66   #if defined(__linux__)
67 
68   return (sched_setaffinity(0, sizeof(c), &c) == 0);
69 
70   #elif defined(__FreeBSD__) || defined(__DragonFly__)
71 
72   return (pthread_setaffinity_np(pthread_self(), sizeof(c), &c) == 0);
73 
74   #elif defined(__NetBSD__)
75 
76   if (pthread_setaffinity_np(pthread_self(), cpuset_size(c), c)) {
77 
78     cpuset_destroy(c);
79     return 0;
80 
81   }
82 
83   cpuset_destroy(c);
84   return 1;
85 
86   #elif defined(__sun)
87 
88   if (pset_bind(c, P_PID, getpid(), NULL)) {
89 
90     pset_destroy(c);
91     return 0;
92 
93   }
94 
95   pset_destroy(c);
96   return 1;
97 
98   #else
99 
100   // this will need something for other platforms
101   // TODO: Solaris/Illumos has processor_bind ... might worth a try
102   WARNF("Cannot bind to CPU yet on this platform.");
103   return 1;
104 
105   #endif
106 
107 }
108 
109 /* Build a list of processes bound to specific cores. Returns -1 if nothing
110    can be found. Assumes an upper bound of 4k CPUs. */
111 
bind_to_free_cpu(afl_state_t * afl)112 void bind_to_free_cpu(afl_state_t *afl) {
113 
114   u8  cpu_used[4096] = {0};
115   u8  lockfile[PATH_MAX] = "";
116   s32 i;
117 
118   if (afl->afl_env.afl_no_affinity && !afl->afl_env.afl_try_affinity) {
119 
120     if (afl->cpu_to_bind != -1) {
121 
122       FATAL("-b and AFL_NO_AFFINITY are mututally exclusive.");
123 
124     }
125 
126     WARNF("Not binding to a CPU core (AFL_NO_AFFINITY set).");
127   #ifdef __linux__
128     if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = 0; }
129   #endif
130     return;
131 
132   }
133 
134   if (afl->cpu_to_bind != -1) {
135 
136     if (!bind_cpu(afl, afl->cpu_to_bind)) {
137 
138       if (afl->afl_env.afl_try_affinity) {
139 
140         WARNF(
141             "Could not bind to requested CPU %d! Make sure you passed a valid "
142             "-b.",
143             afl->cpu_to_bind);
144 
145       } else {
146 
147         FATAL(
148             "Could not bind to requested CPU %d! Make sure you passed a valid "
149             "-b.",
150             afl->cpu_to_bind);
151 
152       }
153 
154     } else {
155 
156       OKF("CPU binding request using -b %d successful.", afl->cpu_to_bind);
157   #ifdef __linux__
158       if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = afl->cpu_to_bind; }
159   #endif
160 
161     }
162 
163     return;
164 
165   }
166 
167   if (afl->cpu_core_count < 2) { return; }
168 
169   if (afl->sync_id) {
170 
171     s32 lockfd, first = 1;
172 
173     snprintf(lockfile, sizeof(lockfile), "%s/.affinity_lock", afl->sync_dir);
174     setenv(CPU_AFFINITY_ENV_VAR, lockfile, 1);
175 
176     do {
177 
178       if ((lockfd = open(lockfile, O_RDWR | O_CREAT | O_EXCL,
179                          DEFAULT_PERMISSION)) < 0) {
180 
181         if (first) {
182 
183           WARNF("CPU affinity lock file present, waiting ...");
184           first = 0;
185 
186         }
187 
188         usleep(1000);
189 
190       }
191 
192     } while (lockfd < 0);
193 
194     close(lockfd);
195 
196   }
197 
198   #if defined(__linux__)
199 
200   DIR           *d;
201   struct dirent *de;
202   d = opendir("/proc");
203 
204   if (!d) {
205 
206     if (lockfile[0]) unlink(lockfile);
207     WARNF("Unable to access /proc - can't scan for free CPU cores.");
208     return;
209 
210   }
211 
212   ACTF("Checking CPU core loadout...");
213 
214   /* Scan all /proc/<pid>/status entries, checking for Cpus_allowed_list.
215      Flag all processes bound to a specific CPU using cpu_used[]. This will
216      fail for some exotic binding setups, but is likely good enough in almost
217      all real-world use cases. */
218 
219   while ((de = readdir(d))) {
220 
221     u8    fn[PATH_MAX];
222     FILE *f;
223     u8    tmp[MAX_LINE];
224     u8    has_vmsize = 0;
225 
226     if (!isdigit(de->d_name[0])) { continue; }
227 
228     snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name);
229 
230     if (!(f = fopen(fn, "r"))) { continue; }
231 
232     while (fgets(tmp, MAX_LINE, f)) {
233 
234       u32 hval;
235 
236       /* Processes without VmSize are probably kernel tasks. */
237 
238       if (!strncmp(tmp, "VmSize:\t", 8)) { has_vmsize = 1; }
239 
240       if (!strncmp(tmp, "Cpus_allowed_list:\t", 19) && !strchr(tmp, '-') &&
241           !strchr(tmp, ',') && sscanf(tmp + 19, "%u", &hval) == 1 &&
242           hval < sizeof(cpu_used) && has_vmsize) {
243 
244         cpu_used[hval] = 1;
245         break;
246 
247       }
248 
249     }
250 
251     fclose(f);
252 
253   }
254 
255   closedir(d);
256 
257   #elif defined(__FreeBSD__) || defined(__DragonFly__)
258 
259   struct kinfo_proc *procs;
260   size_t             nprocs;
261   size_t             proccount;
262   int                s_name[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL};
263   size_t             s_name_l = sizeof(s_name) / sizeof(s_name[0]);
264 
265   if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) {
266 
267     if (lockfile[0]) unlink(lockfile);
268     return;
269 
270   }
271 
272   proccount = nprocs / sizeof(*procs);
273   nprocs = nprocs * 4 / 3;
274 
275   procs = ck_alloc(nprocs);
276   if (sysctl(s_name, s_name_l, procs, &nprocs, NULL, 0) != 0) {
277 
278     if (lockfile[0]) unlink(lockfile);
279     ck_free(procs);
280     return;
281 
282   }
283 
284   for (i = 0; i < (s32)proccount; i++) {
285 
286     #if defined(__FreeBSD__)
287 
288     if (!strcmp(procs[i].ki_comm, "idle")) continue;
289 
290     // fix when ki_oncpu = -1
291     s32 oncpu;
292     oncpu = procs[i].ki_oncpu;
293     if (oncpu == -1) oncpu = procs[i].ki_lastcpu;
294 
295     if (oncpu != -1 && oncpu < (s32)sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
296       cpu_used[oncpu] = 1;
297 
298     #elif defined(__DragonFly__)
299 
300     if (procs[i].kp_lwp.kl_cpuid < (s32)sizeof(cpu_used) &&
301         procs[i].kp_lwp.kl_pctcpu > 10)
302       cpu_used[procs[i].kp_lwp.kl_cpuid] = 1;
303 
304     #endif
305 
306   }
307 
308   ck_free(procs);
309 
310   #elif defined(__NetBSD__)
311 
312   struct kinfo_proc2 *procs;
313   size_t              nprocs;
314   size_t              proccount;
315   int                 s_name[] = {
316 
317       CTL_KERN, KERN_PROC2, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), 0};
318   size_t s_name_l = sizeof(s_name) / sizeof(s_name[0]);
319 
320   if (sysctl(s_name, s_name_l, NULL, &nprocs, NULL, 0) != 0) {
321 
322     if (lockfile[0]) unlink(lockfile);
323     return;
324 
325   }
326 
327   proccount = nprocs / sizeof(struct kinfo_proc2);
328   procs = ck_alloc(nprocs * sizeof(struct kinfo_proc2));
329   s_name[5] = proccount;
330 
331   if (sysctl(s_name, s_name_l, procs, &nprocs, NULL, 0) != 0) {
332 
333     if (lockfile[0]) unlink(lockfile);
334     ck_free(procs);
335     return;
336 
337   }
338 
339   for (i = 0; i < (s32)proccount; i++) {
340 
341     if (procs[i].p_cpuid < sizeof(cpu_used) && procs[i].p_pctcpu > 0)
342       cpu_used[procs[i].p_cpuid] = 1;
343 
344   }
345 
346   ck_free(procs);
347 
348   #elif defined(__sun)
349 
350   kstat_named_t *n;
351   kstat_ctl_t   *m;
352   kstat_t       *k;
353   cpu_stat_t     cs;
354   u32            ncpus;
355 
356   m = kstat_open();
357 
358   if (!m) FATAL("kstat_open failed");
359 
360   k = kstat_lookup(m, "unix", 0, "system_misc");
361 
362   if (!k) {
363 
364     if (lockfile[0]) unlink(lockfile);
365     kstat_close(m);
366     return;
367 
368   }
369 
370   if (kstat_read(m, k, NULL)) {
371 
372     if (lockfile[0]) unlink(lockfile);
373     kstat_close(m);
374     return;
375 
376   }
377 
378   n = kstat_data_lookup(k, "ncpus");
379   ncpus = n->value.i32;
380 
381   if (ncpus > sizeof(cpu_used)) ncpus = sizeof(cpu_used);
382 
383   for (i = 0; i < (s32)ncpus; i++) {
384 
385     k = kstat_lookup(m, "cpu_stat", i, NULL);
386     if (kstat_read(m, k, &cs)) {
387 
388       if (lockfile[0]) unlink(lockfile);
389       kstat_close(m);
390       return;
391 
392     }
393 
394     if (cs.cpu_sysinfo.cpu[CPU_IDLE] > 0) continue;
395 
396     if (cs.cpu_sysinfo.cpu[CPU_USER] > 0 || cs.cpu_sysinfo.cpu[CPU_KERNEL] > 0)
397       cpu_used[i] = 1;
398 
399   }
400 
401   kstat_close(m);
402 
403   #else
404     #warning \
405         "For this platform we do not have free CPU binding code yet. If possible, please supply a PR to https://github.com/AFLplusplus/AFLplusplus"
406   #endif
407 
408   #if !defined(__aarch64__) && !defined(__arm__) && !defined(__arm64__)
409 
410   for (i = 0; i < afl->cpu_core_count; i++) {
411 
412   #else
413 
414   /* many ARM devices have performance and efficiency cores, the slower
415      efficiency cores seem to always come first */
416 
417   for (i = afl->cpu_core_count - 1; i > -1; i--) {
418 
419   #endif
420 
421     if (cpu_used[i]) { continue; }
422 
423     OKF("Found a free CPU core, try binding to #%u.", i);
424 
425     if (bind_cpu(afl, i)) {
426 
427   #ifdef __linux__
428       if (afl->fsrv.nyx_mode) { afl->fsrv.nyx_bind_cpu_id = i; }
429   #endif
430       /* Success :) */
431       break;
432 
433     }
434 
435     WARNF("setaffinity failed to CPU %d, trying next CPU", i);
436 
437   }
438 
439   if (lockfile[0]) unlink(lockfile);
440 
441   if (i == afl->cpu_core_count || i == -1) {
442 
443     SAYF("\n" cLRD "[-] " cRST
444          "Uh-oh, looks like all %d CPU cores on your system are allocated to\n"
445          "    other instances of afl-fuzz (or similar CPU-locked tasks). "
446          "Starting\n"
447          "    another fuzzer on this machine is probably a bad plan.\n"
448          "%s",
449          afl->cpu_core_count,
450          afl->afl_env.afl_try_affinity ? ""
451                                        : "    If you are sure, you can set "
452                                          "AFL_NO_AFFINITY and try again.\n");
453 
454     if (!afl->afl_env.afl_try_affinity) { FATAL("No more free CPU cores"); }
455 
456   }
457 
458 }
459 
460 #endif                                                     /* HAVE_AFFINITY */
461 
462 /* Shuffle an array of pointers. Might be slightly biased. */
463 
464 static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
465 
466   u32 i;
467 
468   for (i = 0; i < cnt - 2; ++i) {
469 
470     u32   j = i + rand_below(afl, cnt - i);
471     void *s = ptrs[i];
472     ptrs[i] = ptrs[j];
473     ptrs[j] = s;
474 
475   }
476 
477 }
478 
479 /* Read all testcases from foreign input directories, then queue them for
480    testing. Called at startup and at sync intervals.
481    Does not descend into subdirectories! */
482 
483 void read_foreign_testcases(afl_state_t *afl, int first) {
484 
485   if (!afl->foreign_sync_cnt) return;
486 
487   struct dirent **nl;
488   s32             nl_cnt;
489   u32             i, iter;
490 
491   u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
492   u8 foreign_name[16];
493 
494   for (iter = 0; iter < afl->foreign_sync_cnt; iter++) {
495 
496     if (afl->foreign_syncs[iter].dir && afl->foreign_syncs[iter].dir[0]) {
497 
498       if (first) ACTF("Scanning '%s'...", afl->foreign_syncs[iter].dir);
499       time_t mtime_max = 0;
500 
501       u8 *name = strrchr(afl->foreign_syncs[iter].dir, '/');
502       if (!name) {
503 
504         name = afl->foreign_syncs[iter].dir;
505 
506       } else {
507 
508         ++name;
509 
510       }
511 
512       if (!strcmp(name, "queue") || !strcmp(name, "out") ||
513           !strcmp(name, "default")) {
514 
515         snprintf(foreign_name, sizeof(foreign_name), "foreign_%u", iter);
516 
517       } else {
518 
519         snprintf(foreign_name, sizeof(foreign_name), "%s_%u", name, iter);
520 
521       }
522 
523       /* We do not use sorting yet and do a more expensive mtime check instead.
524          a mtimesort() implementation would be better though. */
525 
526       nl_cnt = scandir(afl->foreign_syncs[iter].dir, &nl, NULL, NULL);
527 
528       if (nl_cnt < 0) {
529 
530         if (first) {
531 
532           WARNF("Unable to open directory '%s'", afl->foreign_syncs[iter].dir);
533           sleep(1);
534 
535         }
536 
537         continue;
538 
539       }
540 
541       if (nl_cnt == 0) {
542 
543         if (first) {
544 
545           WARNF("directory %s is currently empty",
546                 afl->foreign_syncs[iter].dir);
547 
548         }
549 
550         continue;
551 
552       }
553 
554       /* Show stats */
555 
556       snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "foreign sync %u", iter);
557 
558       afl->stage_name = afl->stage_name_buf;
559       afl->stage_cur = 0;
560       afl->stage_max = 0;
561 
562       for (i = 0; i < (u32)nl_cnt; ++i) {
563 
564         struct stat st;
565 
566         u8 *fn2 =
567             alloc_printf("%s/%s", afl->foreign_syncs[iter].dir, nl[i]->d_name);
568 
569         free(nl[i]);                                         /* not tracked */
570 
571         if (unlikely(lstat(fn2, &st) || access(fn2, R_OK))) {
572 
573           if (first) PFATAL("Unable to access '%s'", fn2);
574           continue;
575 
576         }
577 
578         /* we detect new files by their mtime */
579         if (likely(st.st_mtime <= afl->foreign_syncs[iter].mtime)) {
580 
581           ck_free(fn2);
582           continue;
583 
584         }
585 
586         /* This also takes care of . and .. */
587 
588         if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
589 
590           ck_free(fn2);
591           continue;
592 
593         }
594 
595         if (st.st_size > MAX_FILE) {
596 
597           if (first) {
598 
599             WARNF(
600                 "Test case '%s' is too big (%s, limit is %s), skipping", fn2,
601                 stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
602                 stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
603 
604           }
605 
606           ck_free(fn2);
607           continue;
608 
609         }
610 
611         // lets do not use add_to_queue(afl, fn2, st.st_size, 0);
612         // as this could add duplicates of the startup input corpus
613 
614         int fd = open(fn2, O_RDONLY);
615         if (fd < 0) {
616 
617           ck_free(fn2);
618           continue;
619 
620         }
621 
622         u8  fault;
623         u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
624 
625         if (mem == MAP_FAILED) {
626 
627           ck_free(fn2);
628           continue;
629 
630         }
631 
632         u32 len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
633         fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
634         afl->syncing_party = foreign_name;
635         afl->queued_imported += save_if_interesting(afl, mem, len, fault);
636         afl->syncing_party = 0;
637         munmap(mem, st.st_size);
638         close(fd);
639 
640         if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
641 
642       }
643 
644       afl->foreign_syncs[iter].mtime = mtime_max;
645       free(nl);                                              /* not tracked */
646 
647     }
648 
649   }
650 
651   if (first) {
652 
653     afl->last_find_time = 0;
654     afl->queued_at_start = afl->queued_items;
655 
656   }
657 
658 }
659 
660 /* Read all testcases from the input directory, then queue them for testing.
661    Called at startup. */
662 
663 void read_testcases(afl_state_t *afl, u8 *directory) {
664 
665   struct dirent **nl;
666   s32             nl_cnt, subdirs = 1;
667   u32             i;
668   u8             *fn1, *dir = directory;
669   u8              val_buf[2][STRINGIFY_VAL_SIZE_MAX];
670 
671   /* Auto-detect non-in-place resumption attempts. */
672 
673   if (dir == NULL) {
674 
675     fn1 = alloc_printf("%s/queue", afl->in_dir);
676     if (!access(fn1, F_OK)) {
677 
678       afl->in_dir = fn1;
679       subdirs = 0;
680 
681     } else {
682 
683       ck_free(fn1);
684 
685     }
686 
687     dir = afl->in_dir;
688 
689   }
690 
691   ACTF("Scanning '%s'...", dir);
692 
693   /* We use scandir() + alphasort() rather than readdir() because otherwise,
694      the ordering of test cases would vary somewhat randomly and would be
695      difficult to control. */
696 
697   nl_cnt = scandir(dir, &nl, NULL, alphasort);
698 
699   if (nl_cnt < 0 && directory == NULL) {
700 
701     if (errno == ENOENT || errno == ENOTDIR) {
702 
703       SAYF("\n" cLRD "[-] " cRST
704            "The input directory does not seem to be valid - try again. The "
705            "fuzzer needs\n"
706            "    one or more test case to start with - ideally, a small file "
707            "under 1 kB\n"
708            "    or so. The cases must be stored as regular files directly in "
709            "the input\n"
710            "    directory.\n");
711 
712     }
713 
714     PFATAL("Unable to open '%s'", dir);
715 
716   }
717 
718   if (unlikely(afl->old_seed_selection && afl->shuffle_queue && nl_cnt > 1)) {
719 
720     ACTF("Shuffling queue...");
721     shuffle_ptrs(afl, (void **)nl, nl_cnt);
722 
723   }
724 
725   // if (getenv("MYTEST")) afl->in_place_resume = 1;
726 
727   if (nl_cnt) {
728 
729     u32 done = 0;
730 
731     if (unlikely(afl->in_place_resume)) {
732 
733       i = nl_cnt;
734 
735     } else {
736 
737       i = 0;
738 
739     }
740 
741     do {
742 
743       if (unlikely(afl->in_place_resume)) { --i; }
744 
745       struct stat st;
746       u8          dfn[PATH_MAX];
747       snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
748                nl[i]->d_name);
749       u8 *fn2 = alloc_printf("%s/%s", dir, nl[i]->d_name);
750 
751       u8 passed_det = 0;
752 
753       if (lstat(fn2, &st) || access(fn2, R_OK)) {
754 
755         PFATAL("Unable to access '%s'", fn2);
756 
757       }
758 
759       /* obviously we want to skip "descending" into . and .. directories,
760          however it is a good idea to skip also directories that start with
761          a dot */
762       if (subdirs && S_ISDIR(st.st_mode) && nl[i]->d_name[0] != '.') {
763 
764         free(nl[i]);                                         /* not tracked */
765         read_testcases(afl, fn2);
766         ck_free(fn2);
767         goto next_entry;
768 
769       }
770 
771       free(nl[i]);
772 
773       if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
774 
775         ck_free(fn2);
776         goto next_entry;
777 
778       }
779 
780       if (st.st_size > MAX_FILE) {
781 
782         WARNF("Test case '%s' is too big (%s, limit is %s), partial reading",
783               fn2,
784               stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
785               stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
786 
787       }
788 
789       /* Check for metadata that indicates that deterministic fuzzing
790          is complete for this entry. We don't want to repeat deterministic
791          fuzzing when resuming aborted scans, because it would be pointless
792          and probably very time-consuming. */
793 
794       if (!access(dfn, F_OK)) { passed_det = 1; }
795 
796       add_to_queue(afl, fn2, st.st_size >= MAX_FILE ? MAX_FILE : st.st_size,
797                    passed_det);
798 
799       if (unlikely(afl->shm.cmplog_mode)) {
800 
801         if (afl->cmplog_lvl == 1) {
802 
803           if (!afl->cmplog_max_filesize ||
804               afl->cmplog_max_filesize < st.st_size) {
805 
806             afl->cmplog_max_filesize = st.st_size;
807 
808           }
809 
810         } else if (afl->cmplog_lvl == 2) {
811 
812           if (!afl->cmplog_max_filesize ||
813               afl->cmplog_max_filesize > st.st_size) {
814 
815             afl->cmplog_max_filesize = st.st_size;
816 
817           }
818 
819         }
820 
821       }
822 
823     next_entry:
824       if (unlikely(afl->in_place_resume)) {
825 
826         if (unlikely(i == 0)) { done = 1; }
827 
828       } else {
829 
830         if (unlikely(++i >= (u32)nl_cnt)) { done = 1; }
831 
832       }
833 
834     } while (!done);
835 
836   }
837 
838   // if (getenv("MYTEST")) afl->in_place_resume = 0;
839 
840   free(nl);                                                  /* not tracked */
841 
842   if (!afl->queued_items && directory == NULL) {
843 
844     SAYF("\n" cLRD "[-] " cRST
845          "Looks like there are no valid test cases in the input directory! The "
846          "fuzzer\n"
847          "    needs one or more test case to start with - ideally, a small "
848          "file under\n"
849          "    1 kB or so. The cases must be stored as regular files directly "
850          "in the\n"
851          "    input directory.\n");
852 
853     FATAL("No usable test cases in '%s'", afl->in_dir);
854 
855   }
856 
857   if (unlikely(afl->shm.cmplog_mode)) {
858 
859     if (afl->cmplog_max_filesize < 1024) {
860 
861       afl->cmplog_max_filesize = 1024;
862 
863     } else {
864 
865       afl->cmplog_max_filesize = (((afl->cmplog_max_filesize >> 10) + 1) << 10);
866 
867     }
868 
869   }
870 
871   afl->last_find_time = 0;
872   afl->queued_at_start = afl->queued_items;
873 
874 }
875 
876 /* Perform dry run of all test cases to confirm that the app is working as
877    expected. This is done only for the initial inputs, and only once. */
878 
879 void perform_dry_run(afl_state_t *afl) {
880 
881   struct queue_entry *q;
882   u32                 cal_failures = 0, idx;
883   u8                 *use_mem;
884 
885   for (idx = 0; idx < afl->queued_items; idx++) {
886 
887     q = afl->queue_buf[idx];
888     if (unlikely(!q || q->disabled)) { continue; }
889 
890     u8  res;
891     s32 fd;
892 
893     if (unlikely(!q->len)) {
894 
895       WARNF("Skipping 0-sized entry in queue (%s)", q->fname);
896       continue;
897 
898     }
899 
900     if (afl->afl_env.afl_cmplog_only_new) { q->colorized = CMPLOG_LVL_MAX; }
901 
902     u8 *fn = strrchr(q->fname, '/') + 1;
903 
904     ACTF("Attempting dry run with '%s'...", fn);
905 
906     fd = open(q->fname, O_RDONLY);
907     if (fd < 0) { PFATAL("Unable to open '%s'", q->fname); }
908 
909     u32 read_len = MIN(q->len, (u32)MAX_FILE);
910     use_mem = afl_realloc(AFL_BUF_PARAM(in), read_len);
911     ck_read(fd, use_mem, read_len, q->fname);
912 
913     close(fd);
914 
915     res = calibrate_case(afl, q, use_mem, 0, 1);
916 
917     if (afl->stop_soon) { return; }
918 
919     if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
920 
921       SAYF(cGRA
922            "    len = %u, map size = %u, exec speed = %llu us, hash = "
923            "%016llx\n" cRST,
924            q->len, q->bitmap_size, q->exec_us, q->exec_cksum);
925 
926     }
927 
928     switch (res) {
929 
930       case FSRV_RUN_OK:
931 
932         if (afl->crash_mode) { FATAL("Test case '%s' does *NOT* crash", fn); }
933 
934         break;
935 
936       case FSRV_RUN_TMOUT:
937 
938         if (afl->timeout_given && !afl->afl_env.afl_exit_on_seed_issues) {
939 
940           /* if we have a timeout but a timeout value was given then always
941              skip. The '+' meaning has been changed! */
942           WARNF("Test case results in a timeout (skipping)");
943           ++cal_failures;
944           q->cal_failed = CAL_CHANCES;
945           q->disabled = 1;
946           q->perf_score = 0;
947 
948           if (!q->was_fuzzed) {
949 
950             q->was_fuzzed = 1;
951             afl->reinit_table = 1;
952             --afl->pending_not_fuzzed;
953             --afl->active_items;
954 
955           }
956 
957           break;
958 
959         } else {
960 
961           static int say_once = 0;
962 
963           if (!say_once) {
964 
965             SAYF(
966                 "\n" cLRD "[-] " cRST
967                 "The program took more than %u ms to process one of the "
968                 "initial "
969                 "test cases.\n"
970                 "    This is bad news; raising the limit with the -t option is "
971                 "possible, but\n"
972                 "    will probably make the fuzzing process extremely slow.\n\n"
973 
974                 "    If this test case is just a fluke, the other option is to "
975                 "just avoid it\n"
976                 "    altogether, and find one that is less of a CPU hog.\n",
977                 afl->fsrv.exec_tmout);
978 
979             if (!afl->afl_env.afl_ignore_seed_problems) {
980 
981               FATAL("Test case '%s' results in a timeout", fn);
982 
983             }
984 
985             say_once = 1;
986 
987           }
988 
989           if (!q->was_fuzzed) {
990 
991             q->was_fuzzed = 1;
992             afl->reinit_table = 1;
993             --afl->pending_not_fuzzed;
994             --afl->active_items;
995 
996           }
997 
998           q->disabled = 1;
999           q->perf_score = 0;
1000 
1001           WARNF("Test case '%s' results in a timeout, skipping", fn);
1002           break;
1003 
1004         }
1005 
1006       case FSRV_RUN_CRASH:
1007 
1008         if (afl->crash_mode) { break; }
1009 
1010         if (afl->fsrv.mem_limit) {
1011 
1012           u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
1013 
1014           SAYF("\n" cLRD "[-] " cRST
1015                "Oops, the program crashed with one of the test cases provided. "
1016                "There are\n"
1017                "    several possible explanations:\n\n"
1018 
1019                "    - The test case causes known crashes under normal working "
1020                "conditions. If\n"
1021                "      so, please remove it. The fuzzer should be seeded with "
1022                "interesting\n"
1023                "      inputs - but not ones that cause an outright crash.\n\n"
1024 
1025                "    - The current memory limit (%s) is too low for this "
1026                "program, causing\n"
1027                "      it to die due to OOM when parsing valid files. To fix "
1028                "this, try\n"
1029                "      bumping it up with the -m setting in the command line. "
1030                "If in doubt,\n"
1031                "      try something along the lines of:\n\n"
1032 
1033                MSG_ULIMIT_USAGE
1034                " /path/to/binary [...] <testcase )\n\n"
1035 
1036                "      Tip: you can use https://jwilk.net/software/recidivm to\n"
1037                "      estimate the required amount of virtual memory for the "
1038                "binary. Also,\n"
1039                "      if you are using ASAN, set '-m 0'.\n\n"
1040 
1041                "    - In QEMU persistent mode the selected address(es) for the "
1042                "loop are not\n"
1043                "      properly cleaning up variables and memory. Try adding\n"
1044                "      AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in "
1045                "the binary.\n\n"
1046 
1047                MSG_FORK_ON_APPLE
1048 
1049                "    - Least likely, there is a horrible bug in the fuzzer. If "
1050                "other options\n"
1051                "      fail, poke the Awesome Fuzzing Discord for "
1052                "troubleshooting tips.\n",
1053                stringify_mem_size(val_buf, sizeof(val_buf),
1054                                   afl->fsrv.mem_limit << 20),
1055                afl->fsrv.mem_limit - 1);
1056 
1057         } else {
1058 
1059           SAYF("\n" cLRD "[-] " cRST
1060                "Oops, the program crashed with one of the test cases provided. "
1061                "There are\n"
1062                "    several possible explanations:\n\n"
1063 
1064                "    - The test case causes known crashes under normal working "
1065                "conditions. If\n"
1066                "      so, please remove it. The fuzzer should be seeded with "
1067                "interesting\n"
1068                "      inputs - but not ones that cause an outright crash.\n\n"
1069 
1070                "    - In QEMU persistent mode the selected address(es) for the "
1071                "loop are not\n"
1072                "      properly cleaning up variables and memory. Try adding\n"
1073                "      AFL_QEMU_PERSISTENT_GPR=1 or select better addresses in "
1074                "the binary.\n\n"
1075 
1076                MSG_FORK_ON_APPLE
1077 
1078                "    - Least likely, there is a horrible bug in the fuzzer. If "
1079                "other options\n"
1080                "      fail, poke the Awesome Fuzzing Discord for "
1081                "troubleshooting tips.\n");
1082 
1083         }
1084 
1085 #undef MSG_ULIMIT_USAGE
1086 #undef MSG_FORK_ON_APPLE
1087 
1088         if (afl->fsrv.uses_crash_exitcode) {
1089 
1090           WARNF(
1091               "Test case '%s' results in a crash or AFL_CRASH_EXITCODE %d, "
1092               "skipping",
1093               fn, (int)(s8)afl->fsrv.crash_exitcode);
1094 
1095         } else {
1096 
1097           if (afl->afl_env.afl_crashing_seeds_as_new_crash) {
1098 
1099             WARNF(
1100                 "Test case '%s' results in a crash, "
1101                 "as AFL_CRASHING_SEEDS_AS_NEW_CRASH is set, "
1102                 "saving as a new crash",
1103                 fn);
1104 
1105           } else {
1106 
1107             WARNF("Test case '%s' results in a crash, skipping", fn);
1108 
1109           }
1110 
1111         }
1112 
1113         if (afl->afl_env.afl_exit_on_seed_issues) {
1114 
1115           FATAL("As AFL_EXIT_ON_SEED_ISSUES is set, afl-fuzz exits.");
1116 
1117         }
1118 
1119         /* Remove from fuzzing queue but keep for splicing */
1120 
1121         if (!q->was_fuzzed) {
1122 
1123           q->was_fuzzed = 1;
1124           afl->reinit_table = 1;
1125           --afl->pending_not_fuzzed;
1126           --afl->active_items;
1127 
1128         }
1129 
1130         /* Crashing seeds will be regarded as new crashes on startup */
1131         if (afl->afl_env.afl_crashing_seeds_as_new_crash) {
1132 
1133           ++afl->total_crashes;
1134 
1135           if (likely(!afl->non_instrumented_mode)) {
1136 
1137             classify_counts(&afl->fsrv);
1138 
1139             simplify_trace(afl, afl->fsrv.trace_bits);
1140 
1141             if (!has_new_bits(afl, afl->virgin_crash)) { break; }
1142 
1143           }
1144 
1145           if (unlikely(!afl->saved_crashes) &&
1146               (afl->afl_env.afl_no_crash_readme != 1)) {
1147 
1148             write_crash_readme(afl);
1149 
1150           }
1151 
1152           u8  crash_fn[PATH_MAX];
1153           u8 *use_name = strstr(q->fname, ",orig:");
1154 
1155           afl->stage_name = "dry_run";
1156           afl->stage_short = "dry_run";
1157 
1158 #ifndef SIMPLE_FILES
1159 
1160           snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s",
1161                    afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
1162                    describe_op(afl, 0,
1163                                NAME_MAX - strlen("id:000000,sig:00,") -
1164                                    strlen(use_name)),
1165                    use_name);
1166 
1167 #else
1168 
1169           snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u",
1170                    afl->out_dir, afl->saved_crashes,
1171                    afl->fsrv.last_kill_signal);
1172 
1173 #endif
1174 
1175           ++afl->saved_crashes;
1176 
1177           fd = open(crash_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
1178           if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", crash_fn); }
1179           ck_write(fd, use_mem, read_len, crash_fn);
1180           close(fd);
1181 
1182           afl->last_crash_time = get_cur_time();
1183           afl->last_crash_execs = afl->fsrv.total_execs;
1184 
1185         } else {
1186 
1187           u32 i = 0;
1188           while (unlikely(i < afl->queued_items && afl->queue_buf[i] &&
1189                           afl->queue_buf[i]->disabled)) {
1190 
1191             ++i;
1192 
1193           }
1194 
1195           if (i < afl->queued_items && afl->queue_buf[i]) {
1196 
1197             afl->queue = afl->queue_buf[i];
1198 
1199           } else {
1200 
1201             afl->queue = afl->queue_buf[0];
1202 
1203           }
1204 
1205           afl->max_depth = 0;
1206           for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) {
1207 
1208             if (!afl->queue_buf[i]->disabled &&
1209                 afl->queue_buf[i]->depth > afl->max_depth)
1210               afl->max_depth = afl->queue_buf[i]->depth;
1211 
1212           }
1213 
1214         }
1215 
1216         q->disabled = 1;
1217         q->perf_score = 0;
1218 
1219         break;
1220 
1221       case FSRV_RUN_ERROR:
1222 
1223         FATAL("Unable to execute target application ('%s')", afl->argv[0]);
1224 
1225       case FSRV_RUN_NOINST:
1226 #ifdef __linux__
1227         if (afl->fsrv.nyx_mode && afl->fsrv.nyx_runner != NULL) {
1228 
1229           afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner);
1230 
1231         }
1232 
1233 #endif
1234         FATAL("No instrumentation detected");
1235 
1236       case FSRV_RUN_NOBITS:
1237 
1238         ++afl->useless_at_start;
1239 
1240         if (!afl->in_bitmap && !afl->shuffle_queue) {
1241 
1242           WARNF("No new instrumentation output, test case may be useless.");
1243 
1244         }
1245 
1246         break;
1247 
1248     }
1249 
1250     if (unlikely(q->var_behavior && !afl->afl_env.afl_no_warn_instability)) {
1251 
1252       WARNF("Instrumentation output varies across runs.");
1253 
1254     }
1255 
1256   }
1257 
1258   if (cal_failures) {
1259 
1260     if (cal_failures == afl->queued_items) {
1261 
1262       FATAL("All test cases time out or crash, giving up!");
1263 
1264     }
1265 
1266     WARNF("Skipped %u test cases (%0.02f%%) due to timeouts or crashes.",
1267           cal_failures, ((double)cal_failures) * 100 / afl->queued_items);
1268 
1269     if (cal_failures * 5 > afl->queued_items) {
1270 
1271       WARNF(cLRD "High percentage of rejected test cases, check settings!");
1272 
1273     }
1274 
1275   }
1276 
1277   /* Now we remove all entries from the queue that have a duplicate trace map */
1278 
1279   u32 duplicates = 0, i;
1280 
1281   for (idx = 0; idx < afl->queued_items - 1; idx++) {
1282 
1283     q = afl->queue_buf[idx];
1284     if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
1285     u32 done = 0;
1286 
1287     for (i = idx + 1;
1288          likely(i < afl->queued_items && afl->queue_buf[i] && !done); ++i) {
1289 
1290       struct queue_entry *p = afl->queue_buf[i];
1291       if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
1292 
1293       if (p->exec_cksum == q->exec_cksum) {
1294 
1295         duplicates = 1;
1296 
1297         // we keep the shorter file
1298         if (p->len >= q->len) {
1299 
1300           if (!p->was_fuzzed) {
1301 
1302             p->was_fuzzed = 1;
1303             afl->reinit_table = 1;
1304             --afl->pending_not_fuzzed;
1305             --afl->active_items;
1306 
1307           }
1308 
1309           p->disabled = 1;
1310           p->perf_score = 0;
1311 
1312           if (afl->debug) {
1313 
1314             WARNF("Same coverage - %s is kept active, %s is disabled.",
1315                   q->fname, p->fname);
1316 
1317           }
1318 
1319         } else {
1320 
1321           if (!q->was_fuzzed) {
1322 
1323             q->was_fuzzed = 1;
1324             afl->reinit_table = 1;
1325             --afl->pending_not_fuzzed;
1326             --afl->active_items;
1327 
1328           }
1329 
1330           q->disabled = 1;
1331           q->perf_score = 0;
1332 
1333           if (afl->debug) {
1334 
1335             WARNF("Same coverage - %s is kept active, %s is disabled.",
1336                   p->fname, q->fname);
1337 
1338           }
1339 
1340           done = 1;  // end inner loop because outer loop entry is disabled now
1341 
1342         }
1343 
1344       }
1345 
1346     }
1347 
1348   }
1349 
1350   if (duplicates) {
1351 
1352     afl->max_depth = 0;
1353 
1354     for (idx = 0; idx < afl->queued_items; idx++) {
1355 
1356       if (afl->queue_buf[idx] && !afl->queue_buf[idx]->disabled &&
1357           afl->queue_buf[idx]->depth > afl->max_depth)
1358         afl->max_depth = afl->queue_buf[idx]->depth;
1359 
1360     }
1361 
1362     afl->queue_top = afl->queue;
1363 
1364   }
1365 
1366   OKF("All test cases processed.");
1367 
1368 }
1369 
1370 /* Helper function: link() if possible, copy otherwise. */
1371 
1372 static void link_or_copy(u8 *old_path, u8 *new_path) {
1373 
1374   s32 i = link(old_path, new_path);
1375   s32 sfd, dfd;
1376   u8 *tmp;
1377 
1378   if (!i) { return; }
1379 
1380   sfd = open(old_path, O_RDONLY);
1381   if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
1382 
1383   dfd = open(new_path, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
1384   if (dfd < 0) { PFATAL("Unable to create '%s'", new_path); }
1385 
1386   tmp = ck_alloc(64 * 1024);
1387 
1388   while ((i = read(sfd, tmp, 64 * 1024)) > 0) {
1389 
1390     ck_write(dfd, tmp, i, new_path);
1391 
1392   }
1393 
1394   if (i < 0) { PFATAL("read() failed"); }
1395 
1396   ck_free(tmp);
1397   close(sfd);
1398   close(dfd);
1399 
1400 }
1401 
1402 /* Create hard links for input test cases in the output directory, choosing
1403    good names and pivoting accordingly. */
1404 
1405 void pivot_inputs(afl_state_t *afl) {
1406 
1407   struct queue_entry *q;
1408   u32                 id = 0, i;
1409 
1410   ACTF("Creating hard links for all input files...");
1411 
1412   for (i = 0; i < afl->queued_items && likely(afl->queue_buf[i]); i++) {
1413 
1414     q = afl->queue_buf[i];
1415 
1416     if (unlikely(q->disabled)) { continue; }
1417 
1418     u8 *nfn, *rsl = strrchr(q->fname, '/');
1419     u32 orig_id;
1420 
1421     if (!rsl) {
1422 
1423       rsl = q->fname;
1424 
1425     } else {
1426 
1427       ++rsl;
1428 
1429     }
1430 
1431     /* If the original file name conforms to the syntax and the recorded
1432        ID matches the one we'd assign, just use the original file name.
1433        This is valuable for resuming fuzzing runs. */
1434 
1435     if (!strncmp(rsl, CASE_PREFIX, 3) &&
1436         sscanf(rsl + 3, "%06u", &orig_id) == 1 && orig_id == id) {
1437 
1438       u8 *src_str;
1439       u32 src_id;
1440 
1441       afl->resuming_fuzz = 1;
1442       nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
1443 
1444       /* Since we're at it, let's also get the parent and figure out the
1445          appropriate depth for this entry. */
1446 
1447       src_str = strchr(rsl + 3, ':');
1448 
1449       if (src_str && sscanf(src_str + 1, "%06u", &src_id) == 1) {
1450 
1451         if (src_id < afl->queued_items) {
1452 
1453           struct queue_entry *s = afl->queue_buf[src_id];
1454 
1455           if (s) { q->depth = s->depth + 1; }
1456 
1457         }
1458 
1459         if (afl->max_depth < q->depth) { afl->max_depth = q->depth; }
1460 
1461       }
1462 
1463     } else {
1464 
1465       /* No dice - invent a new name, capturing the original one as a
1466          substring. */
1467 
1468 #ifndef SIMPLE_FILES
1469 
1470       u8 *use_name = strstr(rsl, ",orig:");
1471 
1472       if (use_name) {
1473 
1474         use_name += 6;
1475 
1476       } else {
1477 
1478         use_name = rsl;
1479 
1480       }
1481 
1482       nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
1483                          afl->out_dir, id, afl->fsrv.total_execs, use_name);
1484 
1485 #else
1486 
1487       nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id);
1488 
1489 #endif                                                    /* ^!SIMPLE_FILES */
1490 
1491     }
1492 
1493     /* Pivot to the new queue entry. */
1494 
1495     link_or_copy(q->fname, nfn);
1496     ck_free(q->fname);
1497     q->fname = nfn;
1498 
1499     /* Make sure that the passed_det value carries over, too. */
1500 
1501     if (q->passed_det) { mark_as_det_done(afl, q); }
1502 
1503     if (afl->custom_mutators_count) {
1504 
1505       run_afl_custom_queue_new_entry(afl, q, q->fname, NULL);
1506 
1507     }
1508 
1509     ++id;
1510 
1511   }
1512 
1513   if (afl->in_place_resume) { nuke_resume_dir(afl); }
1514 
1515 }
1516 
1517 /* When resuming, try to find the queue position to start from. This makes sense
1518    only when resuming, and when we can find the original fuzzer_stats. */
1519 
1520 u32 find_start_position(afl_state_t *afl) {
1521 
1522   u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
1523 
1524   u8 *fn, *off;
1525   s32 fd, i;
1526   u32 ret;
1527 
1528   if (!afl->resuming_fuzz) { return 0; }
1529 
1530   if (afl->in_place_resume) {
1531 
1532     fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1533 
1534   } else {
1535 
1536     fn = alloc_printf("%s/../fuzzer_stats", afl->in_dir);
1537 
1538   }
1539 
1540   fd = open(fn, O_RDONLY);
1541   ck_free(fn);
1542 
1543   if (fd < 0) { return 0; }
1544 
1545   i = read(fd, tmp, sizeof(tmp) - 1);
1546   (void)i;                                                 /* Ignore errors */
1547   close(fd);
1548 
1549   off = strstr(tmp, "cur_item          : ");
1550   if (!off) { return 0; }
1551 
1552   ret = atoi(off + 20);
1553   if (ret >= afl->queued_items) { ret = 0; }
1554   return ret;
1555 
1556 }
1557 
1558 /* The same, but for timeouts. The idea is that when resuming sessions without
1559    -t given, we don't want to keep auto-scaling the timeout over and over
1560    again to prevent it from growing due to random flukes. */
1561 
1562 void find_timeout(afl_state_t *afl) {
1563 
1564   u8 tmp[4096] = {0};                    /* Ought to be enough for anybody. */
1565 
1566   u8 *fn, *off;
1567   s32 fd, i;
1568   u32 ret;
1569 
1570   if (!afl->resuming_fuzz) { return; }
1571 
1572   if (afl->in_place_resume) {
1573 
1574     fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1575 
1576   } else {
1577 
1578     fn = alloc_printf("%s/../fuzzer_stats", afl->in_dir);
1579 
1580   }
1581 
1582   fd = open(fn, O_RDONLY);
1583   ck_free(fn);
1584 
1585   if (fd < 0) { return; }
1586 
1587   i = read(fd, tmp, sizeof(tmp) - 1);
1588   (void)i;                                                 /* Ignore errors */
1589   close(fd);
1590 
1591   off = strstr(tmp, "exec_timeout      : ");
1592   if (!off) { return; }
1593 
1594   ret = atoi(off + 20);
1595   if (ret <= 4) { return; }
1596 
1597   afl->fsrv.exec_tmout = ret;
1598   afl->timeout_given = 3;
1599 
1600 }
1601 
1602 /* A helper function for handle_existing_out_dir(), deleting all prefixed
1603    files in a directory. */
1604 
1605 static u8 delete_files(u8 *path, u8 *prefix) {
1606 
1607   DIR           *d;
1608   struct dirent *d_ent;
1609 
1610   d = opendir(path);
1611 
1612   if (!d) { return 0; }
1613 
1614   while ((d_ent = readdir(d))) {
1615 
1616     if (d_ent->d_name[0] != '.' &&
1617         (!prefix || !strncmp(d_ent->d_name, prefix, strlen(prefix)))) {
1618 
1619       u8 *fname = alloc_printf("%s/%s", path, d_ent->d_name);
1620       if (unlink(fname)) { PFATAL("Unable to delete '%s'", fname); }
1621       ck_free(fname);
1622 
1623     }
1624 
1625   }
1626 
1627   closedir(d);
1628 
1629   return !!rmdir(path);
1630 
1631 }
1632 
1633 /* Get the number of runnable processes, with some simple smoothing. */
1634 
1635 double get_runnable_processes(void) {
1636 
1637   double res = 0;
1638 
1639 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
1640     defined(__NetBSD__) || defined(__DragonFly__)
1641 
1642   /* I don't see any portable sysctl or so that would quickly give us the
1643      number of runnable processes; the 1-minute load average can be a
1644      semi-decent approximation, though. */
1645 
1646   if (getloadavg(&res, 1) != 1) return 0;
1647 
1648 #else
1649 
1650   /* On Linux, /proc/stat is probably the best way; load averages are
1651      computed in funny ways and sometimes don't reflect extremely short-lived
1652      processes well. */
1653 
1654   FILE *f = fopen("/proc/stat", "r");
1655   u8    tmp[1024];
1656   u32   val = 0;
1657 
1658   if (!f) { return 0; }
1659 
1660   while (fgets(tmp, sizeof(tmp), f)) {
1661 
1662     if (!strncmp(tmp, "procs_running ", 14) ||
1663         !strncmp(tmp, "procs_blocked ", 14)) {
1664 
1665       val += atoi(tmp + 14);
1666 
1667     }
1668 
1669   }
1670 
1671   fclose(f);
1672 
1673   if (!res) {
1674 
1675     res = val;
1676 
1677   } else {
1678 
1679     res = res * (1.0 - 1.0 / AVG_SMOOTHING) +
1680           ((double)val) * (1.0 / AVG_SMOOTHING);
1681 
1682   }
1683 
1684 #endif          /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__ || __NetBSD__) */
1685 
1686   return res;
1687 
1688 }
1689 
1690 /* Delete the temporary directory used for in-place session resume. */
1691 
1692 void nuke_resume_dir(afl_state_t *afl) {
1693 
1694   u8 *fn;
1695 
1696   fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
1697   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1698   ck_free(fn);
1699 
1700   fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
1701   if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; }
1702   ck_free(fn);
1703 
1704   fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
1705   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1706   ck_free(fn);
1707 
1708   fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
1709   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1710   ck_free(fn);
1711 
1712   fn = alloc_printf("%s/_resume/.state", afl->out_dir);
1713   if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1714   ck_free(fn);
1715 
1716   fn = alloc_printf("%s/_resume", afl->out_dir);
1717   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1718   ck_free(fn);
1719 
1720   return;
1721 
1722 dir_cleanup_failed:
1723 
1724   FATAL("_resume directory cleanup failed");
1725 
1726 }
1727 
1728 /* Delete fuzzer output directory if we recognize it as ours, if the fuzzer
1729    is not currently running, and if the last run time isn't too great.
1730    Resume fuzzing if `-` is set as in_dir or if AFL_AUTORESUME is set */
1731 
1732 static void handle_existing_out_dir(afl_state_t *afl) {
1733 
1734   FILE *f;
1735   u8   *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1736 
1737   /* See if the output directory is locked. If yes, bail out. If not,
1738      create a lock that will persist for the lifetime of the process
1739      (this requires leaving the descriptor open).*/
1740 
1741   afl->fsrv.out_dir_fd = open(afl->out_dir, O_RDONLY);
1742   if (afl->fsrv.out_dir_fd < 0) { PFATAL("Unable to open '%s'", afl->out_dir); }
1743 
1744 #ifndef __sun
1745 
1746   if (flock(afl->fsrv.out_dir_fd, LOCK_EX | LOCK_NB) && errno == EWOULDBLOCK) {
1747 
1748     SAYF("\n" cLRD "[-] " cRST
1749          "Looks like the job output directory is being actively used by "
1750          "another\n"
1751          "    instance of afl-fuzz. You will need to choose a different %s\n"
1752          "    or stop the other process first.\n",
1753          afl->sync_id ? "fuzzer ID" : "output location");
1754 
1755     FATAL("Directory '%s' is in use", afl->out_dir);
1756 
1757   }
1758 
1759 #endif                                                            /* !__sun */
1760 
1761   f = fopen(fn, "r");
1762 
1763   if (f) {
1764 
1765     u64 start_time2, last_update;
1766 
1767     if (fscanf(f,
1768                "start_time     : %llu\n"
1769                "last_update    : %llu\n",
1770                &start_time2, &last_update) != 2) {
1771 
1772       FATAL("Malformed data in '%s'", fn);
1773 
1774     }
1775 
1776     fclose(f);
1777 
1778     /* Autoresume treats a normal run as in_place_resume if a valid out dir
1779      * already exists */
1780 
1781     if (!afl->in_place_resume && afl->autoresume) {
1782 
1783       OKF("Detected prior run with AFL_AUTORESUME set. Resuming.");
1784       afl->in_place_resume = 1;
1785 
1786     }
1787 
1788     /* Let's see how much work is at stake. */
1789 
1790     if (!afl->in_place_resume && last_update > start_time2 &&
1791         last_update - start_time2 > OUTPUT_GRACE * 60) {
1792 
1793       SAYF("\n" cLRD "[-] " cRST
1794            "The job output directory already exists and contains the results "
1795            "of more\n"
1796            "    than %d minutes worth of fuzzing. To avoid data loss, afl-fuzz "
1797            "will *NOT*\n"
1798            "    automatically delete this data for you.\n\n"
1799 
1800            "    If you wish to start a new session, remove or rename the "
1801            "directory manually,\n"
1802            "    or specify a different output location for this job. To resume "
1803            "the old\n"
1804            "    session, pass '-' as input directory in the command line ('-i "
1805            "-')\n"
1806            "    or set the 'AFL_AUTORESUME=1' env variable and try again.\n",
1807            OUTPUT_GRACE);
1808 
1809       FATAL("At-risk data found in '%s'", afl->out_dir);
1810 
1811     }
1812 
1813   }
1814 
1815   ck_free(fn);
1816 
1817   /* The idea for in-place resume is pretty simple: we temporarily move the old
1818      queue/ to a new location that gets deleted once import to the new queue/
1819      is finished. If _resume/ already exists, the current queue/ may be
1820      incomplete due to an earlier abort, so we want to use the old _resume/
1821      dir instead, and we let rename() fail silently. */
1822 
1823   if (afl->in_place_resume) {
1824 
1825     u8 *orig_q = alloc_printf("%s/queue", afl->out_dir);
1826 
1827     afl->in_dir = alloc_printf("%s/_resume", afl->out_dir);
1828 
1829     rename(orig_q, afl->in_dir);                           /* Ignore errors */
1830 
1831     OKF("Output directory exists, will attempt session resume.");
1832 
1833     ck_free(orig_q);
1834 
1835   } else {
1836 
1837     OKF("Output directory exists but deemed OK to reuse.");
1838 
1839   }
1840 
1841   ACTF("Deleting old session data...");
1842 
1843   /* Okay, let's get the ball rolling! First, we need to get rid of the entries
1844      in <afl->out_dir>/.synced/.../id:*, if any are present. */
1845 
1846   if (!afl->in_place_resume) {
1847 
1848     fn = alloc_printf("%s/.synced", afl->out_dir);
1849     if (delete_files(fn, NULL)) { goto dir_cleanup_failed; }
1850     ck_free(fn);
1851 
1852   }
1853 
1854   /* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
1855 
1856   fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
1857   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1858   ck_free(fn);
1859 
1860   fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
1861   if (delete_files(fn, "auto_")) { goto dir_cleanup_failed; }
1862   ck_free(fn);
1863 
1864   fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
1865   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1866   ck_free(fn);
1867 
1868   fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
1869   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1870   ck_free(fn);
1871 
1872   /* Then, get rid of the .state subdirectory itself (should be empty by now)
1873      and everything matching <afl->out_dir>/queue/id:*. */
1874 
1875   fn = alloc_printf("%s/queue/.state", afl->out_dir);
1876   if (rmdir(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1877   ck_free(fn);
1878 
1879   fn = alloc_printf("%s/queue", afl->out_dir);
1880   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1881   ck_free(fn);
1882 
1883   /* All right, let's do <afl->out_dir>/crashes/id:* and
1884    * <afl->out_dir>/hangs/id:*. */
1885 
1886   if (!afl->in_place_resume) {
1887 
1888     fn = alloc_printf("%s/crashes/README.txt", afl->out_dir);
1889     unlink(fn);                                            /* Ignore errors */
1890     ck_free(fn);
1891 
1892   }
1893 
1894   fn = alloc_printf("%s/crashes", afl->out_dir);
1895 
1896   /* Make backup of the crashes directory if it's not empty and if we're
1897      doing in-place resume. */
1898 
1899   if (afl->in_place_resume && rmdir(fn)) {
1900 
1901     time_t    cur_t = time(0);
1902     struct tm t;
1903     localtime_r(&cur_t, &t);
1904 
1905 #ifndef SIMPLE_FILES
1906 
1907     u8 *nfn =
1908         alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, t.tm_year + 1900,
1909                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1910 
1911 #else
1912 
1913     u8 *nfn =
1914         alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t.tm_year + 1900,
1915                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1916 
1917 #endif                                                    /* ^!SIMPLE_FILES */
1918 
1919     rename(fn, nfn);                                      /* Ignore errors. */
1920     ck_free(nfn);
1921 
1922   }
1923 
1924   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1925   ck_free(fn);
1926 
1927   fn = alloc_printf("%s/hangs", afl->out_dir);
1928 
1929   /* Backup hangs, too. */
1930 
1931   if (afl->in_place_resume && rmdir(fn)) {
1932 
1933     time_t    cur_t = time(0);
1934     struct tm t;
1935     localtime_r(&cur_t, &t);
1936 
1937 #ifndef SIMPLE_FILES
1938 
1939     u8 *nfn =
1940         alloc_printf("%s.%04d-%02d-%02d-%02d:%02d:%02d", fn, t.tm_year + 1900,
1941                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1942 
1943 #else
1944 
1945     u8 *nfn =
1946         alloc_printf("%s_%04d%02d%02d%02d%02d%02d", fn, t.tm_year + 1900,
1947                      t.tm_mon + 1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
1948 
1949 #endif                                                    /* ^!SIMPLE_FILES */
1950 
1951     rename(fn, nfn);                                      /* Ignore errors. */
1952     ck_free(nfn);
1953 
1954   }
1955 
1956   if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
1957   ck_free(fn);
1958 
1959   /* And now, for some finishing touches. */
1960 
1961   if (afl->file_extension) {
1962 
1963     fn = alloc_printf("%s/.cur_input.%s", afl->out_dir, afl->file_extension);
1964 
1965   } else {
1966 
1967     fn = alloc_printf("%s/.cur_input", afl->out_dir);
1968 
1969   }
1970 
1971   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1972   ck_free(fn);
1973 
1974   if (afl->afl_env.afl_tmpdir) {
1975 
1976     if (afl->file_extension) {
1977 
1978       fn = alloc_printf("%s/.cur_input.%s", afl->afl_env.afl_tmpdir,
1979                         afl->file_extension);
1980 
1981     } else {
1982 
1983       fn = alloc_printf("%s/.cur_input", afl->afl_env.afl_tmpdir);
1984 
1985     }
1986 
1987     if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1988     ck_free(fn);
1989 
1990   }
1991 
1992   fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
1993   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
1994   ck_free(fn);
1995 
1996   if (!afl->in_place_resume) {
1997 
1998     fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
1999     if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
2000     ck_free(fn);
2001 
2002   }
2003 
2004   if (!afl->in_place_resume) {
2005 
2006     fn = alloc_printf("%s/plot_data", afl->out_dir);
2007     if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
2008     ck_free(fn);
2009 
2010   }
2011 
2012   fn = alloc_printf("%s/queue_data", afl->out_dir);
2013   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
2014   ck_free(fn);
2015 
2016   fn = alloc_printf("%s/cmdline", afl->out_dir);
2017   if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
2018   ck_free(fn);
2019 
2020   OKF("Output dir cleanup successful.");
2021 
2022   /* Wow... is that all? If yes, celebrate! */
2023 
2024   return;
2025 
2026 dir_cleanup_failed:
2027 
2028   SAYF("\n" cLRD "[-] " cRST
2029        "Whoops, the fuzzer tried to reuse your output directory, but bumped "
2030        "into\n"
2031        "    some files that shouldn't be there or that couldn't be removed - "
2032        "so it\n"
2033        "    decided to abort! This happened while processing this path:\n\n"
2034 
2035        "    %s\n\n"
2036        "    Please examine and manually delete the files, or specify a "
2037        "different\n"
2038        "    output location for the tool.\n",
2039        fn);
2040 
2041   FATAL("Output directory cleanup failed");
2042 
2043 }
2044 
2045 /* If this is a -S secondary node, ensure a -M main node is running,
2046   if a main node is running when another main is started, then warn */
2047 
2048 int check_main_node_exists(afl_state_t *afl) {
2049 
2050   DIR           *sd;
2051   struct dirent *sd_ent;
2052   u8            *fn;
2053 
2054   sd = opendir(afl->sync_dir);
2055   if (!sd) { return 0; }
2056 
2057   while ((sd_ent = readdir(sd))) {
2058 
2059     /* Skip dot files and our own output directory. */
2060 
2061     if (sd_ent->d_name[0] == '.' || !strcmp(afl->sync_id, sd_ent->d_name)) {
2062 
2063       continue;
2064 
2065     }
2066 
2067     fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name);
2068     int res = access(fn, F_OK);
2069     free(fn);
2070     if (res == 0) return 1;
2071 
2072   }
2073 
2074   return 0;
2075 
2076 }
2077 
2078 /* Prepare output directories and fds. */
2079 
2080 void setup_dirs_fds(afl_state_t *afl) {
2081 
2082   u8 *tmp;
2083 
2084   ACTF("Setting up output directories...");
2085 
2086   if (afl->sync_id && mkdir(afl->sync_dir, 0700) && errno != EEXIST) {
2087 
2088     PFATAL("Unable to create '%s'", afl->sync_dir);
2089 
2090   }
2091 
2092   if (mkdir(afl->out_dir, 0700)) {
2093 
2094     if (errno != EEXIST) { PFATAL("Unable to create '%s'", afl->out_dir); }
2095 
2096     handle_existing_out_dir(afl);
2097 
2098   } else {
2099 
2100     if (afl->in_place_resume) {
2101 
2102       FATAL("Resume attempted but old output directory not found");
2103 
2104     }
2105 
2106     afl->fsrv.out_dir_fd = open(afl->out_dir, O_RDONLY);
2107 
2108 #ifndef __sun
2109 
2110     if (afl->fsrv.out_dir_fd < 0 ||
2111         flock(afl->fsrv.out_dir_fd, LOCK_EX | LOCK_NB)) {
2112 
2113       PFATAL("Unable to flock() output directory.");
2114 
2115     }
2116 
2117 #endif                                                            /* !__sun */
2118 
2119   }
2120 
2121   if (afl->is_main_node) {
2122 
2123     u8 *x = alloc_printf("%s/is_main_node", afl->out_dir);
2124     int fd = open(x, O_CREAT | O_RDWR, 0644);
2125     if (fd < 0) FATAL("cannot create %s", x);
2126     free(x);
2127     close(fd);
2128 
2129   }
2130 
2131   /* Queue directory for any starting & discovered paths. */
2132 
2133   tmp = alloc_printf("%s/queue", afl->out_dir);
2134   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2135   ck_free(tmp);
2136 
2137   /* Top-level directory for queue metadata used for session
2138      resume and related tasks. */
2139 
2140   tmp = alloc_printf("%s/queue/.state/", afl->out_dir);
2141   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2142   ck_free(tmp);
2143 
2144   /* Directory for flagging queue entries that went through
2145      deterministic fuzzing in the past. */
2146 
2147   tmp = alloc_printf("%s/queue/.state/deterministic_done/", afl->out_dir);
2148   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2149   ck_free(tmp);
2150 
2151   /* Directory with the auto-selected dictionary entries. */
2152 
2153   tmp = alloc_printf("%s/queue/.state/auto_extras/", afl->out_dir);
2154   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2155   ck_free(tmp);
2156 
2157   /* The set of paths currently deemed redundant. */
2158 
2159   tmp = alloc_printf("%s/queue/.state/redundant_edges/", afl->out_dir);
2160   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2161   ck_free(tmp);
2162 
2163   /* The set of paths showing variable behavior. */
2164 
2165   tmp = alloc_printf("%s/queue/.state/variable_behavior/", afl->out_dir);
2166   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2167   ck_free(tmp);
2168 
2169   /* Sync directory for keeping track of cooperating fuzzers. */
2170 
2171   if (afl->sync_id) {
2172 
2173     tmp = alloc_printf("%s/.synced/", afl->out_dir);
2174 
2175     if (mkdir(tmp, 0700) && (!afl->in_place_resume || errno != EEXIST)) {
2176 
2177       PFATAL("Unable to create '%s'", tmp);
2178 
2179     }
2180 
2181     ck_free(tmp);
2182 
2183   }
2184 
2185   /* All recorded crashes. */
2186 
2187   tmp = alloc_printf("%s/crashes", afl->out_dir);
2188   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2189   ck_free(tmp);
2190 
2191   /* All recorded hangs. */
2192 
2193   tmp = alloc_printf("%s/hangs", afl->out_dir);
2194   if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
2195   ck_free(tmp);
2196 
2197   /* Generally useful file descriptors. */
2198 
2199   afl->fsrv.dev_null_fd = open("/dev/null", O_RDWR);
2200   if (afl->fsrv.dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
2201 
2202   afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
2203   if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
2204 
2205   /* Gnuplot output file. */
2206 
2207   tmp = alloc_printf("%s/plot_data", afl->out_dir);
2208 
2209   if (!afl->in_place_resume) {
2210 
2211     int fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
2212     if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2213     ck_free(tmp);
2214 
2215     afl->fsrv.plot_file = fdopen(fd, "w");
2216     if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
2217 
2218     fprintf(
2219         afl->fsrv.plot_file,
2220         "# relative_time, cycles_done, cur_item, corpus_count, "
2221         "pending_total, pending_favs, map_size, saved_crashes, "
2222         "saved_hangs, max_depth, execs_per_sec, total_execs, edges_found\n");
2223 
2224   } else {
2225 
2226     int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION);
2227     if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2228     ck_free(tmp);
2229 
2230     afl->fsrv.plot_file = fdopen(fd, "w");
2231     if (!afl->fsrv.plot_file) { PFATAL("fdopen() failed"); }
2232 
2233     fseek(afl->fsrv.plot_file, 0, SEEK_END);
2234 
2235   }
2236 
2237   fflush(afl->fsrv.plot_file);
2238 
2239 #ifdef INTROSPECTION
2240 
2241   tmp = alloc_printf("%s/plot_det_data", afl->out_dir);
2242 
2243   int fd = open(tmp, O_WRONLY | O_CREAT, DEFAULT_PERMISSION);
2244   if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2245   ck_free(tmp);
2246 
2247   afl->fsrv.det_plot_file = fdopen(fd, "w");
2248   if (!afl->fsrv.det_plot_file) { PFATAL("fdopen() failed"); }
2249 
2250   if (afl->in_place_resume) { fseek(afl->fsrv.det_plot_file, 0, SEEK_END); }
2251 
2252 #endif
2253 
2254   /* ignore errors */
2255 
2256 }
2257 
2258 void setup_cmdline_file(afl_state_t *afl, char **argv) {
2259 
2260   u8 *tmp;
2261   s32 fd;
2262   u32 i = 0;
2263 
2264   FILE *cmdline_file = NULL;
2265 
2266   /* Store the command line to reproduce our findings */
2267   tmp = alloc_printf("%s/cmdline", afl->out_dir);
2268   fd = open(tmp, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
2269   if (fd < 0) { PFATAL("Unable to create '%s'", tmp); }
2270   ck_free(tmp);
2271 
2272   cmdline_file = fdopen(fd, "w");
2273   if (!cmdline_file) { PFATAL("fdopen() failed"); }
2274 
2275   while (argv[i]) {
2276 
2277     fprintf(cmdline_file, "%s\n", argv[i]);
2278     ++i;
2279 
2280   }
2281 
2282   fclose(cmdline_file);
2283 
2284 }
2285 
2286 /* Setup the output file for fuzzed data, if not using -f. */
2287 
2288 void setup_stdio_file(afl_state_t *afl) {
2289 
2290   if (afl->file_extension) {
2291 
2292     afl->fsrv.out_file =
2293         alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
2294 
2295   } else {
2296 
2297     afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
2298 
2299   }
2300 
2301   unlink(afl->fsrv.out_file);                              /* Ignore errors */
2302 
2303   afl->fsrv.out_fd =
2304       open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
2305 
2306   if (afl->fsrv.out_fd < 0) {
2307 
2308     PFATAL("Unable to create '%s'", afl->fsrv.out_file);
2309 
2310   }
2311 
2312 }
2313 
2314 /* Make sure that core dumps don't go to a program. */
2315 
2316 void check_crash_handling(void) {
2317 
2318 #ifdef __APPLE__
2319 
2320   /* Yuck! There appears to be no simple C API to query for the state of
2321      loaded daemons on MacOS X, and I'm a bit hesitant to do something
2322      more sophisticated, such as disabling crash reporting via Mach ports,
2323      until I get a box to test the code. So, for now, we check for crash
2324      reporting the awful way. */
2325 
2326   #if !TARGET_OS_IPHONE
2327   if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash\\>'"))
2328     return;
2329 
2330   SAYF(
2331       "\n" cLRD "[-] " cRST
2332       "Whoops, your system is configured to forward crash notifications to an\n"
2333       "    external crash reporting utility. This will cause issues due to "
2334       "the\n"
2335       "    extended delay between the fuzzed binary malfunctioning and this "
2336       "fact\n"
2337       "    being relayed to the fuzzer via the standard waitpid() API.\n\n"
2338       "    To avoid having crashes misinterpreted as timeouts, please run the\n"
2339       "    following commands:\n\n"
2340 
2341       "    SL=/System/Library; PL=com.apple.ReportCrash\n"
2342       "    launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n"
2343       "    sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n");
2344 
2345   #endif
2346   if (!get_afl_env("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))
2347     FATAL("Crash reporter detected");
2348 
2349 #else
2350 
2351   /* This is Linux specific, but I don't think there's anything equivalent on
2352    *BSD, so we can just let it slide for now. */
2353 
2354   s32 fd = open("/proc/sys/kernel/core_pattern", O_RDONLY);
2355   u8  fchar;
2356 
2357   if (fd < 0) { return; }
2358 
2359   ACTF("Checking core_pattern...");
2360 
2361   if (read(fd, &fchar, 1) == 1 && fchar == '|') {
2362 
2363     SAYF(
2364         "\n" cLRD "[-] " cRST
2365         "Hmm, your system is configured to send core dump notifications to an\n"
2366         "    external utility. This will cause issues: there will be an "
2367         "extended delay\n"
2368         "    between stumbling upon a crash and having this information "
2369         "relayed to the\n"
2370         "    fuzzer via the standard waitpid() API.\n"
2371         "    If you're just testing, set "
2372         "'AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1'.\n\n"
2373 
2374         "    To avoid having crashes misinterpreted as timeouts, please log in "
2375         "as root\n"
2376         "    and temporarily modify /proc/sys/kernel/core_pattern, like so:\n\n"
2377 
2378         "    echo core >/proc/sys/kernel/core_pattern\n");
2379 
2380     if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES")) {
2381 
2382       FATAL("Pipe at the beginning of 'core_pattern'");
2383 
2384     }
2385 
2386   }
2387 
2388   close(fd);
2389 
2390 #endif                                                        /* ^__APPLE__ */
2391 
2392 }
2393 
2394 /* Check CPU governor. */
2395 
2396 void check_cpu_governor(afl_state_t *afl) {
2397 
2398 #ifdef __linux__
2399   FILE *f;
2400   u8    tmp[128];
2401   u64   min = 0, max = 0;
2402 
2403   if (afl->afl_env.afl_skip_cpufreq) { return; }
2404 
2405   if (afl->cpu_aff > 0) {
2406 
2407     snprintf(tmp, sizeof(tmp), "%s%d%s", "/sys/devices/system/cpu/cpu",
2408              afl->cpu_aff, "/cpufreq/scaling_governor");
2409 
2410   } else {
2411 
2412     snprintf(tmp, sizeof(tmp), "%s",
2413              "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor");
2414 
2415   }
2416 
2417   f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor", "r");
2418   if (!f) {
2419 
2420     if (afl->cpu_aff > 0) {
2421 
2422       snprintf(tmp, sizeof(tmp), "%s%d%s",
2423                "/sys/devices/system/cpu/cpufreq/policy", afl->cpu_aff,
2424                "/scaling_governor");
2425 
2426     } else {
2427 
2428       snprintf(tmp, sizeof(tmp), "%s",
2429                "/sys/devices/system/cpu/cpufreq/policy0/scaling_governor");
2430 
2431     }
2432 
2433     f = fopen(tmp, "r");
2434 
2435   }
2436 
2437   if (!f) {
2438 
2439     WARNF("Could not check CPU scaling governor");
2440     return;
2441 
2442   }
2443 
2444   ACTF("Checking CPU scaling governor...");
2445 
2446   if (!fgets(tmp, 128, f)) { PFATAL("fgets() failed"); }
2447 
2448   fclose(f);
2449 
2450   if (!strncmp(tmp, "perf", 4)) { return; }
2451 
2452   f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_min_freq", "r");
2453 
2454   if (f) {
2455 
2456     if (fscanf(f, "%llu", &min) != 1) { min = 0; }
2457     fclose(f);
2458 
2459   }
2460 
2461   f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/scaling_max_freq", "r");
2462 
2463   if (f) {
2464 
2465     if (fscanf(f, "%llu", &max) != 1) { max = 0; }
2466     fclose(f);
2467 
2468   }
2469 
2470   if (min == max) { return; }
2471 
2472   SAYF("\n" cLRD "[-] " cRST
2473        "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n"
2474        "    between %llu and %llu MHz. Unfortunately, the scaling algorithm in "
2475        "the\n"
2476        "    kernel is imperfect and can miss the short-lived processes spawned "
2477        "by\n"
2478        "    afl-fuzz. To keep things moving, run these commands as root:\n\n"
2479 
2480        "    cd /sys/devices/system/cpu\n"
2481        "    echo performance | tee cpu*/cpufreq/scaling_governor\n\n"
2482 
2483        "    You can later go back to the original state by replacing "
2484        "'performance'\n"
2485        "    with 'ondemand' or 'powersave'. If you don't want to change the "
2486        "settings,\n"
2487        "    set AFL_SKIP_CPUFREQ to make afl-fuzz skip this check - but expect "
2488        "some\n"
2489        "    performance drop.\n",
2490        min / 1024, max / 1024);
2491   FATAL("Suboptimal CPU scaling governor");
2492 
2493 #elif defined __APPLE__
2494   u64    min = 0, max = 0;
2495   size_t mlen = sizeof(min);
2496   if (afl->afl_env.afl_skip_cpufreq) return;
2497 
2498   ACTF("Checking CPU scaling governor...");
2499 
2500   if (sysctlbyname("hw.cpufrequency_min", &min, &mlen, NULL, 0) == -1) {
2501 
2502     WARNF("Could not check CPU min frequency");
2503     return;
2504 
2505   }
2506 
2507   if (sysctlbyname("hw.cpufrequency_max", &max, &mlen, NULL, 0) == -1) {
2508 
2509     WARNF("Could not check CPU max frequency");
2510     return;
2511 
2512   }
2513 
2514   if (min == max) return;
2515 
2516   SAYF("\n" cLRD "[-] " cRST
2517        "Whoops, your system uses on-demand CPU frequency scaling, adjusted\n"
2518        "    between %llu and %llu MHz.\n"
2519        "    If you don't want to check those settings, set "
2520        "AFL_SKIP_CPUFREQ\n"
2521        "    to make afl-fuzz skip this check - but expect some performance "
2522        "drop.\n",
2523        min / 1024, max / 1024);
2524   FATAL("Suboptimal CPU scaling governor");
2525 #else
2526   (void)afl;
2527 #endif
2528 
2529 }
2530 
2531 /* Count the number of logical CPU cores. */
2532 
2533 void get_core_count(afl_state_t *afl) {
2534 
2535 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
2536     defined(__DragonFly__)
2537 
2538   size_t s = sizeof(afl->cpu_core_count);
2539 
2540   /* On *BSD systems, we can just use a sysctl to get the number of CPUs. */
2541 
2542   #ifdef __APPLE__
2543 
2544   if (sysctlbyname("hw.logicalcpu", &afl->cpu_core_count, &s, NULL, 0) < 0)
2545     return;
2546 
2547   #else
2548 
2549   int s_name[2] = {CTL_HW, HW_NCPU};
2550 
2551   if (sysctl(s_name, 2, &afl->cpu_core_count, &s, NULL, 0) < 0) return;
2552 
2553   #endif                                                      /* ^__APPLE__ */
2554 
2555 #else
2556 
2557   #ifdef HAVE_AFFINITY
2558 
2559   afl->cpu_core_count = sysconf(_SC_NPROCESSORS_ONLN);
2560 
2561   #else
2562 
2563   FILE *f = fopen("/proc/stat", "r");
2564   u8    tmp[1024];
2565 
2566   if (!f) return;
2567 
2568   while (fgets(tmp, sizeof(tmp), f))
2569     if (!strncmp(tmp, "cpu", 3) && isdigit(tmp[3])) ++afl->cpu_core_count;
2570 
2571   fclose(f);
2572 
2573   #endif                                                  /* ^HAVE_AFFINITY */
2574 
2575 #endif                        /* ^(__APPLE__ || __FreeBSD__ || __OpenBSD__) */
2576 
2577   if (afl->cpu_core_count > 0) {
2578 
2579     u32 cur_runnable = 0;
2580 
2581     cur_runnable = (u32)get_runnable_processes();
2582 
2583 #if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
2584     defined(__DragonFly__)
2585 
2586     /* Add ourselves, since the 1-minute average doesn't include that yet. */
2587 
2588     ++cur_runnable;
2589 
2590 #endif                           /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
2591 
2592     OKF("You have %d CPU core%s and %u runnable tasks (utilization: %0.0f%%).",
2593         afl->cpu_core_count, afl->cpu_core_count > 1 ? "s" : "", cur_runnable,
2594         cur_runnable * 100.0 / afl->cpu_core_count);
2595 
2596     if (afl->cpu_core_count > 1) {
2597 
2598       if (cur_runnable > afl->cpu_core_count * 1.5) {
2599 
2600         WARNF("System under apparent load, performance may be spotty.");
2601 
2602       } else if ((s64)cur_runnable + 1 <= (s64)afl->cpu_core_count) {
2603 
2604         OKF("Try parallel jobs - see "
2605             "%s/fuzzing_in_depth.md#c-using-multiple-cores",
2606             doc_path);
2607 
2608       }
2609 
2610     }
2611 
2612   } else {
2613 
2614     afl->cpu_core_count = 0;
2615     WARNF("Unable to figure out the number of CPU cores.");
2616 
2617   }
2618 
2619 }
2620 
2621 /* Validate and fix up afl->out_dir and sync_dir when using -S. */
2622 
2623 void fix_up_sync(afl_state_t *afl) {
2624 
2625   u8 *x = afl->sync_id;
2626 
2627   while (*x) {
2628 
2629     if (!isalnum(*x) && *x != '_' && *x != '-') {
2630 
2631       FATAL("Non-alphanumeric fuzzer ID specified via -S or -M");
2632 
2633     }
2634 
2635     ++x;
2636 
2637   }
2638 
2639   if (strlen(afl->sync_id) > 32) { FATAL("Fuzzer ID too long"); }
2640 
2641   x = alloc_printf("%s/%s", afl->out_dir, afl->sync_id);
2642 
2643 #ifdef __linux__
2644   if (afl->fsrv.nyx_mode) { afl->fsrv.out_dir_path = afl->out_dir; }
2645 #endif
2646   afl->sync_dir = afl->out_dir;
2647   afl->out_dir = x;
2648 
2649 }
2650 
2651 /* Handle screen resize (SIGWINCH). */
2652 
2653 static void handle_resize(int sig) {
2654 
2655   (void)sig;
2656   afl_states_clear_screen();
2657 
2658 }
2659 
2660 /* Check ASAN options. */
2661 
2662 void check_asan_opts(afl_state_t *afl) {
2663 
2664   u8 *x = get_afl_env("ASAN_OPTIONS");
2665 
2666   (void)(afl);
2667 
2668   if (x) {
2669 
2670     if (!strstr(x, "abort_on_error=1")) {
2671 
2672       FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
2673 
2674     }
2675 
2676 #ifndef ASAN_BUILD
2677     if (!afl->debug && !strstr(x, "symbolize=0")) {
2678 
2679       FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
2680 
2681     }
2682 
2683 #endif
2684 
2685   }
2686 
2687   x = get_afl_env("MSAN_OPTIONS");
2688 
2689   if (x) {
2690 
2691     if (!strstr(x, "exit_code=" STRINGIFY(MSAN_ERROR))) {
2692 
2693       FATAL("Custom MSAN_OPTIONS set without exit_code=" STRINGIFY(
2694           MSAN_ERROR) " - please fix!");
2695 
2696     }
2697 
2698     if (!afl->debug && !strstr(x, "symbolize=0")) {
2699 
2700       FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
2701 
2702     }
2703 
2704   }
2705 
2706   x = get_afl_env("LSAN_OPTIONS");
2707 
2708   if (x) {
2709 
2710     if (!strstr(x, "symbolize=0")) {
2711 
2712       FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
2713 
2714     }
2715 
2716   }
2717 
2718 }
2719 
2720 /* Handle stop signal (Ctrl-C, etc). */
2721 
2722 static void handle_stop_sig(int sig) {
2723 
2724   (void)sig;
2725   afl_states_stop();
2726 
2727 }
2728 
2729 /* Handle skip request (SIGUSR1). */
2730 
2731 static void handle_skipreq(int sig) {
2732 
2733   (void)sig;
2734   afl_states_request_skip();
2735 
2736 }
2737 
2738 /* Setup shared map for fuzzing with input via sharedmem */
2739 
2740 void setup_testcase_shmem(afl_state_t *afl) {
2741 
2742   afl->shm_fuzz = ck_alloc(sizeof(sharedmem_t));
2743 
2744   // we need to set the non-instrumented mode to not overwrite the SHM_ENV_VAR
2745   u8 *map = afl_shm_init(afl->shm_fuzz, MAX_FILE + sizeof(u32), 1);
2746   afl->shm_fuzz->shmemfuzz_mode = 1;
2747 
2748   if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
2749 
2750 #ifdef USEMMAP
2751   setenv(SHM_FUZZ_ENV_VAR, afl->shm_fuzz->g_shm_file_path, 1);
2752 #else
2753   u8 *shm_str = alloc_printf("%d", afl->shm_fuzz->shm_id);
2754   setenv(SHM_FUZZ_ENV_VAR, shm_str, 1);
2755   ck_free(shm_str);
2756 #endif
2757   afl->fsrv.support_shmem_fuzz = 1;
2758   afl->fsrv.shmem_fuzz_len = (u32 *)map;
2759   afl->fsrv.shmem_fuzz = map + sizeof(u32);
2760 
2761 }
2762 
2763 /* Do a PATH search and find target binary to see that it exists and
2764    isn't a shell script - a common and painful mistake. We also check for
2765    a valid ELF header and for evidence of AFL instrumentation. */
2766 
2767 void check_binary(afl_state_t *afl, u8 *fname) {
2768 
2769   if (unlikely(!fname)) { FATAL("BUG: Binary name is NULL"); }
2770 
2771   u8         *env_path = 0;
2772   struct stat st;
2773 
2774   s32 fd;
2775   u8 *f_data;
2776   u32 f_len = 0;
2777 
2778   ACTF("Validating target binary...");
2779 
2780   if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
2781 
2782     afl->fsrv.target_path = ck_strdup(fname);
2783 #ifdef __linux__
2784     if (afl->fsrv.nyx_mode) {
2785 
2786       /* check if target_path is a nyx sharedir */
2787       if (stat(afl->fsrv.target_path, &st) || S_ISDIR(st.st_mode)) {
2788 
2789         char *tmp = alloc_printf("%s/config.ron", afl->fsrv.target_path);
2790         if (stat(tmp, &st) || S_ISREG(st.st_mode)) {
2791 
2792           free(tmp);
2793           return;
2794 
2795         }
2796 
2797       }
2798 
2799       FATAL("Directory '%s' not found or is not a nyx share directory",
2800             afl->fsrv.target_path);
2801 
2802     }
2803 
2804 #endif
2805     if (stat(afl->fsrv.target_path, &st) || !S_ISREG(st.st_mode) ||
2806         !(st.st_mode & 0111) || (f_len = st.st_size) < 4) {
2807 
2808       FATAL("Program '%s' not found or not executable", fname);
2809 
2810     }
2811 
2812   } else {
2813 
2814     while (env_path) {
2815 
2816       u8 *cur_elem, *delim = strchr(env_path, ':');
2817 
2818       if (delim) {
2819 
2820         cur_elem = ck_alloc(delim - env_path + 1);
2821         if (unlikely(!cur_elem)) { FATAL("Unexpected large PATH"); }
2822         memcpy(cur_elem, env_path, delim - env_path);
2823         ++delim;
2824 
2825       } else {
2826 
2827         cur_elem = ck_strdup(env_path);
2828 
2829       }
2830 
2831       env_path = delim;
2832 
2833       if (cur_elem[0]) {
2834 
2835         afl->fsrv.target_path = alloc_printf("%s/%s", cur_elem, fname);
2836 
2837       } else {
2838 
2839         afl->fsrv.target_path = ck_strdup(fname);
2840 
2841       }
2842 
2843       ck_free(cur_elem);
2844 
2845       if (!stat(afl->fsrv.target_path, &st) && S_ISREG(st.st_mode) &&
2846           (st.st_mode & 0111) && (f_len = st.st_size) >= 4) {
2847 
2848         break;
2849 
2850       }
2851 
2852       ck_free(afl->fsrv.target_path);
2853       afl->fsrv.target_path = 0;
2854 
2855     }
2856 
2857     if (!afl->fsrv.target_path) {
2858 
2859       FATAL("Program '%s' not found or not executable", fname);
2860 
2861     }
2862 
2863   }
2864 
2865   if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode ||
2866       (afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
2867       (afl->fsrv.cs_mode && getenv("AFL_CS_CUSTOM_BIN")) ||
2868       afl->non_instrumented_mode) {
2869 
2870     return;
2871 
2872   }
2873 
2874   /* Check for blatant user errors. */
2875 
2876   /*  disabled. not a real-worl scenario where this is a problem.
2877     if ((!strncmp(afl->fsrv.target_path, "/tmp/", 5) &&
2878          !strchr(afl->fsrv.target_path + 5, '/')) ||
2879         (!strncmp(afl->fsrv.target_path, "/var/tmp/", 9) &&
2880          !strchr(afl->fsrv.target_path + 9, '/'))) {
2881 
2882       FATAL("Please don't keep binaries in /tmp or /var/tmp");
2883 
2884     }
2885 
2886   */
2887 
2888   fd = open(afl->fsrv.target_path, O_RDONLY);
2889 
2890   if (fd < 0) { PFATAL("Unable to open '%s'", afl->fsrv.target_path); }
2891 
2892   f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
2893 
2894   if (f_data == MAP_FAILED) {
2895 
2896     PFATAL("Unable to mmap file '%s'", afl->fsrv.target_path);
2897 
2898   }
2899 
2900   close(fd);
2901 
2902   if (f_data[0] == '#' && f_data[1] == '!') {
2903 
2904     SAYF("\n" cLRD "[-] " cRST
2905          "Oops, the target binary looks like a shell script. Some build "
2906          "systems will\n"
2907          "    sometimes generate shell stubs for dynamically linked programs; "
2908          "try static\n"
2909          "    library mode (./configure --disable-shared) if that's the "
2910          "case.\n\n"
2911 
2912          "    Another possible cause is that you are actually trying to use a "
2913          "shell\n"
2914          "    wrapper around the fuzzed component. Invoking shell can slow "
2915          "down the\n"
2916          "    fuzzing process by a factor of 20x or more; it's best to write "
2917          "the wrapper\n"
2918          "    in a compiled language instead.\n");
2919 
2920     FATAL("Program '%s' is a shell script", afl->fsrv.target_path);
2921 
2922   }
2923 
2924 #ifndef __APPLE__
2925 
2926   if (f_data[0] != 0x7f || memcmp(f_data + 1, "ELF", 3)) {
2927 
2928     FATAL("Program '%s' is not an ELF binary", afl->fsrv.target_path);
2929 
2930   }
2931 
2932 #else
2933 
2934   #if !defined(__arm__) && !defined(__arm64__)
2935   if ((f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) &&
2936       (f_data[0] != 0xCA || f_data[1] != 0xFE || f_data[2] != 0xBA))
2937     FATAL("Program '%s' is not a 64-bit or universal Mach-O binary",
2938           afl->fsrv.target_path);
2939   #endif
2940 
2941 #endif                                                       /* ^!__APPLE__ */
2942 
2943   if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode &&
2944 #ifdef __linux__
2945       !afl->fsrv.nyx_mode &&
2946 #endif
2947       !afl->fsrv.cs_mode && !afl->non_instrumented_mode &&
2948       !afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
2949 
2950     SAYF("\n" cLRD "[-] " cRST
2951          "Looks like the target binary is not instrumented! The fuzzer depends "
2952          "on\n"
2953          "    compile-time instrumentation to isolate interesting test cases "
2954          "while\n"
2955          "    mutating the input data. For more information, and for tips on "
2956          "how to\n"
2957          "    instrument binaries, please see %s/README.md.\n\n"
2958 
2959          "    When source code is not available, you may be able to leverage "
2960          "QEMU\n"
2961          "    mode support. Consult the README.md for tips on how to enable "
2962          "this.\n\n"
2963 
2964          "    If your target is an instrumented binary (e.g. with zafl, "
2965          "retrowrite,\n"
2966          "    etc.) then set 'AFL_SKIP_BIN_CHECK=1'\n\n"
2967 
2968          "    (It is also possible to use afl-fuzz as a traditional, "
2969          "non-instrumented\n"
2970          "    fuzzer. For that use the -n option - but expect much worse "
2971          "results.)\n",
2972          doc_path);
2973 
2974     FATAL("No instrumentation detected");
2975 
2976   }
2977 
2978   if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
2979       afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
2980 
2981     SAYF("\n" cLRD "[-] " cRST
2982          "This program appears to be instrumented with afl-gcc, but is being "
2983          "run in\n"
2984          "    QEMU mode (-Q). This is probably not what you "
2985          "want -\n"
2986          "    this setup will be slow and offer no practical benefits.\n");
2987 
2988     FATAL("Instrumentation found in -Q mode");
2989 
2990   }
2991 
2992   if (afl_memmem(f_data, f_len, "__asan_init", 11) ||
2993       afl_memmem(f_data, f_len, "__msan_init", 11) ||
2994       afl_memmem(f_data, f_len, "__lsan_init", 11)) {
2995 
2996     afl->fsrv.uses_asan = 1;
2997 
2998   }
2999 
3000   /* Detect persistent & deferred init signatures in the binary. */
3001 
3002   if (afl_memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
3003 
3004     OKF(cPIN "Persistent mode binary detected.");
3005     setenv(PERSIST_ENV_VAR, "1", 1);
3006     afl->persistent_mode = 1;
3007     afl->fsrv.persistent_mode = 1;
3008     afl->shmem_testcase_mode = 1;
3009 
3010   } else if (getenv("AFL_PERSISTENT")) {
3011 
3012     OKF(cPIN "Persistent mode enforced.");
3013     setenv(PERSIST_ENV_VAR, "1", 1);
3014     afl->persistent_mode = 1;
3015     afl->fsrv.persistent_mode = 1;
3016     afl->shmem_testcase_mode = 1;
3017 
3018   } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
3019 
3020     OKF("FRIDA Persistent mode configuration options detected.");
3021     setenv(PERSIST_ENV_VAR, "1", 1);
3022     afl->persistent_mode = 1;
3023     afl->fsrv.persistent_mode = 1;
3024     afl->shmem_testcase_mode = 1;
3025 
3026   }
3027 
3028   if (afl->fsrv.frida_mode ||
3029       afl_memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
3030 
3031     OKF(cPIN "Deferred forkserver binary detected.");
3032     setenv(DEFER_ENV_VAR, "1", 1);
3033     afl->deferred_mode = 1;
3034 
3035   } else if (getenv("AFL_DEFER_FORKSRV")) {
3036 
3037     OKF(cPIN "Deferred forkserver enforced.");
3038     setenv(DEFER_ENV_VAR, "1", 1);
3039     afl->deferred_mode = 1;
3040 
3041   }
3042 
3043   if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
3044 
3045 }
3046 
3047 /* Check if we're on TTY. */
3048 
3049 void check_if_tty(afl_state_t *afl) {
3050 
3051   struct winsize ws;
3052 
3053   if (afl->afl_env.afl_no_ui) {
3054 
3055     OKF("Disabling the UI because AFL_NO_UI is set.");
3056     afl->not_on_tty = 1;
3057     return;
3058 
3059   }
3060 
3061   if (ioctl(1, TIOCGWINSZ, &ws)) {
3062 
3063     if (errno == ENOTTY) {
3064 
3065       OKF("Looks like we're not running on a tty, so I'll be a bit less "
3066           "verbose.");
3067       afl->not_on_tty = 1;
3068 
3069     }
3070 
3071     return;
3072 
3073   }
3074 
3075 }
3076 
3077 /* Set up signal handlers. More complicated that needs to be, because libc on
3078    Solaris doesn't resume interrupted reads(), sets SA_RESETHAND when you call
3079    siginterrupt(), and does other stupid things. */
3080 
3081 void setup_signal_handlers(void) {
3082 
3083   struct sigaction sa;
3084 
3085   memset((void *)&sa, 0, sizeof(sa));
3086   sa.sa_handler = NULL;
3087 #ifdef SA_RESTART
3088   sa.sa_flags = SA_RESTART;
3089 #endif
3090   sa.sa_sigaction = NULL;
3091 
3092   sigemptyset(&sa.sa_mask);
3093 
3094   /* Various ways of saying "stop". */
3095 
3096   sa.sa_handler = handle_stop_sig;
3097   sigaction(SIGHUP, &sa, NULL);
3098   sigaction(SIGINT, &sa, NULL);
3099   sigaction(SIGTERM, &sa, NULL);
3100 
3101   /* Window resize */
3102 
3103   sa.sa_handler = handle_resize;
3104   sigaction(SIGWINCH, &sa, NULL);
3105 
3106   /* SIGUSR1: skip entry */
3107 
3108   sa.sa_handler = handle_skipreq;
3109   sigaction(SIGUSR1, &sa, NULL);
3110 
3111   /* Things we don't care about. */
3112 
3113   sa.sa_handler = SIG_IGN;
3114   sigaction(SIGTSTP, &sa, NULL);
3115   sigaction(SIGPIPE, &sa, NULL);
3116 
3117 }
3118 
3119 /* Make a copy of the current command line. */
3120 
3121 void save_cmdline(afl_state_t *afl, u32 argc, char **argv) {
3122 
3123   u32 len = 1, i;
3124   u8 *buf;
3125 
3126   for (i = 0; i < argc; ++i) {
3127 
3128     len += strlen(argv[i]) + 1;
3129 
3130   }
3131 
3132   buf = afl->orig_cmdline = ck_alloc(len);
3133 
3134   for (i = 0; i < argc; ++i) {
3135 
3136     u32 l = strlen(argv[i]);
3137 
3138     if (!argv[i] || !buf) { FATAL("null deref detected"); }
3139 
3140     memcpy(buf, argv[i], l);
3141     buf += l;
3142 
3143     if (i != argc - 1) { *(buf++) = ' '; }
3144 
3145   }
3146 
3147   *buf = 0;
3148 
3149 }
3150 
3151