1 /*
2 american fuzzy lop++ - common 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 Gather some functions common to multiple executables
21
22 - detect_file_args
23
24 */
25
26 #include <stdlib.h>
27 #include <stdio.h>
28 #include "forkserver.h"
29 #ifndef _GNU_SOURCE
30 #define _GNU_SOURCE
31 #endif
32 #ifndef __USE_GNU
33 #define __USE_GNU
34 #endif
35 #include <string.h>
36 #include <strings.h>
37 #include <math.h>
38 #include <sys/mman.h>
39
40 #include "debug.h"
41 #include "alloc-inl.h"
42 #include "envs.h"
43 #include "common.h"
44
45 /* Detect @@ in args. */
46 #include <unistd.h>
47 #include <limits.h>
48 #include <sys/types.h>
49 #include <sys/stat.h>
50 #include <fcntl.h>
51 #include <signal.h>
52
53 u8 be_quiet = 0;
54 u8 *doc_path = "";
55 u8 last_intr = 0;
56
57 #ifndef AFL_PATH
58 #define AFL_PATH "/usr/local/lib/afl/"
59 #endif
60
afl_memmem(const void * haystack,size_t haystacklen,const void * needle,size_t needlelen)61 void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
62 size_t needlelen) {
63
64 if (unlikely(needlelen > haystacklen)) { return NULL; }
65
66 for (u32 i = 0; i <= haystacklen - needlelen; ++i) {
67
68 if (unlikely(memcmp(haystack + i, needle, needlelen) == 0)) {
69
70 return (void *)(haystack + i);
71
72 }
73
74 }
75
76 return (void *)NULL;
77
78 }
79
set_sanitizer_defaults()80 void set_sanitizer_defaults() {
81
82 /* Set sane defaults for ASAN if nothing else is specified. */
83 u8 *have_asan_options = getenv("ASAN_OPTIONS");
84 u8 *have_ubsan_options = getenv("UBSAN_OPTIONS");
85 u8 *have_msan_options = getenv("MSAN_OPTIONS");
86 u8 *have_lsan_options = getenv("LSAN_OPTIONS");
87 u8 have_san_options = 0;
88 u8 default_options[1024] =
89 "detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
90 "return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
91 "sigfpe=0:handle_sigill=0:";
92
93 if (have_asan_options || have_ubsan_options || have_msan_options ||
94 have_lsan_options) {
95
96 have_san_options = 1;
97
98 }
99
100 /* LSAN does not support abort_on_error=1. (is this still true??) */
101 u8 should_detect_leaks = 0;
102
103 if (!have_lsan_options) {
104
105 u8 buf[2048] = "";
106 if (!have_san_options) { strcpy(buf, default_options); }
107 if (have_asan_options) {
108
109 if (NULL != strstr(have_asan_options, "detect_leaks=0")) {
110
111 strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=0:malloc_context_size=0:");
112
113 } else {
114
115 should_detect_leaks = 1;
116 strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:");
117
118 }
119
120 }
121
122 setenv("LSAN_OPTIONS", buf, 1);
123
124 }
125
126 /* for everything not LSAN we disable detect_leaks */
127
128 if (!have_lsan_options) {
129
130 if (should_detect_leaks) {
131
132 strcat(default_options, "detect_leaks=1:malloc_context_size=30:");
133
134 } else {
135
136 strcat(default_options, "detect_leaks=0:malloc_context_size=0:");
137
138 }
139
140 }
141
142 /* Set sane defaults for ASAN if nothing else is specified. */
143
144 if (!have_san_options) { setenv("ASAN_OPTIONS", default_options, 1); }
145
146 /* Set sane defaults for UBSAN if nothing else is specified. */
147
148 if (!have_san_options) { setenv("UBSAN_OPTIONS", default_options, 1); }
149
150 /* MSAN is tricky, because it doesn't support abort_on_error=1 at this
151 point. So, we do this in a very hacky way. */
152
153 if (!have_msan_options) {
154
155 u8 buf[2048] = "";
156 if (!have_san_options) { strcpy(buf, default_options); }
157 strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:");
158 setenv("MSAN_OPTIONS", buf, 1);
159
160 }
161
162 /* Envs for QASan */
163 setenv("QASAN_MAX_CALL_STACK", "0", 0);
164 setenv("QASAN_SYMBOLIZE", "0", 0);
165
166 }
167
check_binary_signatures(u8 * fn)168 u32 check_binary_signatures(u8 *fn) {
169
170 int ret = 0, fd = open(fn, O_RDONLY);
171 if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
172 struct stat st;
173 if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
174 u32 f_len = st.st_size;
175 u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
176 if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
177 close(fd);
178
179 if (afl_memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
180
181 if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); }
182 setenv(PERSIST_ENV_VAR, "1", 1);
183 ret = 1;
184
185 } else if (getenv("AFL_PERSISTENT")) {
186
187 if (!be_quiet) { OKF(cPIN "Persistent mode enforced."); }
188 setenv(PERSIST_ENV_VAR, "1", 1);
189 ret = 1;
190
191 } else if (getenv("AFL_FRIDA_PERSISTENT_ADDR")) {
192
193 if (!be_quiet) {
194
195 OKF("FRIDA Persistent mode configuration options detected.");
196
197 }
198
199 setenv(PERSIST_ENV_VAR, "1", 1);
200 ret = 1;
201
202 }
203
204 if (afl_memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
205
206 if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); }
207 setenv(DEFER_ENV_VAR, "1", 1);
208 ret += 2;
209
210 } else if (getenv("AFL_DEFER_FORKSRV")) {
211
212 if (!be_quiet) { OKF(cPIN "Deferred forkserver enforced."); }
213 setenv(DEFER_ENV_VAR, "1", 1);
214 ret += 2;
215
216 }
217
218 if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
219
220 return ret;
221
222 }
223
detect_file_args(char ** argv,u8 * prog_in,bool * use_stdin)224 void detect_file_args(char **argv, u8 *prog_in, bool *use_stdin) {
225
226 u32 i = 0;
227 u8 cwd[PATH_MAX];
228 if (getcwd(cwd, (size_t)sizeof(cwd)) == NULL) { PFATAL("getcwd() failed"); }
229
230 /* we are working with libc-heap-allocated argvs. So do not mix them with
231 * other allocation APIs like ck_alloc. That would disturb the free() calls.
232 */
233 while (argv[i]) {
234
235 u8 *aa_loc = strstr(argv[i], "@@");
236
237 if (aa_loc) {
238
239 if (!prog_in) { FATAL("@@ syntax is not supported by this tool."); }
240
241 *use_stdin = false;
242
243 /* Be sure that we're always using fully-qualified paths. */
244
245 *aa_loc = 0;
246
247 /* Construct a replacement argv value. */
248 u8 *n_arg;
249
250 if (prog_in[0] == '/') {
251
252 n_arg = alloc_printf("%s%s%s", argv[i], prog_in, aa_loc + 2);
253
254 } else {
255
256 n_arg = alloc_printf("%s%s/%s%s", argv[i], cwd, prog_in, aa_loc + 2);
257
258 }
259
260 ck_free(argv[i]);
261 argv[i] = n_arg;
262
263 }
264
265 i++;
266
267 }
268
269 /* argvs are automatically freed at exit. */
270
271 }
272
273 /* duplicate the system argv so that
274 we can edit (and free!) it later */
275
argv_cpy_dup(int argc,char ** argv)276 char **argv_cpy_dup(int argc, char **argv) {
277
278 int i = 0;
279
280 char **ret = ck_alloc((argc + 1) * sizeof(char *));
281 if (unlikely(!ret)) { FATAL("Amount of arguments specified is too high"); }
282
283 for (i = 0; i < argc; i++) {
284
285 ret[i] = ck_strdup(argv[i]);
286
287 }
288
289 ret[i] = NULL;
290
291 return ret;
292
293 }
294
295 /* frees all args in the given argv,
296 previously created by argv_cpy_dup */
297
argv_cpy_free(char ** argv)298 void argv_cpy_free(char **argv) {
299
300 u32 i = 0;
301 while (argv[i]) {
302
303 ck_free(argv[i]);
304 argv[i] = NULL;
305 i++;
306
307 }
308
309 ck_free(argv);
310
311 }
312
313 /* Rewrite argv for CoreSight process tracer. */
314
get_cs_argv(u8 * own_loc,u8 ** target_path_p,int argc,char ** argv)315 char **get_cs_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
316
317 if (unlikely(getenv("AFL_CS_CUSTOM_BIN"))) {
318
319 WARNF(
320 "AFL_CS_CUSTOM_BIN is enabled. "
321 "You must run your target under afl-cs-proxy on your own!");
322 return argv;
323
324 }
325
326 char **new_argv = ck_alloc(sizeof(char *) * (argc + 4));
327 if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
328
329 memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
330 new_argv[argc + 3] = NULL;
331
332 new_argv[2] = *target_path_p;
333 new_argv[1] = "--";
334
335 /* Now we need to actually find the cs-proxy binary to put in argv[0]. */
336
337 *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-cs-proxy");
338 return new_argv;
339
340 }
341
342 /* Rewrite argv for QEMU. */
343
get_qemu_argv(u8 * own_loc,u8 ** target_path_p,int argc,char ** argv)344 char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
345
346 if (unlikely(getenv("AFL_QEMU_CUSTOM_BIN"))) {
347
348 WARNF(
349 "AFL_QEMU_CUSTOM_BIN is enabled. "
350 "You must run your target under afl-qemu-trace on your own!");
351 return argv;
352
353 }
354
355 char **new_argv = ck_alloc(sizeof(char *) * (argc + 3));
356 if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
357
358 memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1));
359
360 new_argv[2] = *target_path_p;
361 new_argv[1] = "--";
362
363 /* Now we need to actually find the QEMU binary to put in argv[0]. */
364
365 *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-qemu-trace");
366 return new_argv;
367
368 }
369
370 /* Rewrite argv for Wine+QEMU. */
371
get_wine_argv(u8 * own_loc,u8 ** target_path_p,int argc,char ** argv)372 char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) {
373
374 char **new_argv = ck_alloc(sizeof(char *) * (argc + 2));
375 if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); }
376
377 memcpy(&new_argv[2], &argv[1], (int)(sizeof(char *)) * (argc - 1));
378
379 new_argv[1] = *target_path_p;
380
381 /* Now we need to actually find the QEMU binary to put in argv[0]. */
382
383 u8 *tmp = find_afl_binary(own_loc, "afl-qemu-trace");
384 ck_free(tmp);
385 *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-wine-trace");
386 return new_argv;
387
388 }
389
390 /* Find binary, used by analyze, showmap, tmin
391 @returns the path, allocating the string */
392
find_binary(u8 * fname)393 u8 *find_binary(u8 *fname) {
394
395 // TODO: Merge this function with check_binary of afl-fuzz-init.c
396
397 u8 *env_path = NULL;
398 u8 *target_path = NULL;
399
400 struct stat st;
401
402 if (unlikely(!fname)) { FATAL("No binary supplied"); }
403
404 if (strchr(fname, '/') || !(env_path = getenv("PATH"))) {
405
406 target_path = ck_strdup(fname);
407
408 if (stat(target_path, &st) || !S_ISREG(st.st_mode) ||
409 !(st.st_mode & 0111) || st.st_size < 4) {
410
411 ck_free(target_path);
412 FATAL("Program '%s' not found or not executable", fname);
413
414 }
415
416 } else {
417
418 while (env_path) {
419
420 u8 *cur_elem, *delim = strchr(env_path, ':');
421
422 if (delim) {
423
424 cur_elem = ck_alloc(delim - env_path + 1);
425 if (unlikely(!cur_elem)) {
426
427 FATAL(
428 "Unexpected overflow when processing ENV. This should never "
429 "had happened.");
430
431 }
432
433 memcpy(cur_elem, env_path, delim - env_path);
434 delim++;
435
436 } else {
437
438 cur_elem = ck_strdup(env_path);
439
440 }
441
442 env_path = delim;
443
444 if (cur_elem[0]) {
445
446 target_path = alloc_printf("%s/%s", cur_elem, fname);
447
448 } else {
449
450 target_path = ck_strdup(fname);
451
452 }
453
454 ck_free(cur_elem);
455
456 if (!stat(target_path, &st) && S_ISREG(st.st_mode) &&
457 (st.st_mode & 0111) && st.st_size >= 4) {
458
459 break;
460
461 }
462
463 ck_free(target_path);
464 target_path = NULL;
465
466 }
467
468 if (!target_path) {
469
470 FATAL("Program '%s' not found or not executable", fname);
471
472 }
473
474 }
475
476 return target_path;
477
478 }
479
find_afl_binary(u8 * own_loc,u8 * fname)480 u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
481
482 u8 *afl_path = NULL, *target_path, *own_copy, *tmp;
483 int perm = X_OK;
484
485 if ((tmp = strrchr(fname, '.'))) {
486
487 if (!strcasecmp(tmp, ".so") || !strcasecmp(tmp, ".dylib")) { perm = R_OK; }
488
489 }
490
491 if ((afl_path = getenv("AFL_PATH"))) {
492
493 target_path = alloc_printf("%s/%s", afl_path, fname);
494 if (!access(target_path, perm)) {
495
496 return target_path;
497
498 } else {
499
500 ck_free(target_path);
501
502 }
503
504 }
505
506 if (own_loc) {
507
508 own_copy = ck_strdup(own_loc);
509 u8 *rsl = strrchr(own_copy, '/');
510
511 if (rsl) {
512
513 *rsl = 0;
514
515 target_path = alloc_printf("%s/%s", own_copy, fname);
516 ck_free(own_copy);
517
518 if (!access(target_path, perm)) {
519
520 return target_path;
521
522 } else {
523
524 ck_free(target_path);
525
526 }
527
528 } else {
529
530 ck_free(own_copy);
531
532 }
533
534 }
535
536 if (perm == X_OK) {
537
538 target_path = alloc_printf("%s/%s", BIN_PATH, fname);
539
540 } else {
541
542 target_path = alloc_printf("%s/%s", AFL_PATH, fname);
543
544 }
545
546 if (!access(target_path, perm)) {
547
548 return target_path;
549
550 } else {
551
552 ck_free(target_path);
553
554 }
555
556 if (perm == X_OK) {
557
558 return find_binary(fname);
559
560 } else {
561
562 FATAL("Library '%s' not found", fname);
563
564 }
565
566 }
567
parse_afl_kill_signal(u8 * numeric_signal_as_str,int default_signal)568 int parse_afl_kill_signal(u8 *numeric_signal_as_str, int default_signal) {
569
570 if (numeric_signal_as_str && numeric_signal_as_str[0]) {
571
572 char *endptr;
573 u8 signal_code;
574 signal_code = (u8)strtoul(numeric_signal_as_str, &endptr, 10);
575 /* Did we manage to parse the full string? */
576 if (*endptr != '\0' || endptr == (char *)numeric_signal_as_str) {
577
578 FATAL("Invalid signal name: %s", numeric_signal_as_str);
579
580 } else {
581
582 return signal_code;
583
584 }
585
586 }
587
588 return default_signal;
589
590 }
591
configure_afl_kill_signals(afl_forkserver_t * fsrv,char * afl_kill_signal_env,char * afl_fsrv_kill_signal_env,int default_server_kill_signal)592 void configure_afl_kill_signals(afl_forkserver_t *fsrv,
593 char *afl_kill_signal_env,
594 char *afl_fsrv_kill_signal_env,
595 int default_server_kill_signal) {
596
597 afl_kill_signal_env =
598 afl_kill_signal_env ? afl_kill_signal_env : getenv("AFL_KILL_SIGNAL");
599 afl_fsrv_kill_signal_env = afl_fsrv_kill_signal_env
600 ? afl_fsrv_kill_signal_env
601 : getenv("AFL_FORK_SERVER_KILL_SIGNAL");
602
603 fsrv->child_kill_signal = parse_afl_kill_signal(afl_kill_signal_env, SIGKILL);
604
605 if (afl_kill_signal_env && !afl_fsrv_kill_signal_env) {
606
607 /*
608 Set AFL_FORK_SERVER_KILL_SIGNAL to the value of AFL_KILL_SIGNAL for
609 backwards compatibility. However, if AFL_FORK_SERVER_KILL_SIGNAL is set, is
610 takes precedence.
611 */
612 afl_fsrv_kill_signal_env = afl_kill_signal_env;
613
614 }
615
616 fsrv->fsrv_kill_signal = parse_afl_kill_signal(afl_fsrv_kill_signal_env,
617 default_server_kill_signal);
618
619 }
620
helper_min3(unsigned int a,unsigned int b,unsigned int c)621 static inline unsigned int helper_min3(unsigned int a, unsigned int b,
622 unsigned int c) {
623
624 return a < b ? (a < c ? a : c) : (b < c ? b : c);
625
626 }
627
628 // from
629 // https://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#C
string_distance_levenshtein(char * s1,char * s2)630 static int string_distance_levenshtein(char *s1, char *s2) {
631
632 unsigned int s1len, s2len, x, y, lastdiag, olddiag;
633 s1len = strlen(s1);
634 s2len = strlen(s2);
635 unsigned int column[s1len + 1];
636 column[s1len] = 1;
637
638 for (y = 1; y <= s1len; y++)
639 column[y] = y;
640 for (x = 1; x <= s2len; x++) {
641
642 column[0] = x;
643 for (y = 1, lastdiag = x - 1; y <= s1len; y++) {
644
645 olddiag = column[y];
646 column[y] = helper_min3(column[y] + 1, column[y - 1] + 1,
647 lastdiag + (s1[y - 1] == s2[x - 1] ? 0 : 1));
648 lastdiag = olddiag;
649
650 }
651
652 }
653
654 return column[s1len];
655
656 }
657
658 #define ENV_SIMILARITY_TRESHOLD 3
659
print_suggested_envs(char * mispelled_env)660 void print_suggested_envs(char *mispelled_env) {
661
662 size_t env_name_len =
663 strcspn(mispelled_env, "=") - 4; // remove the AFL_prefix
664 char *env_name = ck_alloc(env_name_len + 1);
665 memcpy(env_name, mispelled_env + 4, env_name_len);
666
667 char *seen = ck_alloc(sizeof(afl_environment_variables) / sizeof(char *));
668 int found = 0;
669
670 int j;
671 for (j = 0; afl_environment_variables[j] != NULL; ++j) {
672
673 char *afl_env = afl_environment_variables[j] + 4;
674 int distance = string_distance_levenshtein(afl_env, env_name);
675 if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
676
677 SAYF("Did you mean %s?\n", afl_environment_variables[j]);
678 seen[j] = 1;
679 found = 1;
680
681 }
682
683 }
684
685 if (found) goto cleanup;
686
687 for (j = 0; afl_environment_variables[j] != NULL; ++j) {
688
689 char *afl_env = afl_environment_variables[j] + 4;
690 size_t afl_env_len = strlen(afl_env);
691 char *reduced = ck_alloc(afl_env_len + 1);
692
693 size_t start = 0;
694 while (start < afl_env_len) {
695
696 size_t end = start + strcspn(afl_env + start, "_") + 1;
697 memcpy(reduced, afl_env, start);
698 if (end < afl_env_len) {
699
700 memcpy(reduced + start, afl_env + end, afl_env_len - end);
701
702 }
703
704 if (afl_env_len + start >= end) {
705
706 reduced[afl_env_len - end + start] = 0;
707
708 }
709
710 int distance = string_distance_levenshtein(reduced, env_name);
711 if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
712
713 SAYF("Did you mean %s?\n", afl_environment_variables[j]);
714 seen[j] = 1;
715 found = 1;
716
717 }
718
719 start = end;
720
721 };
722
723 ck_free(reduced);
724
725 }
726
727 if (found) goto cleanup;
728
729 char *reduced = ck_alloc(env_name_len + 1);
730 size_t start = 0;
731 while (start < env_name_len) {
732
733 size_t end = start + strcspn(env_name + start, "_") + 1;
734 memcpy(reduced, env_name, start);
735 if (end < env_name_len)
736 memcpy(reduced + start, env_name + end, env_name_len - end);
737 reduced[env_name_len - end + start] = 0;
738
739 for (j = 0; afl_environment_variables[j] != NULL; ++j) {
740
741 int distance = string_distance_levenshtein(
742 afl_environment_variables[j] + 4, reduced);
743 if (distance < ENV_SIMILARITY_TRESHOLD && seen[j] == 0) {
744
745 SAYF("Did you mean %s?\n", afl_environment_variables[j]);
746 seen[j] = 1;
747
748 }
749
750 }
751
752 start = end;
753
754 };
755
756 ck_free(reduced);
757
758 cleanup:
759 ck_free(env_name);
760 ck_free(seen);
761
762 }
763
check_environment_vars(char ** envp)764 void check_environment_vars(char **envp) {
765
766 if (be_quiet) { return; }
767
768 int index = 0, issue_detected = 0;
769 char *env, *val, *ignore = getenv("AFL_IGNORE_UNKNOWN_ENVS");
770 while ((env = envp[index++]) != NULL) {
771
772 if (strncmp(env, "ALF_", 4) == 0 || strncmp(env, "_ALF", 4) == 0 ||
773 strncmp(env, "__ALF", 5) == 0 || strncmp(env, "_AFL", 4) == 0 ||
774 strncmp(env, "__AFL", 5) == 0) {
775
776 WARNF("Potentially mistyped AFL environment variable: %s", env);
777 issue_detected = 1;
778
779 } else if (strncmp(env, "AFL_", 4) == 0) {
780
781 int i = 0, match = 0;
782 while (match == 0 && afl_environment_variables[i] != NULL) {
783
784 if (strncmp(env, afl_environment_variables[i],
785 strlen(afl_environment_variables[i])) == 0 &&
786 env[strlen(afl_environment_variables[i])] == '=') {
787
788 match = 1;
789
790 if ((val = getenv(afl_environment_variables[i])) && !*val) {
791
792 WARNF(
793 "AFL environment variable %s defined but is empty, this can "
794 "lead to unexpected consequences",
795 afl_environment_variables[i]);
796 issue_detected = 1;
797
798 }
799
800 } else {
801
802 i++;
803
804 }
805
806 }
807
808 i = 0;
809 while (match == 0 && afl_environment_deprecated[i] != NULL) {
810
811 if (strncmp(env, afl_environment_deprecated[i],
812 strlen(afl_environment_deprecated[i])) == 0 &&
813 env[strlen(afl_environment_deprecated[i])] == '=') {
814
815 match = 1;
816
817 WARNF("AFL environment variable %s is deprecated!",
818 afl_environment_deprecated[i]);
819 issue_detected = 1;
820
821 } else {
822
823 i++;
824
825 }
826
827 }
828
829 if (match == 0 && !ignore) {
830
831 WARNF("Mistyped AFL environment variable: %s", env);
832 issue_detected = 1;
833
834 print_suggested_envs(env);
835
836 }
837
838 }
839
840 }
841
842 if (issue_detected) { sleep(2); }
843
844 }
845
get_afl_env(char * env)846 char *get_afl_env(char *env) {
847
848 char *val;
849
850 if ((val = getenv(env))) {
851
852 if (*val) {
853
854 if (!be_quiet) {
855
856 OKF("Enabled environment variable %s with value %s", env, val);
857
858 }
859
860 return val;
861
862 }
863
864 }
865
866 return NULL;
867
868 }
869
extract_and_set_env(u8 * env_str)870 bool extract_and_set_env(u8 *env_str) {
871
872 if (!env_str) { return false; }
873
874 bool ret = false; // return false by default
875
876 u8 *p = ck_strdup(env_str);
877 u8 *end = p + strlen((char *)p);
878 u8 *rest = p;
879
880 u8 closing_sym = ' ';
881 u8 c;
882
883 size_t num_pairs = 0;
884
885 while (rest < end) {
886
887 while (*rest == ' ') {
888
889 rest++;
890
891 }
892
893 if (rest + 1 >= end) break;
894
895 u8 *key = rest;
896 // env variable names may not start with numbers or '='
897 if (*key == '=' || (*key >= '0' && *key <= '9')) { goto free_and_return; }
898
899 while (rest < end && *rest != '=' && *rest != ' ') {
900
901 c = *rest;
902 // lowercase is bad but we may still allow it
903 if ((c < 'A' || c > 'Z') && (c < 'a' || c > 'z') &&
904 (c < '0' || c > '9') && c != '_') {
905
906 goto free_and_return;
907
908 }
909
910 rest++;
911
912 }
913
914 if (*rest != '=') { goto free_and_return; }
915
916 *rest = '\0'; // done with variable name
917
918 rest += 1;
919 if (rest >= end || *rest == ' ') { goto free_and_return; }
920
921 u8 *val = rest;
922 if (*val == '\'' || *val == '"') {
923
924 closing_sym = *val;
925 val += 1;
926 rest += 1;
927 if (rest >= end) { goto free_and_return; }
928
929 } else {
930
931 closing_sym = ' ';
932
933 }
934
935 while (rest < end && *rest != closing_sym) {
936
937 rest++;
938
939 }
940
941 if (closing_sym != ' ' && *rest != closing_sym) { goto free_and_return; }
942
943 *rest = '\0'; // done with variable value
944
945 rest += 1;
946 num_pairs++;
947 setenv(key, val, 1);
948
949 }
950
951 if (num_pairs) { ret = true; }
952
953 free_and_return:
954 ck_free(p);
955 return ret;
956
957 }
958
959 /* Read mask bitmap from file. This is for the -B option. */
960
read_bitmap(u8 * fname,u8 * map,size_t len)961 void read_bitmap(u8 *fname, u8 *map, size_t len) {
962
963 s32 fd = open(fname, O_RDONLY);
964
965 if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
966
967 ck_read(fd, map, len, fname);
968
969 close(fd);
970
971 }
972
973 /* Get unix time in milliseconds */
974
get_cur_time(void)975 inline u64 get_cur_time(void) {
976
977 struct timeval tv;
978 struct timezone tz;
979
980 gettimeofday(&tv, &tz);
981
982 return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
983
984 }
985
986 /* Get unix time in microseconds */
987
get_cur_time_us(void)988 u64 get_cur_time_us(void) {
989
990 struct timeval tv;
991 struct timezone tz;
992
993 gettimeofday(&tv, &tz);
994
995 return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
996
997 }
998
999 /* Describe integer. The buf should be
1000 at least 6 bytes to fit all ints we randomly see.
1001 Will return buf for convenience. */
1002
stringify_int(u8 * buf,size_t len,u64 val)1003 u8 *stringify_int(u8 *buf, size_t len, u64 val) {
1004 \
1005 #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
1006 do { \
1007 \
1008 if (val < (_divisor) * (_limit_mult)) { \
1009 \
1010 snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
1011 return buf; \
1012 \
1013 } \
1014 \
1015 } while (0)
1016
1017 /* 0-9999 */
1018 CHK_FORMAT(1, 10000, "%llu", u64);
1019
1020 /* 10.0k - 99.9k */
1021 CHK_FORMAT(1000, 99.95, "%0.01fk", double);
1022
1023 /* 100k - 999k */
1024 CHK_FORMAT(1000, 1000, "%lluk", u64);
1025
1026 /* 1.00M - 9.99M */
1027 CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
1028
1029 /* 10.0M - 99.9M */
1030 CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
1031
1032 /* 100M - 999M */
1033 CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
1034
1035 /* 1.00G - 9.99G */
1036 CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
1037
1038 /* 10.0G - 99.9G */
1039 CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
1040
1041 /* 100G - 999G */
1042 CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
1043
1044 /* 1.00T - 9.99G */
1045 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
1046
1047 /* 10.0T - 99.9T */
1048 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
1049
1050 /* 100T+ */
1051 strncpy(buf, "infty", len);
1052 buf[len - 1] = '\0';
1053
1054 return buf;
1055
1056 }
1057
1058 /* Describe float. Similar as int. */
1059
stringify_float(u8 * buf,size_t len,double val)1060 u8 *stringify_float(u8 *buf, size_t len, double val) {
1061
1062 if (val < 99.995) {
1063
1064 snprintf(buf, len, "%0.02f", val);
1065
1066 } else if (val < 999.95) {
1067
1068 snprintf(buf, len, "%0.01f", val);
1069
1070 } else if (unlikely(isnan(val) || isinf(val))) {
1071
1072 strcpy(buf, "inf");
1073
1074 } else {
1075
1076 stringify_int(buf, len, (u64)val);
1077
1078 }
1079
1080 return buf;
1081
1082 }
1083
1084 /* Describe integer as memory size. */
1085
stringify_mem_size(u8 * buf,size_t len,u64 val)1086 u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
1087
1088 /* 0-9999 */
1089 CHK_FORMAT(1, 10000, "%llu B", u64);
1090
1091 /* 10.0k - 99.9k */
1092 CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
1093
1094 /* 100k - 999k */
1095 CHK_FORMAT(1024, 1000, "%llu kB", u64);
1096
1097 /* 1.00M - 9.99M */
1098 CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
1099
1100 /* 10.0M - 99.9M */
1101 CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
1102
1103 /* 100M - 999M */
1104 CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
1105
1106 /* 1.00G - 9.99G */
1107 CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
1108
1109 /* 10.0G - 99.9G */
1110 CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
1111
1112 /* 100G - 999G */
1113 CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
1114
1115 /* 1.00T - 9.99G */
1116 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
1117
1118 /* 10.0T - 99.9T */
1119 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
1120
1121 #undef CHK_FORMAT
1122
1123 /* 100T+ */
1124 strncpy(buf, "infty", len - 1);
1125 buf[len - 1] = '\0';
1126
1127 return buf;
1128
1129 }
1130
1131 /* Describe time delta as string.
1132 Returns a pointer to buf for convenience. */
1133
stringify_time_diff(u8 * buf,size_t len,u64 cur_ms,u64 event_ms)1134 u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
1135
1136 if (!event_ms) {
1137
1138 snprintf(buf, len, "none seen yet");
1139
1140 } else {
1141
1142 u64 delta;
1143 s32 t_d, t_h, t_m, t_s;
1144 u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
1145
1146 delta = cur_ms - event_ms;
1147
1148 t_d = delta / 1000 / 60 / 60 / 24;
1149 t_h = (delta / 1000 / 60 / 60) % 24;
1150 t_m = (delta / 1000 / 60) % 60;
1151 t_s = (delta / 1000) % 60;
1152
1153 stringify_int(val_buf, sizeof(val_buf), t_d);
1154 snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
1155 t_s);
1156
1157 }
1158
1159 return buf;
1160
1161 }
1162
1163 /* Unsafe Describe integer. The buf sizes are not checked.
1164 This is unsafe but fast.
1165 Will return buf for convenience. */
1166
u_stringify_int(u8 * buf,u64 val)1167 u8 *u_stringify_int(u8 *buf, u64 val) {
1168 \
1169 #define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
1170 do { \
1171 \
1172 if (val < (_divisor) * (_limit_mult)) { \
1173 \
1174 sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \
1175 return buf; \
1176 \
1177 } \
1178 \
1179 } while (0)
1180
1181 /* 0-9999 */
1182 CHK_FORMAT(1, 10000, "%llu", u64);
1183
1184 /* 10.0k - 99.9k */
1185 CHK_FORMAT(1000, 99.95, "%0.01fk", double);
1186
1187 /* 100k - 999k */
1188 CHK_FORMAT(1000, 1000, "%lluk", u64);
1189
1190 /* 1.00M - 9.99M */
1191 CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
1192
1193 /* 10.0M - 99.9M */
1194 CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
1195
1196 /* 100M - 999M */
1197 CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
1198
1199 /* 1.00G - 9.99G */
1200 CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
1201
1202 /* 10.0G - 99.9G */
1203 CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
1204
1205 /* 100G - 999G */
1206 CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
1207
1208 /* 1.00T - 9.99G */
1209 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
1210
1211 /* 10.0T - 99.9T */
1212 CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
1213
1214 /* 100T+ */
1215 strcpy(buf, "infty");
1216
1217 return buf;
1218
1219 }
1220
1221 /* Unsafe describe float. Similar as unsafe int. */
1222
u_stringify_float(u8 * buf,double val)1223 u8 *u_stringify_float(u8 *buf, double val) {
1224
1225 if (val < 99.995) {
1226
1227 sprintf(buf, "%0.02f", val);
1228
1229 } else if (val < 999.95) {
1230
1231 sprintf(buf, "%0.01f", val);
1232
1233 } else if (unlikely(isnan(val) || isinf(val))) {
1234
1235 strcpy(buf, "infinite");
1236
1237 } else {
1238
1239 return u_stringify_int(buf, (u64)val);
1240
1241 }
1242
1243 return buf;
1244
1245 }
1246
1247 /* Unsafe describe integer as memory size. */
1248
u_stringify_mem_size(u8 * buf,u64 val)1249 u8 *u_stringify_mem_size(u8 *buf, u64 val) {
1250
1251 /* 0-9999 */
1252 CHK_FORMAT(1, 10000, "%llu B", u64);
1253
1254 /* 10.0k - 99.9k */
1255 CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
1256
1257 /* 100k - 999k */
1258 CHK_FORMAT(1024, 1000, "%llu kB", u64);
1259
1260 /* 1.00M - 9.99M */
1261 CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
1262
1263 /* 10.0M - 99.9M */
1264 CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
1265
1266 /* 100M - 999M */
1267 CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
1268
1269 /* 1.00G - 9.99G */
1270 CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
1271
1272 /* 10.0G - 99.9G */
1273 CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
1274
1275 /* 100G - 999G */
1276 CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
1277
1278 /* 1.00T - 9.99G */
1279 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
1280
1281 /* 10.0T - 99.9T */
1282 CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
1283
1284 #undef CHK_FORMAT
1285
1286 /* 100T+ */
1287 strcpy(buf, "infty");
1288
1289 return buf;
1290
1291 }
1292
1293 /* Unsafe describe time delta as string.
1294 Returns a pointer to buf for convenience. */
1295
u_stringify_time_diff(u8 * buf,u64 cur_ms,u64 event_ms)1296 u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
1297
1298 if (!event_ms) {
1299
1300 sprintf(buf, "none seen yet");
1301
1302 } else {
1303
1304 u64 delta;
1305 s32 t_d, t_h, t_m, t_s;
1306 u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
1307
1308 delta = cur_ms - event_ms;
1309
1310 t_d = delta / 1000 / 60 / 60 / 24;
1311 t_h = (delta / 1000 / 60 / 60) % 24;
1312 t_m = (delta / 1000 / 60) % 60;
1313 t_s = (delta / 1000) % 60;
1314
1315 u_stringify_int(val_buf, t_d);
1316 sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
1317
1318 }
1319
1320 return buf;
1321
1322 }
1323
1324 /* Unsafe describe time delta as simple string.
1325 Returns a pointer to buf for convenience. */
1326
u_simplestring_time_diff(u8 * buf,u64 cur_ms,u64 event_ms)1327 u8 *u_simplestring_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
1328
1329 if (!event_ms) {
1330
1331 sprintf(buf, "00:00:00");
1332
1333 } else {
1334
1335 u64 delta;
1336 s32 t_d, t_h, t_m, t_s;
1337
1338 delta = cur_ms - event_ms;
1339
1340 t_d = delta / 1000 / 60 / 60 / 24;
1341 t_h = (delta / 1000 / 60 / 60) % 24;
1342 t_m = (delta / 1000 / 60) % 60;
1343 t_s = (delta / 1000) % 60;
1344
1345 sprintf(buf, "%d:%02d:%02d:%02d", t_d, t_h, t_m, t_s);
1346
1347 }
1348
1349 return buf;
1350
1351 }
1352
1353 /* Reads the map size from ENV */
get_map_size(void)1354 u32 get_map_size(void) {
1355
1356 uint32_t map_size = DEFAULT_SHMEM_SIZE;
1357 char *ptr;
1358
1359 if ((ptr = getenv("AFL_MAP_SIZE")) || (ptr = getenv("AFL_MAPSIZE"))) {
1360
1361 map_size = atoi(ptr);
1362 if (!map_size || map_size > (1 << 29)) {
1363
1364 FATAL("illegal AFL_MAP_SIZE %u, must be between %u and %u", map_size, 64U,
1365 1U << 29);
1366
1367 }
1368
1369 if (map_size % 64) { map_size = (((map_size >> 6) + 1) << 6); }
1370
1371 } else if (getenv("AFL_SKIP_BIN_CHECK")) {
1372
1373 map_size = MAP_SIZE;
1374
1375 }
1376
1377 return map_size;
1378
1379 }
1380
1381 /* Create a stream file */
1382
create_ffile(u8 * fn)1383 FILE *create_ffile(u8 *fn) {
1384
1385 s32 fd;
1386 FILE *f;
1387
1388 fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
1389
1390 if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
1391
1392 f = fdopen(fd, "w");
1393
1394 if (!f) { PFATAL("fdopen() failed"); }
1395
1396 return f;
1397
1398 }
1399
1400 /* Create a file */
1401
create_file(u8 * fn)1402 s32 create_file(u8 *fn) {
1403
1404 s32 fd;
1405
1406 fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
1407
1408 if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
1409
1410 return fd;
1411
1412 }
1413
1414 #ifdef __linux__
1415
1416 /* Nyx requires a tmp workdir to access specific files (such as mmapped files,
1417 * etc.). This helper function basically creates both a path to a tmp workdir
1418 * and the workdir itself. If the environment variable TMPDIR is set, we use
1419 * that as the base directory, otherwise we use /tmp. */
create_nyx_tmp_workdir(void)1420 char *create_nyx_tmp_workdir(void) {
1421
1422 char *tmpdir = getenv("TMPDIR");
1423
1424 if (!tmpdir) { tmpdir = "/tmp"; }
1425
1426 char *nyx_out_dir_path =
1427 alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
1428
1429 if (mkdir(nyx_out_dir_path, 0700)) { PFATAL("Unable to create nyx workdir"); }
1430
1431 return nyx_out_dir_path;
1432
1433 }
1434
1435 /* Vice versa, we remove the tmp workdir for nyx with this helper function. */
remove_nyx_tmp_workdir(afl_forkserver_t * fsrv,char * nyx_out_dir_path)1436 void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path) {
1437
1438 char *workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
1439
1440 if (access(workdir_path, R_OK) == 0) {
1441
1442 if (fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
1443
1444 WARNF("Unable to remove nyx workdir (%s)", workdir_path);
1445
1446 }
1447
1448 }
1449
1450 if (rmdir(nyx_out_dir_path)) {
1451
1452 WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
1453
1454 }
1455
1456 ck_free(workdir_path);
1457 ck_free(nyx_out_dir_path);
1458
1459 }
1460
1461 #endif
1462
1463