aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMaik Betka <9078425+voidptr127@users.noreply.github.com>2023-04-21 11:31:22 +0200
committerMaik Betka <9078425+voidptr127@users.noreply.github.com>2023-04-21 11:31:22 +0200
commit7101ffa1ae79e15d70905b09decbe69cdf53367b (patch)
treefd34b5686a4522dd6d29c9a40cee3d9826b2c7c6 /src
parent9ab902402cd33156257fc0355c0105e7e03f5ba3 (diff)
parent4e5f42cab6b8c501eeaf76ec7ca920089f6e0f3a (diff)
downloadAFLplusplus-7101ffa1ae79e15d70905b09decbe69cdf53367b.tar.gz
Merge remote-tracking branch 'origin/dev' into atnwalk
# Conflicts: # include/afl-fuzz.h # src/afl-fuzz-run.c
Diffstat (limited to 'src')
-rw-r--r--src/afl-analyze.c170
-rw-r--r--src/afl-as.c24
-rw-r--r--src/afl-cc.c169
-rw-r--r--src/afl-common.c194
-rw-r--r--src/afl-forkserver.c347
-rw-r--r--src/afl-fuzz-bitmap.c58
-rw-r--r--src/afl-fuzz-cmplog.c12
-rw-r--r--src/afl-fuzz-extras.c2
-rw-r--r--src/afl-fuzz-init.c53
-rw-r--r--src/afl-fuzz-mutators.c109
-rw-r--r--src/afl-fuzz-one.c179
-rw-r--r--src/afl-fuzz-python.c108
-rw-r--r--src/afl-fuzz-queue.c134
-rw-r--r--src/afl-fuzz-redqueen.c35
-rw-r--r--src/afl-fuzz-run.c72
-rw-r--r--src/afl-fuzz-state.c67
-rw-r--r--src/afl-fuzz-stats.c156
-rw-r--r--src/afl-fuzz.c275
-rw-r--r--src/afl-gotcpu.c24
-rw-r--r--src/afl-ld-lto.c2
-rw-r--r--src/afl-sharedmem.c2
-rw-r--r--src/afl-showmap.c365
-rw-r--r--src/afl-tmin.c164
23 files changed, 1945 insertions, 776 deletions
diff --git a/src/afl-analyze.c b/src/afl-analyze.c
index d4822341..5b122741 100644
--- a/src/afl-analyze.c
+++ b/src/afl-analyze.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -114,16 +114,16 @@ static void kill_child() {
if (fsrv.child_pid > 0) {
- kill(fsrv.child_pid, fsrv.kill_signal);
+ kill(fsrv.child_pid, fsrv.child_kill_signal);
fsrv.child_pid = -1;
}
}
-static void classify_counts(u8 *mem) {
+static void classify_counts(u8 *mem, u32 mem_size) {
- u32 i = map_size;
+ u32 i = mem_size;
if (edges_only) {
@@ -203,7 +203,7 @@ static void read_initial_file(void) {
/* Execute target application. Returns exec checksum, or 0 if program
times out. */
-static u32 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
+static u64 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
afl_fsrv_write_to_testcase(&fsrv, mem, len);
fsrv_run_result_t ret = afl_fsrv_run_target(&fsrv, exec_tmout, &stop_soon);
@@ -222,7 +222,7 @@ static u32 analyze_run_target(u8 *mem, u32 len, u8 first_run) {
}
- classify_counts(fsrv.trace_bits);
+ classify_counts(fsrv.trace_bits, fsrv.map_size);
total_execs++;
if (stop_soon) {
@@ -528,7 +528,7 @@ static void analyze() {
for (i = 0; i < in_len; i++) {
- u32 xor_ff, xor_01, sub_10, add_10;
+ u64 xor_ff, xor_01, sub_10, add_10;
u8 xff_orig, x01_orig, s10_orig, a10_orig;
/* Perform walking byte adjustments across the file. We perform four
@@ -656,28 +656,6 @@ static void set_up_environment(char **argv) {
if (fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fsrv.out_file); }
/* Set sane defaults... */
-
- x = get_afl_env("ASAN_OPTIONS");
-
- if (x) {
-
- if (!strstr(x, "abort_on_error=1")) {
-
- FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
-
- }
-
-#ifndef ASAN_BUILD
- if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) {
-
- FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
-
- }
-
-#endif
-
- }
-
x = get_afl_env("MSAN_OPTIONS");
if (x) {
@@ -689,69 +667,9 @@ static void set_up_environment(char **argv) {
}
- if (!strstr(x, "symbolize=0")) {
-
- FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
-
- }
-
- }
-
- x = get_afl_env("LSAN_OPTIONS");
-
- if (x) {
-
- if (!strstr(x, "symbolize=0")) {
-
- FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
-
- }
-
}
- setenv("ASAN_OPTIONS",
- "abort_on_error=1:"
- "detect_leaks=0:"
- "allocator_may_return_null=1:"
- "detect_odr_violation=0:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 0);
-
- setenv("UBSAN_OPTIONS",
- "halt_on_error=1:"
- "abort_on_error=1:"
- "malloc_context_size=0:"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 0);
-
- setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "abort_on_error=1:"
- "msan_track_origins=0"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0", 0);
-
- setenv("LSAN_OPTIONS",
- "exitcode=" STRINGIFY(LSAN_ERROR) ":"
- "fast_unwind_on_malloc=0:"
- "symbolize=0:"
- "print_suppressions=0",
- 0);
+ set_sanitizer_defaults();
if (get_afl_env("AFL_PRELOAD")) {
@@ -807,7 +725,11 @@ static void setup_signal_handlers(void) {
struct sigaction sa;
sa.sa_handler = NULL;
+#ifdef SA_RESTART
sa.sa_flags = SA_RESTART;
+#else
+ sa.sa_flags = 0;
+#endif
sa.sa_sigaction = NULL;
sigemptyset(&sa.sa_mask);
@@ -846,6 +768,7 @@ static void usage(u8 *argv0) {
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine "
"mode)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
@@ -862,11 +785,15 @@ static void usage(u8 *argv0) {
"MSAN_OPTIONS: custom settings for MSAN\n"
" (must contain exitcode="STRINGIFY(MSAN_ERROR)" and symbolize=0)\n"
"AFL_ANALYZE_HEX: print file offsets in hexadecimal instead of decimal\n"
+ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n"
+ " (default: SIGKILL)\n"
+ "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n"
+ " (default: SIGTERM). If unset and AFL_KILL_SIGNAL is\n"
+ " set, that value will be used.\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_SKIP_BIN_CHECK: skip checking the location of and the target\n"
-
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
exit(1);
@@ -888,7 +815,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init(&fsrv);
- while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWXYh")) > 0) {
switch (opt) {
@@ -1040,6 +967,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'Y': // fallthough
+#ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv.nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv.nyx_mode = 1;
+ fsrv.nyx_parent = true;
+ fsrv.nyx_standalone = true;
+
+ break;
+#else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+#endif
+
case 'h':
usage(argv[0]);
return -1;
@@ -1071,7 +1015,21 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(argv);
+#ifdef __linux__
+ if (!fsrv.nyx_mode) {
+
+ fsrv.target_path = find_binary(argv[optind]);
+
+ } else {
+
+ fsrv.target_path = ck_strdup(argv[optind]);
+
+ }
+
+#else
fsrv.target_path = find_binary(argv[optind]);
+#endif
+
fsrv.trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, fsrv.out_file, &use_stdin);
signal(SIGALRM, kill_child);
@@ -1094,6 +1052,26 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind);
+#ifdef __linux__
+
+ } else if (fsrv.nyx_mode) {
+
+ fsrv.nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+ fsrv.nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv.nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv.nyx_use_tmp_workdir = true;
+ fsrv.nyx_bind_cpu_id = 0;
+
+ use_argv = argv + optind;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1115,11 +1093,15 @@ int main(int argc, char **argv_orig, char **envp) {
}
- fsrv.kill_signal =
- parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
+ configure_afl_kill_signals(
+ &fsrv, NULL, NULL, (fsrv.qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
read_initial_file();
+#ifdef __linux__
+ if (!fsrv.nyx_mode) { (void)check_binary_signatures(fsrv.target_path); }
+#else
(void)check_binary_signatures(fsrv.target_path);
+#endif
ACTF("Performing dry run (mem limit = %llu MB, timeout = %u ms%s)...",
mem_limit, exec_tmout, edges_only ? ", edges only" : "");
diff --git a/src/afl-as.c b/src/afl-as.c
index 1edc8cca..772e31b3 100644
--- a/src/afl-as.c
+++ b/src/afl-as.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -93,7 +93,7 @@ static u8 use_64bit = 0;
static void edit_params(int argc, char **argv) {
u8 *tmp_dir = getenv("TMPDIR"), *afl_as = getenv("AFL_AS");
- u32 i;
+ u32 i, input_index;
#ifdef __APPLE__
@@ -142,7 +142,23 @@ static void edit_params(int argc, char **argv) {
as_params[argc] = 0;
- for (i = 1; (s32)i < argc - 1; i++) {
+ /* Find the input file. It's usually located near the end.
+ Assume there won't be any arguments referring to files after the input
+ file, e.g. as input.s -o output.o */
+ for (input_index = argc - 1; input_index > 0; input_index--) {
+
+ input_file = argv[input_index];
+ /* Clang may add debug arguments after the input file. */
+ if (strncmp(input_file, "-g", 2)) break;
+
+ }
+
+ if (input_index == 0)
+ FATAL("Could not find input file (not called through afl-gcc?)");
+
+ for (i = 1; (s32)i < argc; i++) {
+
+ if (i == input_index) continue;
if (!strcmp(argv[i], "--64")) {
@@ -194,8 +210,6 @@ static void edit_params(int argc, char **argv) {
#endif /* __APPLE__ */
- input_file = argv[argc - 1];
-
if (input_file[0] == '-') {
if (!strcmp(input_file + 1, "-version")) {
diff --git a/src/afl-cc.c b/src/afl-cc.c
index c0449e64..7f15ad76 100644
--- a/src/afl-cc.c
+++ b/src/afl-cc.c
@@ -5,7 +5,7 @@
Written by Michal Zalewski, Laszlo Szekeres and Marc Heuse
Copyright 2015, 2016 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -317,7 +317,7 @@ void parse_fsanitize(char *string) {
char *tmp = malloc(strlen(ptr));
u32 count = 0, len, ende = 0;
- if (!new || !tmp) { FATAL("could not aquire memory"); }
+ if (!new || !tmp) { FATAL("could not acquire memory"); }
strcpy(new, "-fsanitize=");
do {
@@ -514,7 +514,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (lto_mode && have_instr_env) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] = alloc_printf(
"-fpass-plugin=%s/afl-llvm-lto-instrumentlist.so", obj_path);
#else
@@ -530,7 +532,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (getenv("AFL_LLVM_DICT2FILE")) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/afl-llvm-dict2file.so", obj_path);
#else
@@ -547,7 +551,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (getenv("LAF_SPLIT_SWITCHES") || getenv("AFL_LLVM_LAF_SPLIT_SWITCHES")) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
#else
@@ -564,7 +570,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/compare-transform-pass.so", obj_path);
#else
@@ -581,7 +589,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
getenv("AFL_LLVM_LAF_SPLIT_FLOATS")) {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/split-compares-pass.so", obj_path);
#else
@@ -604,10 +614,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
cc_params[cc_par_cnt++] = "-fno-inline";
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/cmplog-switches-pass.so", obj_path);
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/split-switches-pass.so", obj_path);
#else
@@ -666,15 +680,21 @@ static void edit_params(u32 argc, char **argv, char **envp) {
#endif
free(ld_path);
-#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13
+#if defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 15
+ // The NewPM implementation only works fully since LLVM 15.
+ cc_params[cc_par_cnt++] = alloc_printf(
+ "-Wl,--load-pass-plugin=%s/SanitizerCoverageLTO.so", obj_path);
+#elif defined(AFL_CLANG_LDPATH) && LLVM_MAJOR >= 13
cc_params[cc_par_cnt++] = "-Wl,--lto-legacy-pass-manager";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
#else
cc_params[cc_par_cnt++] = "-fno-experimental-new-pass-manager";
+ cc_params[cc_par_cnt++] =
+ alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
#endif
cc_params[cc_par_cnt++] = "-Wl,--allow-multiple-definition";
- cc_params[cc_par_cnt++] =
- alloc_printf("-Wl,-mllvm=-load=%s/SanitizerCoverageLTO.so", obj_path);
cc_params[cc_par_cnt++] = lto_flag;
} else {
@@ -699,7 +719,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] = alloc_printf(
"-fpass-plugin=%s/SanitizerCoveragePCGUARD.so", obj_path);
#else
@@ -737,7 +759,9 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else {
#if LLVM_MAJOR >= 11 /* use new pass manager */
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/afl-llvm-pass.so", obj_path);
#else
@@ -755,10 +779,14 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (cmplog_mode) {
#if LLVM_MAJOR >= 11
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] = alloc_printf(
"-fpass-plugin=%s/cmplog-instructions-pass.so", obj_path);
+ #if LLVM_MAJOR < 16
cc_params[cc_par_cnt++] = "-fexperimental-new-pass-manager";
+ #endif
cc_params[cc_par_cnt++] =
alloc_printf("-fpass-plugin=%s/cmplog-routines-pass.so", obj_path);
#else
@@ -949,7 +977,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
strncmp(libdir, "/lib", 4)) {
- cc_params[cc_par_cnt++] = "-rpath";
+ cc_params[cc_par_cnt++] = "-Wl,-rpath";
cc_params[cc_par_cnt++] = libdir;
} else {
@@ -1022,17 +1050,25 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (getenv("AFL_USE_CFISAN")) {
- if (!lto_mode) {
+ if (compiler_mode == GCC_PLUGIN || compiler_mode == GCC) {
- uint32_t i = 0, found = 0;
- while (envp[i] != NULL && !found)
- if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
- if (!found) cc_params[cc_par_cnt++] = "-flto";
+ cc_params[cc_par_cnt++] = "-fcf-protection=full";
- }
+ } else {
+
+ if (!lto_mode) {
- cc_params[cc_par_cnt++] = "-fsanitize=cfi";
- cc_params[cc_par_cnt++] = "-fvisibility=hidden";
+ uint32_t i = 0, found = 0;
+ while (envp[i] != NULL && !found)
+ if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
+ if (!found) cc_params[cc_par_cnt++] = "-flto";
+
+ }
+
+ cc_params[cc_par_cnt++] = "-fsanitize=cfi";
+ cc_params[cc_par_cnt++] = "-fvisibility=hidden";
+
+ }
}
@@ -1065,37 +1101,45 @@ static void edit_params(u32 argc, char **argv, char **envp) {
if (!have_c) cc_params[cc_par_cnt++] = "-lrt";
#endif
- cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
- /* When the user tries to use persistent or deferred forkserver modes by
- appending a single line to the program, we want to reliably inject a
- signature into the binary (to be picked up by afl-fuzz) and we want
- to call a function from the runtime .o file. This is unnecessarily
- painful for three reasons:
+ /* As documented in instrumentation/README.persistent_mode.md, deferred
+ forkserver initialization and persistent mode are not available in afl-gcc
+ and afl-clang. */
+ if (compiler_mode != GCC && compiler_mode != CLANG) {
- 1) We need to convince the compiler not to optimize out the signature.
- This is done with __attribute__((used)).
+ cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
- 2) We need to convince the linker, when called with -Wl,--gc-sections,
- not to do the same. This is done by forcing an assignment to a
- 'volatile' pointer.
+ /* When the user tries to use persistent or deferred forkserver modes by
+ appending a single line to the program, we want to reliably inject a
+ signature into the binary (to be picked up by afl-fuzz) and we want
+ to call a function from the runtime .o file. This is unnecessarily
+ painful for three reasons:
- 3) We need to declare __afl_persistent_loop() in the global namespace,
- but doing this within a method in a class is hard - :: and extern "C"
- are forbidden and __attribute__((alias(...))) doesn't work. Hence the
- __asm__ aliasing trick.
+ 1) We need to convince the compiler not to optimize out the signature.
+ This is done with __attribute__((used)).
- */
+ 2) We need to convince the linker, when called with -Wl,--gc-sections,
+ not to do the same. This is done by forcing an assignment to a
+ 'volatile' pointer.
- cc_params[cc_par_cnt++] =
- "-D__AFL_FUZZ_INIT()="
- "int __afl_sharedmem_fuzzing = 1;"
- "extern unsigned int *__afl_fuzz_len;"
- "extern unsigned char *__afl_fuzz_ptr;"
- "unsigned char __afl_fuzz_alt[1048576];"
- "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+ 3) We need to declare __afl_persistent_loop() in the global namespace,
+ but doing this within a method in a class is hard - :: and extern "C"
+ are forbidden and __attribute__((alias(...))) doesn't work. Hence the
+ __asm__ aliasing trick.
+
+ */
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_FUZZ_INIT()="
+ "int __afl_sharedmem_fuzzing = 1;"
+ "extern unsigned int *__afl_fuzz_len;"
+ "extern unsigned char *__afl_fuzz_ptr;"
+ "unsigned char __afl_fuzz_alt[1048576];"
+ "unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;";
+
+ }
if (plusplus_mode) {
@@ -1133,33 +1177,39 @@ static void edit_params(u32 argc, char **argv, char **envp) {
"(*__afl_fuzz_len = read(0, __afl_fuzz_alt_ptr, 1048576)) == 0xffffffff "
"? 0 : *__afl_fuzz_len)";
- cc_params[cc_par_cnt++] =
- "-D__AFL_LOOP(_A)="
- "({ static volatile char *_B __attribute__((used,unused)); "
- " _B = (char*)\"" PERSIST_SIG
- "\"; "
+ if (compiler_mode != GCC && compiler_mode != CLANG) {
+
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_LOOP(_A)="
+ "({ static volatile const char *_B __attribute__((used,unused)); "
+ " _B = (const char*)\"" PERSIST_SIG
+ "\"; "
+ "extern int __afl_connected;"
#ifdef __APPLE__
- "__attribute__((visibility(\"default\"))) "
- "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
#else
- "__attribute__((visibility(\"default\"))) "
- "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
#endif /* ^__APPLE__ */
- "_L(_A); })";
+ // if afl is connected, we run _A times, else once.
+ "_L(__afl_connected ? _A : 1); })";
- cc_params[cc_par_cnt++] =
- "-D__AFL_INIT()="
- "do { static volatile char *_A __attribute__((used,unused)); "
- " _A = (char*)\"" DEFER_SIG
- "\"; "
+ cc_params[cc_par_cnt++] =
+ "-D__AFL_INIT()="
+ "do { static volatile const char *_A __attribute__((used,unused)); "
+ " _A = (const char*)\"" DEFER_SIG
+ "\"; "
#ifdef __APPLE__
- "__attribute__((visibility(\"default\"))) "
- "void _I(void) __asm__(\"___afl_manual_init\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "void _I(void) __asm__(\"___afl_manual_init\"); "
#else
- "__attribute__((visibility(\"default\"))) "
- "void _I(void) __asm__(\"__afl_manual_init\"); "
+ "__attribute__((visibility(\"default\"))) "
+ "void _I(void) __asm__(\"__afl_manual_init\"); "
#endif /* ^__APPLE__ */
- "_I(); } while (0)";
+ "_I(); } while (0)";
+
+ }
if (x_set) {
@@ -2003,6 +2053,8 @@ int main(int argc, char **argv, char **envp) {
" AFL_LLVM_DICT2FILE: generate an afl dictionary based on found "
"comparisons\n"
+ " AFL_LLVM_DICT2FILE_NO_MAIN: skip parsing main() for the "
+ "dictionary\n"
" AFL_LLVM_LAF_ALL: enables all LAF splits/transforms\n"
" AFL_LLVM_LAF_SPLIT_COMPARES: enable cascaded comparisons\n"
" AFL_LLVM_LAF_SPLIT_COMPARES_BITW: size limit (default 8)\n"
@@ -2090,7 +2142,8 @@ int main(int argc, char **argv, char **envp) {
"defaults.\n"
"Recommended is afl-clang-lto with AFL_LLVM_CMPLOG or afl-clang-fast "
"with\n"
- "AFL_LLVM_CMPLOG and AFL_LLVM_DICT2FILE.\n\n");
+ "AFL_LLVM_CMPLOG and "
+ "AFL_LLVM_DICT2FILE+AFL_LLVM_DICT2FILE_NO_MAIN.\n\n");
exit(1);
diff --git a/src/afl-common.c b/src/afl-common.c
index f3e78ac5..a5c48e80 100644
--- a/src/afl-common.c
+++ b/src/afl-common.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include <stdlib.h>
#include <stdio.h>
+#include "forkserver.h"
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
@@ -47,6 +48,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <signal.h>
u8 be_quiet = 0;
u8 *doc_path = "";
@@ -56,6 +58,90 @@ u8 last_intr = 0;
#define AFL_PATH "/usr/local/lib/afl/"
#endif
+void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
+ size_t needlelen) {
+
+ if (unlikely(needlelen > haystacklen)) { return NULL; }
+
+ for (u32 i = 0; i <= haystacklen - needlelen; ++i) {
+
+ if (unlikely(memcmp(haystack + i, needle, needlelen) == 0)) {
+
+ return (void *)(haystack + i);
+
+ }
+
+ }
+
+ return (void *)NULL;
+
+}
+
+void set_sanitizer_defaults() {
+
+ /* Set sane defaults for ASAN if nothing else is specified. */
+ u8 *have_asan_options = getenv("ASAN_OPTIONS");
+ u8 *have_ubsan_options = getenv("UBSAN_OPTIONS");
+ u8 *have_msan_options = getenv("MSAN_OPTIONS");
+ u8 *have_lsan_options = getenv("LSAN_OPTIONS");
+ u8 have_san_options = 0;
+ u8 default_options[1024] =
+ "detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
+ "return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
+ "sigfpe=0:handle_sigill=0:";
+
+ if (have_asan_options || have_ubsan_options || have_msan_options ||
+ have_lsan_options) {
+
+ have_san_options = 1;
+
+ }
+
+ /* LSAN does not support abort_on_error=1. (is this still true??) */
+
+ if (!have_lsan_options) {
+
+ u8 buf[2048] = "";
+ if (!have_san_options) { strcpy(buf, default_options); }
+ strcat(buf, "exitcode=" STRINGIFY(LSAN_ERROR) ":fast_unwind_on_malloc=0:print_suppressions=0:detect_leaks=1:malloc_context_size=30:");
+ setenv("LSAN_OPTIONS", buf, 1);
+
+ }
+
+ /* for everything not LSAN we disable detect_leaks */
+
+ if (!have_lsan_options) {
+
+ strcat(default_options, "detect_leaks=0:malloc_context_size=0:");
+
+ }
+
+ /* Set sane defaults for ASAN if nothing else is specified. */
+
+ if (!have_san_options) { setenv("ASAN_OPTIONS", default_options, 1); }
+
+ /* Set sane defaults for UBSAN if nothing else is specified. */
+
+ if (!have_san_options) { setenv("UBSAN_OPTIONS", default_options, 1); }
+
+ /* MSAN is tricky, because it doesn't support abort_on_error=1 at this
+ point. So, we do this in a very hacky way. */
+
+ if (!have_msan_options) {
+
+ u8 buf[2048] = "";
+ if (!have_san_options) { strcpy(buf, default_options); }
+ strcat(buf, "exit_code=" STRINGIFY(MSAN_ERROR) ":msan_track_origins=0:");
+ setenv("MSAN_OPTIONS", buf, 1);
+
+ }
+
+ /* Envs for QASan */
+ setenv("QASAN_MAX_CALL_STACK", "0", 0);
+ setenv("QASAN_SYMBOLIZE", "0", 0);
+
+}
+
u32 check_binary_signatures(u8 *fn) {
int ret = 0, fd = open(fn, O_RDONLY);
@@ -67,7 +153,7 @@ u32 check_binary_signatures(u8 *fn) {
if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
close(fd);
- if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
+ if (afl_memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
if (!be_quiet) { OKF(cPIN "Persistent mode binary detected."); }
setenv(PERSIST_ENV_VAR, "1", 1);
@@ -92,7 +178,7 @@ u32 check_binary_signatures(u8 *fn) {
}
- if (memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
+ if (afl_memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
if (!be_quiet) { OKF(cPIN "Deferred forkserver binary detected."); }
setenv(DEFER_ENV_VAR, "1", 1);
@@ -456,38 +542,57 @@ u8 *find_afl_binary(u8 *own_loc, u8 *fname) {
}
-/* Parses the kill signal environment variable, FATALs on error.
- If the env is not set, sets the env to default_signal for the signal handlers
- and returns the default_signal. */
-int parse_afl_kill_signal_env(u8 *afl_kill_signal_env, int default_signal) {
+int parse_afl_kill_signal(u8 *numeric_signal_as_str, int default_signal) {
- if (afl_kill_signal_env && afl_kill_signal_env[0]) {
+ if (numeric_signal_as_str && numeric_signal_as_str[0]) {
char *endptr;
u8 signal_code;
- signal_code = (u8)strtoul(afl_kill_signal_env, &endptr, 10);
+ signal_code = (u8)strtoul(numeric_signal_as_str, &endptr, 10);
/* Did we manage to parse the full string? */
- if (*endptr != '\0' || endptr == (char *)afl_kill_signal_env) {
+ if (*endptr != '\0' || endptr == (char *)numeric_signal_as_str) {
+
+ FATAL("Invalid signal name: %s", numeric_signal_as_str);
- FATAL("Invalid AFL_KILL_SIGNAL: %s (expected unsigned int)",
- afl_kill_signal_env);
+ } else {
+
+ return signal_code;
}
- return signal_code;
+ }
+
+ return default_signal;
- } else {
+}
+
+void configure_afl_kill_signals(afl_forkserver_t *fsrv,
+ char *afl_kill_signal_env,
+ char *afl_fsrv_kill_signal_env,
+ int default_server_kill_signal) {
+
+ afl_kill_signal_env =
+ afl_kill_signal_env ? afl_kill_signal_env : getenv("AFL_KILL_SIGNAL");
+ afl_fsrv_kill_signal_env = afl_fsrv_kill_signal_env
+ ? afl_fsrv_kill_signal_env
+ : getenv("AFL_FORK_SERVER_KILL_SIGNAL");
- char *sigstr = alloc_printf("%d", default_signal);
- if (!sigstr) { FATAL("Failed to alloc mem for signal buf"); }
+ fsrv->child_kill_signal = parse_afl_kill_signal(afl_kill_signal_env, SIGKILL);
- /* Set the env for signal handler */
- setenv("AFL_KILL_SIGNAL", sigstr, 1);
- free(sigstr);
- return default_signal;
+ if (afl_kill_signal_env && !afl_fsrv_kill_signal_env) {
+
+ /*
+ Set AFL_FORK_SERVER_KILL_SIGNAL to the value of AFL_KILL_SIGNAL for
+ backwards compatibility. However, if AFL_FORK_SERVER_KILL_SIGNAL is set, is
+ takes precedence.
+ */
+ afl_fsrv_kill_signal_env = afl_kill_signal_env;
}
+ fsrv->fsrv_kill_signal = parse_afl_kill_signal(afl_fsrv_kill_signal_env,
+ default_server_kill_signal);
+
}
static inline unsigned int helper_min3(unsigned int a, unsigned int b,
@@ -1254,3 +1359,52 @@ s32 create_file(u8 *fn) {
}
+#ifdef __linux__
+
+/* Nyx requires a tmp workdir to access specific files (such as mmapped files,
+ * etc.). This helper function basically creates both a path to a tmp workdir
+ * and the workdir itself. If the environment variable TMPDIR is set, we use
+ * that as the base directory, otherwise we use /tmp. */
+char *create_nyx_tmp_workdir(void) {
+
+ char *tmpdir = getenv("TMPDIR");
+
+ if (!tmpdir) { tmpdir = "/tmp"; }
+
+ char *nyx_out_dir_path =
+ alloc_printf("%s/.nyx_tmp_%d/", tmpdir, (u32)getpid());
+
+ if (mkdir(nyx_out_dir_path, 0700)) { PFATAL("Unable to create nyx workdir"); }
+
+ return nyx_out_dir_path;
+
+}
+
+/* Vice versa, we remove the tmp workdir for nyx with this helper function. */
+void remove_nyx_tmp_workdir(afl_forkserver_t *fsrv, char *nyx_out_dir_path) {
+
+ char *workdir_path = alloc_printf("%s/workdir", nyx_out_dir_path);
+
+ if (access(workdir_path, R_OK) == 0) {
+
+ if (fsrv->nyx_handlers->nyx_remove_work_dir(workdir_path) != true) {
+
+ WARNF("Unable to remove nyx workdir (%s)", workdir_path);
+
+ }
+
+ }
+
+ if (rmdir(nyx_out_dir_path)) {
+
+ WARNF("Unable to remove nyx workdir (%s)", nyx_out_dir_path);
+
+ }
+
+ ck_free(workdir_path);
+ ck_free(nyx_out_dir_path);
+
+}
+
+#endif
+
diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c
index 628ff590..aa8c8622 100644
--- a/src/afl-forkserver.c
+++ b/src/afl-forkserver.c
@@ -13,7 +13,7 @@
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -49,6 +49,134 @@
#include <sys/select.h>
#include <sys/stat.h>
+#ifdef __linux__
+ #include <dlfcn.h>
+
+/* function to load nyx_helper function from libnyx.so */
+
+nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
+
+ void *handle;
+ nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
+
+ ACTF("Trying to load libnyx.so plugin...");
+ handle = dlopen((char *)libnyx_binary, RTLD_NOW);
+ if (!handle) { goto fail; }
+
+ plugin->nyx_config_load = dlsym(handle, "nyx_config_load");
+ if (plugin->nyx_config_load == NULL) { goto fail; }
+
+ plugin->nyx_config_set_workdir_path =
+ dlsym(handle, "nyx_config_set_workdir_path");
+ if (plugin->nyx_config_set_workdir_path == NULL) { goto fail; }
+
+ plugin->nyx_config_set_input_buffer_size =
+ dlsym(handle, "nyx_config_set_input_buffer_size");
+ if (plugin->nyx_config_set_input_buffer_size == NULL) { goto fail; }
+
+ plugin->nyx_config_set_input_buffer_write_protection =
+ dlsym(handle, "nyx_config_set_input_buffer_write_protection");
+ if (plugin->nyx_config_set_input_buffer_write_protection == NULL) {
+
+ goto fail;
+
+ }
+
+ plugin->nyx_config_set_hprintf_fd =
+ dlsym(handle, "nyx_config_set_hprintf_fd");
+ if (plugin->nyx_config_set_hprintf_fd == NULL) { goto fail; }
+
+ plugin->nyx_config_set_process_role =
+ dlsym(handle, "nyx_config_set_process_role");
+ if (plugin->nyx_config_set_process_role == NULL) { goto fail; }
+
+ plugin->nyx_config_set_reuse_snapshot_path =
+ dlsym(handle, "nyx_config_set_reuse_snapshot_path");
+ if (plugin->nyx_config_set_reuse_snapshot_path == NULL) { goto fail; }
+
+ plugin->nyx_new = dlsym(handle, "nyx_new");
+ if (plugin->nyx_new == NULL) { goto fail; }
+
+ plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
+ if (plugin->nyx_shutdown == NULL) { goto fail; }
+
+ plugin->nyx_option_set_reload_mode =
+ dlsym(handle, "nyx_option_set_reload_mode");
+ if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
+
+ plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
+ if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
+
+ plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
+ if (plugin->nyx_option_apply == NULL) { goto fail; }
+
+ plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
+ if (plugin->nyx_set_afl_input == NULL) { goto fail; }
+
+ plugin->nyx_exec = dlsym(handle, "nyx_exec");
+ if (plugin->nyx_exec == NULL) { goto fail; }
+
+ plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
+ if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
+
+ plugin->nyx_get_bitmap_buffer_size =
+ dlsym(handle, "nyx_get_bitmap_buffer_size");
+ if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
+
+ plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
+ if (plugin->nyx_get_aux_string == NULL) { goto fail; }
+
+ plugin->nyx_remove_work_dir = dlsym(handle, "nyx_remove_work_dir");
+ if (plugin->nyx_remove_work_dir == NULL) { goto fail; }
+
+ OKF("libnyx plugin is ready!");
+ return plugin;
+
+fail:
+
+ FATAL("failed to load libnyx: %s\n", dlerror());
+ ck_free(plugin);
+ return NULL;
+
+}
+
+void afl_nyx_runner_kill(afl_forkserver_t *fsrv) {
+
+ if (fsrv->nyx_mode) {
+
+ if (fsrv->nyx_aux_string) { ck_free(fsrv->nyx_aux_string); }
+
+ /* check if we actually got a valid nyx runner */
+ if (fsrv->nyx_runner) {
+
+ fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
+
+ }
+
+ /* if we have use a tmp work dir we need to remove it */
+ if (fsrv->nyx_use_tmp_workdir && fsrv->nyx_tmp_workdir_path) {
+
+ remove_nyx_tmp_workdir(fsrv, fsrv->nyx_tmp_workdir_path);
+
+ }
+
+ }
+
+}
+
+ /* Wrapper for FATAL() that kills the nyx runner (and removes all created tmp
+ * files) before exiting. Used before "afl_fsrv_killall()" is registered as
+ * an atexit() handler. */
+ #define NYX_PRE_FATAL(fsrv, x...) \
+ do { \
+ \
+ afl_nyx_runner_kill(fsrv); \
+ FATAL(x); \
+ \
+ } while (0)
+
+#endif
+
/**
* The correct fds for reading and writing pipes
*/
@@ -84,6 +212,8 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->nyx_runner = NULL;
fsrv->nyx_id = 0xFFFFFFFF;
fsrv->nyx_bind_cpu_id = 0xFFFFFFFF;
+ fsrv->nyx_use_tmp_workdir = false;
+ fsrv->nyx_tmp_workdir_path = NULL;
#endif
// this structure needs default so we initialize it if this was not done
@@ -100,7 +230,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
fsrv->mem_limit = MEM_LIMIT;
fsrv->out_file = NULL;
- fsrv->kill_signal = SIGKILL;
+ fsrv->child_kill_signal = SIGKILL;
/* exec related stuff */
fsrv->child_pid = -1;
@@ -134,7 +264,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->no_unlink = from->no_unlink;
fsrv_to->uses_crash_exitcode = from->uses_crash_exitcode;
fsrv_to->crash_exitcode = from->crash_exitcode;
- fsrv_to->kill_signal = from->kill_signal;
+ fsrv_to->child_kill_signal = from->child_kill_signal;
fsrv_to->debug = from->debug;
// These are forkserver specific.
@@ -397,40 +527,119 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!be_quiet) { ACTF("Spinning up the NYX backend..."); }
- if (fsrv->out_dir_path == NULL) { FATAL("Nyx workdir path not found..."); }
+ if (fsrv->nyx_use_tmp_workdir) {
+
+ fsrv->nyx_tmp_workdir_path = create_nyx_tmp_workdir();
+ fsrv->out_dir_path = fsrv->nyx_tmp_workdir_path;
+
+ } else {
+
+ if (fsrv->out_dir_path == NULL) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx workdir path not found...");
+
+ }
+
+ }
+
+ /* libnyx expects an absolute path */
+ char *outdir_path_absolute = realpath(fsrv->out_dir_path, NULL);
+ if (outdir_path_absolute == NULL) {
- char *x = alloc_printf("%s/workdir", fsrv->out_dir_path);
+ NYX_PRE_FATAL(fsrv, "Nyx workdir path cannot be resolved ...");
- if (fsrv->nyx_id == 0xFFFFFFFF) { FATAL("Nyx ID is not set..."); }
+ }
+
+ char *workdir_path = alloc_printf("%s/workdir", outdir_path_absolute);
+
+ if (fsrv->nyx_id == 0xFFFFFFFF) {
+
+ NYX_PRE_FATAL(fsrv, "Nyx ID is not set...");
+
+ }
if (fsrv->nyx_bind_cpu_id == 0xFFFFFFFF) {
- FATAL("Nyx CPU ID is not set...");
+ NYX_PRE_FATAL(fsrv, "Nyx CPU ID is not set...");
}
+ void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
+
+ fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
+ fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
+ true);
+
if (fsrv->nyx_standalone) {
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, StandAlone);
} else {
if (fsrv->nyx_parent) {
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_parent(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, MAX_FILE, true);
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Parent);
} else {
- fsrv->nyx_runner = fsrv->nyx_handlers->nyx_new_child(
- fsrv->target_path, x, fsrv->nyx_bind_cpu_id, fsrv->nyx_id);
+ fsrv->nyx_handlers->nyx_config_set_process_role(nyx_config, Child);
+
+ }
+
+ }
+
+ if (getenv("NYX_REUSE_SNAPSHOT") != NULL) {
+
+ if (access(getenv("NYX_REUSE_SNAPSHOT"), F_OK) == -1) {
+
+ NYX_PRE_FATAL(fsrv, "NYX_REUSE_SNAPSHOT path does not exist");
+
+ }
+
+ /* stupid sanity check to avoid passing an empty or invalid snapshot
+ * directory */
+ char *snapshot_file_path =
+ alloc_printf("%s/global.state", getenv("NYX_REUSE_SNAPSHOT"));
+ if (access(snapshot_file_path, R_OK) == -1) {
+
+ NYX_PRE_FATAL(
+ fsrv,
+ "NYX_REUSE_SNAPSHOT path does not contain a valid Nyx snapshot");
+
+ }
+
+ ck_free(snapshot_file_path);
+
+ /* another sanity check to avoid passing a snapshot directory that is
+ * located in the current workdir (the workdir will be wiped by libnyx on
+ * startup) */
+ char *workdir_snapshot_path =
+ alloc_printf("%s/workdir/snapshot", outdir_path_absolute);
+ char *reuse_snapshot_path_real =
+ realpath(getenv("NYX_REUSE_SNAPSHOT"), NULL);
+
+ if (strcmp(workdir_snapshot_path, reuse_snapshot_path_real) == 0) {
+
+ NYX_PRE_FATAL(fsrv,
+ "NYX_REUSE_SNAPSHOT path is located in current workdir "
+ "(use another output directory)");
}
+ ck_free(reuse_snapshot_path_real);
+ ck_free(workdir_snapshot_path);
+
+ fsrv->nyx_handlers->nyx_config_set_reuse_snapshot_path(
+ nyx_config, getenv("NYX_REUSE_SNAPSHOT"));
+
}
- ck_free(x);
+ fsrv->nyx_runner =
+ fsrv->nyx_handlers->nyx_new(nyx_config, fsrv->nyx_bind_cpu_id);
+
+ ck_free(workdir_path);
+ ck_free(outdir_path_absolute);
if (fsrv->nyx_runner == NULL) { FATAL("Something went wrong ..."); }
@@ -458,15 +667,13 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
switch (fsrv->nyx_handlers->nyx_exec(fsrv->nyx_runner)) {
case Abort:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
- FATAL("Error: Nyx abort occured...");
+ NYX_PRE_FATAL(fsrv, "Error: Nyx abort occured...");
break;
case IoError:
- FATAL("Error: QEMU-Nyx has died...");
+ NYX_PRE_FATAL(fsrv, "Error: QEMU-Nyx has died...");
break;
case Error:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
- FATAL("Error: Nyx runtime error has occured...");
+ NYX_PRE_FATAL(fsrv, "Error: Nyx runtime error has occured...");
break;
default:
break;
@@ -476,7 +683,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
/* autodict in Nyx mode */
if (!ignore_autodict) {
- x = alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
+ char *x =
+ alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
int nyx_autodict_fd = open(x, O_RDONLY);
ck_free(x);
@@ -489,8 +697,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
u8 *dict = ck_alloc(f_len);
if (dict == NULL) {
- FATAL("Could not allocate %u bytes of autodictionary memory",
- f_len);
+ NYX_PRE_FATAL(
+ fsrv, "Could not allocate %u bytes of autodictionary memory",
+ f_len);
}
@@ -507,7 +716,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
} else {
- FATAL(
+ NYX_PRE_FATAL(
+ fsrv,
"Reading autodictionary fail at position %u with %u bytes "
"left.",
offset, len);
@@ -688,70 +898,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (!getenv("LD_BIND_LAZY")) { setenv("LD_BIND_NOW", "1", 1); }
- /* Set sane defaults for ASAN if nothing else is specified. */
-
- if (!getenv("ASAN_OPTIONS"))
- setenv("ASAN_OPTIONS",
- "abort_on_error=1:"
- "detect_leaks=0:"
- "malloc_context_size=0:"
- "symbolize=0:"
- "allocator_may_return_null=1:"
- "detect_odr_violation=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 1);
-
- /* Set sane defaults for UBSAN if nothing else is specified. */
-
- if (!getenv("UBSAN_OPTIONS"))
- setenv("UBSAN_OPTIONS",
- "halt_on_error=1:"
- "abort_on_error=1:"
- "malloc_context_size=0:"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 1);
-
- /* Envs for QASan */
- setenv("QASAN_MAX_CALL_STACK", "0", 0);
- setenv("QASAN_SYMBOLIZE", "0", 0);
-
- /* MSAN is tricky, because it doesn't support abort_on_error=1 at this
- point. So, we do this in a very hacky way. */
-
- if (!getenv("MSAN_OPTIONS"))
- setenv("MSAN_OPTIONS",
- "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "symbolize=0:"
- "abort_on_error=1:"
- "malloc_context_size=0:"
- "allocator_may_return_null=1:"
- "msan_track_origins=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 1);
-
- /* LSAN, too, does not support abort_on_error=1. */
-
- if (!getenv("LSAN_OPTIONS"))
- setenv("LSAN_OPTIONS",
- "exitcode=" STRINGIFY(LSAN_ERROR) ":"
- "fast_unwind_on_malloc=0:"
- "symbolize=0:"
- "print_suppressions=0",
- 1);
+ /* Set sane defaults for sanitizers */
+ set_sanitizer_defaults();
fsrv->init_child_func(fsrv, argv);
@@ -793,7 +941,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
s32 tmp_pid = fsrv->fsrv_pid;
if (tmp_pid > 0) {
- kill(tmp_pid, fsrv->kill_signal);
+ kill(tmp_pid, fsrv->child_kill_signal);
fsrv->fsrv_pid = -1;
}
@@ -804,7 +952,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
s32 tmp_pid = fsrv->fsrv_pid;
if (tmp_pid > 0) {
- kill(tmp_pid, fsrv->kill_signal);
+ kill(tmp_pid, fsrv->child_kill_signal);
fsrv->fsrv_pid = -1;
}
@@ -1242,11 +1390,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
void afl_fsrv_kill(afl_forkserver_t *fsrv) {
- if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->kill_signal); }
+ if (fsrv->child_pid > 0) { kill(fsrv->child_pid, fsrv->child_kill_signal); }
if (fsrv->fsrv_pid > 0) {
- kill(fsrv->fsrv_pid, fsrv->kill_signal);
- if (waitpid(fsrv->fsrv_pid, NULL, 0) <= 0) { WARNF("error waitpid\n"); }
+ kill(fsrv->fsrv_pid, fsrv->fsrv_kill_signal);
+ waitpid(fsrv->fsrv_pid, NULL, 0);
}
@@ -1256,13 +1404,7 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
fsrv->child_pid = -1;
#ifdef __linux__
- if (fsrv->nyx_mode) {
-
- free(fsrv->nyx_aux_string);
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
-
- }
-
+ afl_nyx_runner_kill(fsrv);
#endif
}
@@ -1432,14 +1574,13 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
case Crash:
case Asan:
return FSRV_RUN_CRASH;
- case Timout:
+ case Timeout:
return FSRV_RUN_TMOUT;
case InvalidWriteToPayload:
/* ??? */
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
break;
case Abort:
- fsrv->nyx_handlers->nyx_shutdown(fsrv->nyx_runner);
FATAL("Error: Nyx abort occured...");
case IoError:
if (*stop_soon_p) {
@@ -1545,7 +1686,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
s32 tmp_pid = fsrv->child_pid;
if (tmp_pid > 0) {
- kill(tmp_pid, fsrv->kill_signal);
+ kill(tmp_pid, fsrv->child_kill_signal);
fsrv->child_pid = -1;
}
@@ -1605,7 +1746,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
/* Did we timeout? */
if (unlikely(fsrv->last_run_timed_out)) {
- fsrv->last_kill_signal = fsrv->kill_signal;
+ fsrv->last_kill_signal = fsrv->child_kill_signal;
return FSRV_RUN_TMOUT;
}
diff --git a/src/afl-fuzz-bitmap.c b/src/afl-fuzz-bitmap.c
index b3a10bb7..556bb5d1 100644
--- a/src/afl-fuzz-bitmap.c
+++ b/src/afl-fuzz-bitmap.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -457,9 +457,16 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (unlikely(len == 0)) { return 0; }
+ if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
+
+ return 0;
+
+ }
+
u8 fn[PATH_MAX];
u8 *queue_fn = "";
- u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0;
+ u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0,
+ need_hash = 1;
s32 fd;
u64 cksum = 0;
@@ -469,10 +476,14 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
only be used for special schedules */
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
+ classify_counts(&afl->fsrv);
+ classified = 1;
+ need_hash = 0;
+
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
/* Saturated increment */
- if (afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF)
+ if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
afl->n_fuzz[cksum % N_FUZZ_SIZE]++;
}
@@ -482,7 +493,17 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
/* Keep only if there are new bits in the map, add to queue for
future fuzzing, etc. */
- new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
+ if (likely(classified)) {
+
+ new_bits = has_new_bits(afl, afl->virgin_bits);
+
+ } else {
+
+ new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
+
+ if (unlikely(new_bits)) { classified = 1; }
+
+ }
if (likely(!new_bits)) {
@@ -491,8 +512,6 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
- classified = new_bits;
-
save_to_queue:
#ifndef SIMPLE_FILES
@@ -550,21 +569,25 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
}
- /* AFLFast schedule? update the new queue entry */
- if (cksum) {
+ if (unlikely(need_hash && new_bits)) {
+
+ /* due to classify counts we have to recalculate the checksum */
+ afl->queue_top->exec_cksum =
+ hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
+ need_hash = 0;
+
+ }
+
+ /* For AFLFast schedules we update the new queue entry */
+ if (likely(cksum)) {
afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
}
- /* due to classify counts we have to recalculate the checksum */
- afl->queue_top->exec_cksum =
- hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
-
/* Try to calibrate inline; this also calls update_bitmap_score() when
successful. */
-
res = calibrate_case(afl, afl->queue_top, mem, afl->queue_cycle - 1, 0);
if (unlikely(res == FSRV_RUN_ERROR)) {
@@ -598,7 +621,7 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (likely(!afl->non_instrumented_mode)) {
- if (!classified) {
+ if (unlikely(!classified)) {
classify_counts(&afl->fsrv);
classified = 1;
@@ -723,7 +746,12 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
if (likely(!afl->non_instrumented_mode)) {
- if (!classified) { classify_counts(&afl->fsrv); }
+ if (unlikely(!classified)) {
+
+ classify_counts(&afl->fsrv);
+ classified = 1;
+
+ }
simplify_trace(afl, afl->fsrv.trace_bits);
diff --git a/src/afl-fuzz-cmplog.c b/src/afl-fuzz-cmplog.c
index d0c829e2..3e6432ca 100644
--- a/src/afl-fuzz-cmplog.c
+++ b/src/afl-fuzz-cmplog.c
@@ -11,7 +11,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -33,15 +33,19 @@ void cmplog_exec_child(afl_forkserver_t *fsrv, char **argv) {
setenv("___AFL_EINS_ZWEI_POLIZEI___", "1", 1);
- if (fsrv->qemu_mode) { setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0); }
+ if (fsrv->qemu_mode || fsrv->cs_mode) {
+
+ setenv("AFL_DISABLE_LLVM_INSTRUMENTATION", "1", 0);
+
+ }
if (!fsrv->qemu_mode && !fsrv->frida_mode && argv[0] != fsrv->cmplog_binary) {
- argv[0] = fsrv->cmplog_binary;
+ fsrv->target_path = argv[0] = fsrv->cmplog_binary;
}
- execv(argv[0], argv);
+ execv(fsrv->target_path, argv);
}
diff --git a/src/afl-fuzz-extras.c b/src/afl-fuzz-extras.c
index 884bb569..f6de11ae 100644
--- a/src/afl-fuzz-extras.c
+++ b/src/afl-fuzz-extras.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c
index 4ffcfd2b..01d1e82e 100644
--- a/src/afl-fuzz-init.c
+++ b/src/afl-fuzz-init.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -24,7 +24,9 @@
*/
#include "afl-fuzz.h"
+#include "common.h"
#include <limits.h>
+#include <string.h>
#include "cmplog.h"
#ifdef HAVE_AFFINITY
@@ -1120,7 +1122,7 @@ void perform_dry_run(afl_state_t *afl) {
}
- if (q->var_behavior) {
+ if (unlikely(q->var_behavior && !afl->afl_env.afl_no_warn_instability)) {
WARNF("Instrumentation output varies across runs.");
@@ -1817,17 +1819,35 @@ static void handle_existing_out_dir(afl_state_t *afl) {
if (afl->file_extension) {
- fn = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
+ fn = alloc_printf("%s/.cur_input.%s", afl->out_dir, afl->file_extension);
} else {
- fn = alloc_printf("%s/.cur_input", afl->tmp_dir);
+ fn = alloc_printf("%s/.cur_input", afl->out_dir);
}
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn);
+ if (afl->afl_env.afl_tmpdir) {
+
+ if (afl->file_extension) {
+
+ fn = alloc_printf("%s/.cur_input.%s", afl->afl_env.afl_tmpdir,
+ afl->file_extension);
+
+ } else {
+
+ fn = alloc_printf("%s/.cur_input", afl->afl_env.afl_tmpdir);
+
+ }
+
+ if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
+ ck_free(fn);
+
+ }
+
fn = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn);
@@ -1848,6 +1868,10 @@ static void handle_existing_out_dir(afl_state_t *afl) {
}
+ fn = alloc_printf("%s/queue_data", afl->out_dir);
+ if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
+ ck_free(fn);
+
fn = alloc_printf("%s/cmdline", afl->out_dir);
if (unlink(fn) && errno != ENOENT) { goto dir_cleanup_failed; }
ck_free(fn);
@@ -2420,7 +2444,9 @@ void get_core_count(afl_state_t *afl) {
} else if ((s64)cur_runnable + 1 <= (s64)afl->cpu_core_count) {
- OKF("Try parallel jobs - see %s/parallel_fuzzing.md.", doc_path);
+ OKF("Try parallel jobs - see "
+ "%s/fuzzing_in_depth.md#c-using-multiple-cores",
+ doc_path);
}
@@ -2762,7 +2788,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
!afl->fsrv.nyx_mode &&
#endif
!afl->fsrv.cs_mode && !afl->non_instrumented_mode &&
- !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
+ !afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST
"Looks like the target binary is not instrumented! The fuzzer depends "
@@ -2793,7 +2819,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) &&
- memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
+ afl_memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST
"This program appears to be instrumented with afl-gcc, but is being "
@@ -2806,9 +2832,9 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
- if (memmem(f_data, f_len, "__asan_init", 11) ||
- memmem(f_data, f_len, "__msan_init", 11) ||
- memmem(f_data, f_len, "__lsan_init", 11)) {
+ if (afl_memmem(f_data, f_len, "__asan_init", 11) ||
+ afl_memmem(f_data, f_len, "__msan_init", 11) ||
+ afl_memmem(f_data, f_len, "__lsan_init", 11)) {
afl->fsrv.uses_asan = 1;
@@ -2816,7 +2842,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
/* Detect persistent & deferred init signatures in the binary. */
- if (memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
+ if (afl_memmem(f_data, f_len, PERSIST_SIG, strlen(PERSIST_SIG) + 1)) {
OKF(cPIN "Persistent mode binary detected.");
setenv(PERSIST_ENV_VAR, "1", 1);
@@ -2843,7 +2869,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
}
if (afl->fsrv.frida_mode ||
- memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
+ afl_memmem(f_data, f_len, DEFER_SIG, strlen(DEFER_SIG) + 1)) {
OKF(cPIN "Deferred forkserver binary detected.");
setenv(DEFER_ENV_VAR, "1", 1);
@@ -2899,8 +2925,11 @@ void setup_signal_handlers(void) {
struct sigaction sa;
+ memset((void *)&sa, 0, sizeof(sa));
sa.sa_handler = NULL;
+#ifdef SA_RESTART
sa.sa_flags = SA_RESTART;
+#endif
sa.sa_sigaction = NULL;
sigemptyset(&sa.sa_mask);
diff --git a/src/afl-fuzz-mutators.c b/src/afl-fuzz-mutators.c
index b9daebfa..64dbe7c6 100644
--- a/src/afl-fuzz-mutators.c
+++ b/src/afl-fuzz-mutators.c
@@ -10,7 +10,7 @@
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -179,11 +179,19 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
void *dh;
struct custom_mutator *mutator = ck_alloc(sizeof(struct custom_mutator));
- mutator->name = fn;
- if (memchr(fn, '/', strlen(fn)))
- mutator->name_short = strrchr(fn, '/') + 1;
- else
+ if (memchr(fn, '/', strlen(fn))) {
+
+ mutator->name_short = strdup(strrchr(fn, '/') + 1);
+
+ } else {
+
mutator->name_short = strdup(fn);
+
+ }
+
+ if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; }
+
+ mutator->name = fn;
ACTF("Loading custom mutator library from '%s'...", fn);
dh = dlopen(fn, RTLD_NOW);
@@ -211,8 +219,16 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
WARNF("Symbol 'afl_custom_mutator' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_mutator'.");
+
}
+ } else {
+
+ OKF("Found 'afl_custom_mutator'.");
+
}
/* "afl_custom_introspection", optional */
@@ -222,6 +238,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_introspection' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_introspection'.");
+
}
#endif
@@ -232,6 +252,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_fuzz_count'.");
+
}
/* "afl_custom_deinit", optional for backward compatibility */
@@ -248,6 +272,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_post_process' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_post_process'.");
+
}
u8 notrim = 0;
@@ -258,6 +286,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
notrim = 1;
ACTF("optional symbol 'afl_custom_init_trim' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_init_trim'.");
+
}
/* "afl_custom_trim", optional */
@@ -267,6 +299,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
notrim = 1;
ACTF("optional symbol 'afl_custom_trim' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_trim'.");
+
}
/* "afl_custom_post_trim", optional */
@@ -276,16 +312,26 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
notrim = 1;
ACTF("optional symbol 'afl_custom_post_trim' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_post_trim'.");
+
}
if (notrim) {
+ if (mutator->afl_custom_init_trim || mutator->afl_custom_trim ||
+ mutator->afl_custom_post_trim) {
+
+ WARNF(
+ "Custom mutator does not implement all three trim APIs, standard "
+ "trimming will be used.");
+
+ }
+
mutator->afl_custom_init_trim = NULL;
mutator->afl_custom_trim = NULL;
mutator->afl_custom_post_trim = NULL;
- ACTF(
- "Custom mutator does not implement all three trim APIs, standard "
- "trimming will be used.");
}
@@ -295,6 +341,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_havoc_mutation' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_havoc_mutation'.");
+
}
/* "afl_custom_havoc_mutation", optional */
@@ -304,6 +354,10 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_havoc_mutation_probability' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_havoc_mutation_probability'.");
+
}
/* "afl_custom_queue_get", optional */
@@ -312,6 +366,35 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_queue_get' not found.");
+ } else {
+
+ OKF("Found 'afl_custom_queue_get'.");
+
+ }
+
+ /* "afl_custom_splice_optout", optional, never called */
+ mutator->afl_custom_splice_optout = dlsym(dh, "afl_custom_splice_optout");
+ if (!mutator->afl_custom_splice_optout) {
+
+ ACTF("optional symbol 'afl_custom_splice_optout' not found.");
+
+ } else {
+
+ OKF("Found 'afl_custom_splice_optout'.");
+ afl->custom_splice_optout = 1;
+
+ }
+
+ /* "afl_custom_fuzz_send", optional */
+ mutator->afl_custom_fuzz_send = dlsym(dh, "afl_custom_fuzz_send");
+ if (!mutator->afl_custom_fuzz_send) {
+
+ ACTF("optional symbol 'afl_custom_fuzz_send' not found.");
+
+ } else {
+
+ OKF("Found 'afl_custom_fuzz_send'.");
+
}
/* "afl_custom_queue_new_entry", optional */
@@ -320,13 +403,21 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
ACTF("optional symbol 'afl_custom_queue_new_entry' not found");
+ } else {
+
+ OKF("Found 'afl_custom_queue_new_entry'.");
+
}
/* "afl_custom_describe", optional */
mutator->afl_custom_describe = dlsym(dh, "afl_custom_describe");
if (!mutator->afl_custom_describe) {
- ACTF("Symbol 'afl_custom_describe' not found.");
+ ACTF("optional symbol 'afl_custom_describe' not found.");
+
+ } else {
+
+ OKF("Found 'afl_custom_describe'.");
}
diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c
index ed9e7a81..ee562f96 100644
--- a/src/afl-fuzz-one.c
+++ b/src/afl-fuzz-one.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -446,9 +446,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
ACTF(
"Fuzzing test case #%u (%u total, %llu crashes saved, "
- "perf_score=%0.0f, exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
+ "perf_score=%0.0f, weight=%0.0f, favorite=%u, was_fuzzed=%u, "
+ "exec_us=%llu, hits=%u, map=%u, ascii=%u)...",
afl->current_entry, afl->queued_items, afl->saved_crashes,
- afl->queue_cur->perf_score, afl->queue_cur->exec_us,
+ afl->queue_cur->perf_score, afl->queue_cur->weight,
+ afl->queue_cur->favored, afl->queue_cur->was_fuzzed,
+ afl->queue_cur->exec_us,
likely(afl->n_fuzz) ? afl->n_fuzz[afl->queue_cur->n_fuzz_entry] : 0,
afl->queue_cur->bitmap_size, afl->queue_cur->is_ascii);
fflush(stdout);
@@ -561,11 +564,11 @@ u8 fuzz_one_original(afl_state_t *afl) {
} else {
- if (afl->cmplog_lvl == 3 ||
- (afl->cmplog_lvl == 2 && afl->queue_cur->tc_ref) ||
- afl->queue_cur->favored ||
- !(afl->fsrv.total_execs % afl->queued_items) ||
- get_cur_time() - afl->last_find_time > 300000) { // 300 seconds
+ if (afl->queue_cur->favored || afl->cmplog_lvl == 3 ||
+ (afl->cmplog_lvl == 2 &&
+ (afl->queue_cur->tc_ref ||
+ afl->fsrv.total_execs % afl->queued_items <= 10)) ||
+ get_cur_time() - afl->last_find_time > 250000) { // 250 seconds
if (input_to_state_stage(afl, in_buf, out_buf, len)) {
@@ -584,7 +587,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
if it has gone through deterministic testing in earlier, resumed runs
(passed_det). */
- if (likely(afl->queue_cur->passed_det) || likely(afl->skip_deterministic) ||
+ if (likely(afl->skip_deterministic) || likely(afl->queue_cur->passed_det) ||
likely(perf_score <
(afl->queue_cur->depth * 30 <= afl->havoc_max_mult * 100
? afl->queue_cur->depth * 30
@@ -743,6 +746,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP1] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Two walking bits. */
@@ -775,6 +781,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP2] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Four walking bits. */
@@ -811,6 +820,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP4] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Effector map setup. These macros calculate:
@@ -919,6 +931,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP8] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Two walking bytes. */
@@ -962,6 +977,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP16] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
if (len < 4) { goto skip_bitflip; }
@@ -1005,6 +1023,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP32] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_bitflip:
@@ -1097,6 +1118,9 @@ skip_bitflip:
afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ARITH8] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* 16-bit arithmetics, both endians. */
@@ -1227,6 +1251,9 @@ skip_bitflip:
afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ARITH16] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* 32-bit arithmetics, both endians. */
@@ -1356,6 +1383,9 @@ skip_bitflip:
afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ARITH32] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_arith:
@@ -1422,6 +1452,9 @@ skip_arith:
afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Setting 16-bit integers, both endians. */
@@ -1510,6 +1543,9 @@ skip_arith:
afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
if (len < 4) { goto skip_interest; }
@@ -1599,6 +1635,9 @@ skip_arith:
afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_interest:
@@ -1672,6 +1711,9 @@ skip_interest:
afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Insertion of user-supplied extras. */
@@ -1728,6 +1770,9 @@ skip_interest:
afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_user_extras:
@@ -1786,6 +1831,9 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Insertion of auto extras. */
@@ -1842,6 +1890,9 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_extras:
@@ -1860,9 +1911,10 @@ custom_mutator_stage:
afl->stage_name = "custom mutator";
afl->stage_short = "custom";
- afl->stage_max = HAVOC_CYCLES * perf_score / afl->havoc_div / 100;
afl->stage_val_type = STAGE_VAL_NONE;
bool has_custom_fuzz = false;
+ u32 shift = unlikely(afl->custom_only) ? 7 : 8;
+ afl->stage_max = (HAVOC_CYCLES * perf_score / afl->havoc_div) >> shift;
if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
@@ -1879,6 +1931,7 @@ custom_mutator_stage:
if (el->afl_custom_fuzz) {
afl->current_custom_fuzz = el;
+ afl->stage_name = el->name_short;
if (el->afl_custom_fuzz_count) {
@@ -1905,7 +1958,8 @@ custom_mutator_stage:
u32 target_len = 0;
/* check if splicing makes sense yet (enough entries) */
- if (likely(afl->ready_for_splicing_count > 1)) {
+ if (likely(!afl->custom_splice_optout &&
+ afl->ready_for_splicing_count > 1)) {
/* Pick a random other queue entry for passing to external API
that has the necessary length */
@@ -1935,7 +1989,8 @@ custom_mutator_stage:
if (unlikely(!mutated_buf)) {
- FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size);
+ // FATAL("Error in custom_fuzz. Size returned: %zu", mutated_size);
+ break;
}
@@ -1987,7 +2042,10 @@ custom_mutator_stage:
new_hit_cnt = afl->queued_items + afl->saved_crashes;
afl->stage_finds[STAGE_CUSTOM_MUTATOR] += new_hit_cnt - orig_hit_cnt;
- afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_max;
+ afl->stage_cycles[STAGE_CUSTOM_MUTATOR] += afl->stage_cur;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
if (likely(afl->custom_only)) {
@@ -2012,8 +2070,9 @@ havoc_stage:
afl->stage_name = "havoc";
afl->stage_short = "havoc";
- afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
- perf_score / afl->havoc_div / 100;
+ afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
+ perf_score / afl->havoc_div) >>
+ 8;
} else {
@@ -2022,11 +2081,11 @@ havoc_stage:
snprintf(afl->stage_name_buf, STAGE_BUF_SIZE, "splice %u", splice_cycle);
afl->stage_name = afl->stage_name_buf;
afl->stage_short = "splice";
- afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
+ afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8;
}
- if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
+ if (unlikely(afl->stage_max < HAVOC_MIN)) { afl->stage_max = HAVOC_MIN; }
temp_len = len;
@@ -2925,11 +2984,17 @@ havoc_stage:
afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_HAVOC] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
} else {
afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_SPLICE] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
}
@@ -3411,6 +3476,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_finds[STAGE_FLIP1] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP1] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Two walking bits. */
@@ -3442,6 +3510,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_finds[STAGE_FLIP2] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP2] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Four walking bits. */
@@ -3477,6 +3548,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_finds[STAGE_FLIP4] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP4] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Effector map setup. These macros calculate:
@@ -3584,6 +3658,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_finds[STAGE_FLIP8] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP8] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Two walking bytes. */
@@ -3626,6 +3703,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_finds[STAGE_FLIP16] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP16] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
if (len < 4) { goto skip_bitflip; }
@@ -3668,6 +3748,9 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
afl->stage_finds[STAGE_FLIP32] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_FLIP32] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_bitflip:
@@ -3758,6 +3841,9 @@ skip_bitflip:
afl->stage_finds[STAGE_ARITH8] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ARITH8] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* 16-bit arithmetics, both endians. */
@@ -3884,6 +3970,9 @@ skip_bitflip:
afl->stage_finds[STAGE_ARITH16] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ARITH16] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* 32-bit arithmetics, both endians. */
@@ -4009,6 +4098,9 @@ skip_bitflip:
afl->stage_finds[STAGE_ARITH32] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_ARITH32] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_arith:
@@ -4074,6 +4166,9 @@ skip_arith:
afl->stage_finds[STAGE_INTEREST8] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_INTEREST8] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Setting 16-bit integers, both endians. */
@@ -4160,6 +4255,9 @@ skip_arith:
afl->stage_finds[STAGE_INTEREST16] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_INTEREST16] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
if (len < 4) { goto skip_interest; }
@@ -4247,6 +4345,9 @@ skip_arith:
afl->stage_finds[STAGE_INTEREST32] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_INTEREST32] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_interest:
@@ -4320,6 +4421,9 @@ skip_interest:
afl->stage_finds[STAGE_EXTRAS_UO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_UO] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Insertion of user-supplied extras. */
@@ -4376,6 +4480,9 @@ skip_interest:
afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_UI] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_user_extras:
@@ -4435,6 +4542,9 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AO] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AO] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
/* Insertion of auto extras. */
@@ -4491,6 +4601,9 @@ skip_user_extras:
afl->stage_finds[STAGE_EXTRAS_AI] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_EXTRAS_AI] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
skip_extras:
@@ -4516,8 +4629,9 @@ pacemaker_fuzzing:
afl->stage_name = MOpt_globals.havoc_stagename;
afl->stage_short = MOpt_globals.havoc_stagenameshort;
- afl->stage_max = (doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
- perf_score / afl->havoc_div / 100;
+ afl->stage_max = ((doing_det ? HAVOC_CYCLES_INIT : HAVOC_CYCLES) *
+ perf_score / afl->havoc_div) >>
+ 7;
} else {
@@ -4527,7 +4641,7 @@ pacemaker_fuzzing:
MOpt_globals.splice_stageformat, splice_cycle);
afl->stage_name = afl->stage_name_buf;
afl->stage_short = MOpt_globals.splice_stagenameshort;
- afl->stage_max = SPLICE_HAVOC * perf_score / afl->havoc_div / 100;
+ afl->stage_max = (SPLICE_HAVOC * perf_score / afl->havoc_div) >> 8;
}
@@ -5316,11 +5430,17 @@ pacemaker_fuzzing:
afl->stage_finds[STAGE_HAVOC] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_HAVOC] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
} else {
afl->stage_finds[STAGE_SPLICE] += new_hit_cnt - orig_hit_cnt;
afl->stage_cycles[STAGE_SPLICE] += afl->stage_max;
+#ifdef INTROSPECTION
+ afl->queue_cur->stats_mutated += afl->stage_max;
+#endif
}
@@ -5572,6 +5692,7 @@ pacemaker_fuzzing:
} /* block */
+ ++afl->queue_cur->fuzz_level;
return ret_val;
}
@@ -5681,13 +5802,11 @@ void pso_updating(afl_state_t *afl) {
}
-/* larger change for MOpt implementation: the original fuzz_one was renamed
- to fuzz_one_original. All documentation references to fuzz_one therefore
- mean fuzz_one_original */
-
+/* The entry point for the mutator, choosing the default mutator, and/or MOpt
+ depending on the configuration. */
u8 fuzz_one(afl_state_t *afl) {
- int key_val_lv_1 = 0, key_val_lv_2 = 0;
+ int key_val_lv_1 = -1, key_val_lv_2 = -1;
#ifdef _AFL_DOCUMENT_MUTATIONS
@@ -5707,7 +5826,12 @@ u8 fuzz_one(afl_state_t *afl) {
#endif
- // if limit_time_sig == -1 then both are run after each other
+ /*
+ -L command line paramter => limit_time_sig value
+ limit_time_sig == 0 then run the default mutator
+ limit_time_sig > 0 then run MOpt
+ limit_time_sig < 0 both are run
+ */
if (afl->limit_time_sig <= 0) { key_val_lv_1 = fuzz_one_original(afl); }
@@ -5729,6 +5853,9 @@ u8 fuzz_one(afl_state_t *afl) {
}
+ if (unlikely(key_val_lv_1 == -1)) { key_val_lv_1 = 0; }
+ if (likely(key_val_lv_2 == -1)) { key_val_lv_2 = 0; }
+
return (key_val_lv_1 | key_val_lv_2);
}
diff --git a/src/afl-fuzz-python.c b/src/afl-fuzz-python.c
index a43d80bb..7dad0770 100644
--- a/src/afl-fuzz-python.c
+++ b/src/afl-fuzz-python.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -219,11 +219,14 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (py_module != NULL) {
- u8 py_notrim = 0, py_idx;
- /* init, required */
+ u8 py_notrim = 0;
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
- if (!py_functions[PY_FUNC_INIT])
- FATAL("init function not found in python module");
+ if (!py_functions[PY_FUNC_INIT]) {
+
+ WARNF("init function not found in python module");
+
+ }
+
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
@@ -231,8 +234,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject_GetAttrString(py_module, "describe");
py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count");
- if (!py_functions[PY_FUNC_FUZZ])
- WARNF("fuzz function not found in python module");
py_functions[PY_FUNC_POST_PROCESS] =
PyObject_GetAttrString(py_module, "post_process");
py_functions[PY_FUNC_INIT_TRIM] =
@@ -246,6 +247,11 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
PyObject_GetAttrString(py_module, "havoc_mutation_probability");
py_functions[PY_FUNC_QUEUE_GET] =
PyObject_GetAttrString(py_module, "queue_get");
+ py_functions[PY_FUNC_FUZZ_SEND] =
+ PyObject_GetAttrString(py_module, "fuzz_send");
+ py_functions[PY_FUNC_SPLICE_OPTOUT] =
+ PyObject_GetAttrString(py_module, "splice_optout");
+ if (py_functions[PY_FUNC_SPLICE_OPTOUT]) { afl->custom_splice_optout = 1; }
py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
PyObject_GetAttrString(py_module, "queue_new_entry");
py_functions[PY_FUNC_INTROSPECTION] =
@@ -254,36 +260,6 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (!py_functions[PY_FUNC_DEINIT])
WARNF("deinit function not found in python module");
- for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
-
- if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
-
- if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
-
- // Implementing the trim API is optional for now
- if (PyErr_Occurred()) { PyErr_Print(); }
- py_notrim = 1;
-
- } else if (py_idx >= PY_OPTIONAL) {
-
- // Only _init and _deinit are not optional currently
-
- if (PyErr_Occurred()) { PyErr_Print(); }
-
- } else {
-
- fprintf(stderr,
- "Cannot find/call function with index %d in external "
- "Python module.\n",
- py_idx);
- return NULL;
-
- }
-
- }
-
- }
-
if (py_notrim) {
py_functions[PY_FUNC_INIT_TRIM] = NULL;
@@ -336,6 +312,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
(void)afl;
+ if (py_mutator->py_functions[PY_FUNC_INIT] == NULL) { return; }
+
PyObject *py_args, *py_value;
/* Provide the init function a seed for the Python RNG */
@@ -392,16 +370,34 @@ void deinit_py(void *py_mutator) {
}
+void splice_optout_py(void *py_mutator) {
+
+ // this is never called
+ (void)(py_mutator);
+
+}
+
struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
char *module_name) {
struct custom_mutator *mutator;
mutator = ck_alloc(sizeof(struct custom_mutator));
-
mutator->name = module_name;
ACTF("Loading Python mutator library from '%s'...", module_name);
+ if (memchr(module_name, '/', strlen(module_name))) {
+
+ mutator->name_short = strdup(strrchr(module_name, '/') + 1);
+
+ } else {
+
+ mutator->name_short = strdup(module_name);
+
+ }
+
+ if (strlen(mutator->name_short) > 22) { mutator->name_short[21] = 0; }
+
py_mutator_t *py_mutator;
py_mutator = init_py_module(afl, module_name);
mutator->data = py_mutator;
@@ -466,6 +462,19 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
}
+ if (py_functions[PY_FUNC_FUZZ_SEND]) {
+
+ mutator->afl_custom_fuzz_send = fuzz_send_py;
+
+ }
+
+ if (py_functions[PY_FUNC_SPLICE_OPTOUT]) {
+
+ mutator->afl_custom_splice_optout = splice_optout_py;
+ afl->custom_splice_optout = 1;
+
+ }
+
if (py_functions[PY_FUNC_QUEUE_NEW_ENTRY]) {
mutator->afl_custom_queue_new_entry = queue_new_entry_py;
@@ -893,6 +902,29 @@ u8 queue_get_py(void *py_mutator, const u8 *filename) {
}
+void fuzz_send_py(void *py_mutator, const u8 *buf, size_t buf_size) {
+
+ PyObject *py_args, *py_value;
+
+ py_args = PyTuple_New(1);
+ py_value = PyByteArray_FromStringAndSize(buf, buf_size);
+ if (!py_value) {
+
+ Py_DECREF(py_args);
+ FATAL("Failed to convert arguments");
+
+ }
+
+ PyTuple_SetItem(py_args, 0, py_value);
+
+ py_value = PyObject_CallObject(
+ ((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ_SEND], py_args);
+ Py_DECREF(py_args);
+
+ if (py_value != NULL) { Py_DECREF(py_value); }
+
+}
+
u8 queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
const u8 *filename_orig_queue) {
diff --git a/src/afl-fuzz-queue.c b/src/afl-fuzz-queue.c
index d8dbdfbe..8ad7cd97 100644
--- a/src/afl-fuzz-queue.c
+++ b/src/afl-fuzz-queue.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at:
@@ -27,6 +27,22 @@
#include <ctype.h>
#include <math.h>
+#ifdef _STANDALONE_MODULE
+void minimize_bits(afl_state_t *afl, u8 *dst, u8 *src) {
+
+ return;
+
+}
+
+void run_afl_custom_queue_new_entry(afl_state_t *afl, struct queue_entry *q,
+ u8 *a, u8 *b) {
+
+ return;
+
+}
+
+#endif
+
/* select next queue entry based on alias algo - fast! */
inline u32 select_next_queue_entry(afl_state_t *afl) {
@@ -51,13 +67,15 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
- if (likely(hits)) { weight *= log10(hits) + 1; }
+ if (likely(hits)) { weight /= (log10(hits) + 1); }
}
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
weight *= (log(q->bitmap_size) / avg_bitmap_size);
weight *= (1 + (q->tc_ref / avg_top_size));
+
+ if (unlikely(weight < 0.1)) { weight = 0.1; }
if (unlikely(q->favored)) { weight *= 5; }
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
@@ -77,8 +95,8 @@ void create_alias_table(afl_state_t *afl) {
afl->alias_probability = (double *)afl_realloc(
(void **)&afl->alias_probability, n * sizeof(double));
double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
- int *S = (u32 *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
- int *L = (u32 *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
+ int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
+ int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
@@ -131,6 +149,20 @@ void create_alias_table(afl_state_t *afl) {
}
+ if (unlikely(afl->schedule == MMOPT) && afl->queued_discovered) {
+
+ u32 cnt = afl->queued_discovered >= 5 ? 5 : afl->queued_discovered;
+
+ for (i = n - cnt; i < n; i++) {
+
+ struct queue_entry *q = afl->queue_buf[i];
+
+ if (likely(!q->disabled)) { q->weight *= 2.0; }
+
+ }
+
+ }
+
for (i = 0; i < n; i++) {
// weight is always 0 for disabled entries
@@ -246,11 +278,11 @@ void create_alias_table(afl_state_t *afl) {
void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
- u8 fn[PATH_MAX];
- s32 fd;
+ char fn[PATH_MAX];
+ s32 fd;
snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir,
- strrchr(q->fname, '/') + 1);
+ strrchr((char *)q->fname, '/') + 1);
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
@@ -265,10 +297,10 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
- u8 fn[PATH_MAX];
- u8 ldest[PATH_MAX];
+ char fn[PATH_MAX];
+ char ldest[PATH_MAX];
- u8 *fn_name = strrchr(q->fname, '/') + 1;
+ char *fn_name = strrchr((char *)q->fname, '/') + 1;
sprintf(ldest, "../../%s", fn_name);
sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name);
@@ -292,12 +324,12 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
if (likely(state == q->fs_redundant)) { return; }
- u8 fn[PATH_MAX];
+ char fn[PATH_MAX];
q->fs_redundant = state;
sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir,
- strrchr(q->fname, '/') + 1);
+ strrchr((char *)q->fname, '/') + 1);
if (state) {
@@ -408,7 +440,7 @@ u8 check_if_text_buf(u8 *buf, u32 len) {
static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) {
- if (q->len < AFL_TXT_MIN_LEN) return 0;
+ if (q->len < AFL_TXT_MIN_LEN || q->len < AFL_TXT_MAX_LEN) return 0;
u8 *buf;
int fd;
@@ -416,8 +448,8 @@ static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) {
ssize_t comp;
if (len >= MAX_FILE) len = MAX_FILE - 1;
- if ((fd = open(q->fname, O_RDONLY)) < 0) return 0;
- buf = afl_realloc(AFL_BUF_PARAM(in_scratch), len + 1);
+ if ((fd = open((char *)q->fname, O_RDONLY)) < 0) return 0;
+ buf = (u8 *)afl_realloc(AFL_BUF_PARAM(in_scratch), len + 1);
comp = read(fd, buf, len);
close(fd);
if (comp != (ssize_t)len) return 0;
@@ -519,7 +551,8 @@ static u8 check_if_text(afl_state_t *afl, struct queue_entry *q) {
void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
- struct queue_entry *q = ck_alloc(sizeof(struct queue_entry));
+ struct queue_entry *q =
+ (struct queue_entry *)ck_alloc(sizeof(struct queue_entry));
q->fname = fname;
q->len = len;
@@ -553,13 +586,30 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
afl->cycles_wo_finds = 0;
- struct queue_entry **queue_buf = afl_realloc(
+ struct queue_entry **queue_buf = (struct queue_entry **)afl_realloc(
AFL_BUF_PARAM(queue), afl->queued_items * sizeof(struct queue_entry *));
if (unlikely(!queue_buf)) { PFATAL("alloc"); }
queue_buf[afl->queued_items - 1] = q;
q->id = afl->queued_items - 1;
- afl->last_find_time = get_cur_time();
+ u64 cur_time = get_cur_time();
+
+ if (likely(afl->start_time) &&
+ unlikely(afl->longest_find_time < cur_time - afl->last_find_time)) {
+
+ if (unlikely(!afl->last_find_time)) {
+
+ afl->longest_find_time = cur_time - afl->start_time;
+
+ } else {
+
+ afl->longest_find_time = cur_time - afl->last_find_time;
+
+ }
+
+ }
+
+ afl->last_find_time = cur_time;
if (afl->custom_mutators_count) {
@@ -573,7 +623,11 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
}
/* only redqueen currently uses is_ascii */
- if (afl->shm.cmplog_mode) q->is_ascii = check_if_text(afl, q);
+ if (unlikely(afl->shm.cmplog_mode && !q->is_ascii)) {
+
+ q->is_ascii = check_if_text(afl, q);
+
+ }
}
@@ -703,7 +757,7 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
if (!q->trace_mini) {
u32 len = (afl->fsrv.map_size >> 3);
- q->trace_mini = ck_alloc(len);
+ q->trace_mini = (u8 *)ck_alloc(len);
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
}
@@ -1006,10 +1060,16 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
break;
case LIN:
+ // Don't modify perf_score for unfuzzed seeds
+ if (!q->fuzz_level) break;
+
factor = q->fuzz_level / (afl->n_fuzz[q->n_fuzz_entry] + 1);
break;
case QUAD:
+ // Don't modify perf_score for unfuzzed seeds
+ if (!q->fuzz_level) break;
+
factor =
q->fuzz_level * q->fuzz_level / (afl->n_fuzz[q->n_fuzz_entry] + 1);
break;
@@ -1089,19 +1149,19 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
if (len != old_len) {
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
- q->testcase_buf = realloc(q->testcase_buf, len);
+ q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
if (unlikely(!q->testcase_buf)) {
- PFATAL("Unable to malloc '%s' with len %u", q->fname, len);
+ PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
}
- int fd = open(q->fname, O_RDONLY);
+ int fd = open((char *)q->fname, O_RDONLY);
- if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); }
+ if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
ck_read(fd, q->testcase_buf, len, q->fname);
close(fd);
@@ -1121,7 +1181,7 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
if (likely(len != old_len)) {
- u8 *ptr = realloc(q->testcase_buf, len);
+ u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
if (likely(ptr)) {
@@ -1153,23 +1213,23 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
if (unlikely(q == afl->queue_cur)) {
- buf = afl_realloc((void **)&afl->testcase_buf, len);
+ buf = (u8 *)afl_realloc((void **)&afl->testcase_buf, len);
} else {
- buf = afl_realloc((void **)&afl->splicecase_buf, len);
+ buf = (u8 *)afl_realloc((void **)&afl->splicecase_buf, len);
}
if (unlikely(!buf)) {
- PFATAL("Unable to malloc '%s' with len %u", q->fname, len);
+ PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
- int fd = open(q->fname, O_RDONLY);
+ int fd = open((char *)q->fname, O_RDONLY);
- if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); }
+ if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
ck_read(fd, buf, len, q->fname);
close(fd);
@@ -1213,7 +1273,7 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
do_once = 1;
// release unneeded memory
- afl->q_testcase_cache = ck_realloc(
+ afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
afl->q_testcase_cache,
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
@@ -1260,15 +1320,15 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
/* Map the test case into memory. */
- int fd = open(q->fname, O_RDONLY);
+ int fd = open((char *)q->fname, O_RDONLY);
- if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", q->fname); }
+ if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
- q->testcase_buf = malloc(len);
+ q->testcase_buf = (u8 *)malloc(len);
if (unlikely(!q->testcase_buf)) {
- PFATAL("Unable to malloc '%s' with len %u", q->fname, len);
+ PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
@@ -1331,11 +1391,11 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q,
/* Map the test case into memory. */
- q->testcase_buf = malloc(len);
+ q->testcase_buf = (u8 *)malloc(len);
if (unlikely(!q->testcase_buf)) {
- PFATAL("Unable to malloc '%s' with len %u", q->fname, len);
+ PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
}
diff --git a/src/afl-fuzz-redqueen.c b/src/afl-fuzz-redqueen.c
index 337f124d..6e4a655b 100644
--- a/src/afl-fuzz-redqueen.c
+++ b/src/afl-fuzz-redqueen.c
@@ -11,7 +11,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -167,6 +167,25 @@ static u8 get_exec_checksum(afl_state_t *afl, u8 *buf, u32 len, u64 *cksum) {
}
+/* replace everything with different values */
+static void random_replace(afl_state_t *afl, u8 *buf, u32 len) {
+
+ for (u32 i = 0; i < len; i++) {
+
+ u8 c;
+
+ do {
+
+ c = rand_below(afl, 256);
+
+ } while (c == buf[i]);
+
+ buf[i] = c;
+
+ }
+
+}
+
/* replace everything with different values but stay in the same type */
static void type_replace(afl_state_t *afl, u8 *buf, u32 len) {
@@ -293,7 +312,15 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
memcpy(backup, buf, len);
memcpy(changed, buf, len);
- type_replace(afl, changed, len);
+ if (afl->cmplog_random_colorization) {
+
+ random_replace(afl, changed, len);
+
+ } else {
+
+ type_replace(afl, changed, len);
+
+ }
while ((rng = pop_biggest_range(&ranges)) != NULL &&
afl->stage_cur < afl->stage_max) {
@@ -1008,7 +1035,7 @@ static u8 cmp_extend_encoding(afl_state_t *afl, struct cmp_header *h,
} else {
- diff = 0;
+ o_diff = 0;
}
@@ -1597,6 +1624,8 @@ static void try_to_add_to_dictN(afl_state_t *afl, u128 v, u8 size) {
}
+ if (cons_0 > 1 || cons_ff > 1) { return; }
+
}
maybe_add_auto(afl, (u8 *)&v + off, size);
diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c
index 3c3d4817..2d53de93 100644
--- a/src/afl-fuzz-run.c
+++ b/src/afl-fuzz-run.c
@@ -10,7 +10,7 @@
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -76,6 +76,8 @@ fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv, u32 timeout) {
u32 __attribute__((hot))
write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
+ u8 sent = 0;
+
if (unlikely(afl->custom_mutators_count)) {
ssize_t new_size = len;
@@ -131,13 +133,46 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
}
- /* everything as planned. use the potentially new data. */
- afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size);
+ if (new_mem != *mem && new_mem != NULL && new_size > 0
+ && !afl->afl_env.afl_post_process_keep_original) {
+
+ u8 *new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
+ if (unlikely(!new_buf)) { PFATAL("alloc"); }
+ *mem = new_buf;
+ memcpy(*mem, new_mem, new_size);
+ afl_swap_bufs(AFL_BUF_PARAM(out), AFL_BUF_PARAM(out_scratch));
+
+ }
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz_send) {
+
+ el->afl_custom_fuzz_send(el->data, *mem, new_size);
+ sent = 1;
+
+ }
+
+ });
+
+ }
+
+ if (likely(!sent)) {
+
+ /* everything as planned. use the potentially new data. */
+
+ if (likely(!afl->afl_env.afl_post_process_keep_original)) {
- if (likely(!afl->afl_env.afl_post_process_keep_original)) {
+ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, new_size);
- if (new_mem != *mem) { *mem = new_mem; }
- len = new_size;
+ } else {
+
+ afl_fsrv_write_to_testcase(&afl->fsrv, new_mem, new_size);
+
+ }
+ len = new_size;
}
@@ -153,8 +188,27 @@ write_to_testcase(afl_state_t *afl, void **mem, u32 len, u32 fix) {
}
- /* boring uncustom. */
- afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len);
+ if (unlikely(afl->custom_mutators_count)) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz_send) {
+
+ el->afl_custom_fuzz_send(el->data, *mem, len);
+ sent = 1;
+
+ }
+
+ });
+
+ }
+
+ if (likely(!sent)) {
+
+ /* boring uncustom. */
+ afl_fsrv_write_to_testcase(&afl->fsrv, *mem, len);
+
+ }
}
@@ -487,7 +541,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
}
- if (unlikely(!var_detected)) {
+ if (unlikely(!var_detected && !afl->afl_env.afl_no_warn_instability)) {
// note: from_queue seems to only be set during initialization
if (afl->afl_env.afl_no_ui || from_queue) {
diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c
index 10bc2768..cccebeb9 100644
--- a/src/afl-fuzz-state.c
+++ b/src/afl-fuzz-state.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -23,6 +23,8 @@
*/
+#include <signal.h>
+#include <limits.h>
#include "afl-fuzz.h"
#include "envs.h"
@@ -99,6 +101,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
afl->hang_tmout = EXEC_TIMEOUT;
afl->exit_on_time = 0;
afl->stats_update_freq = 1;
+ afl->stats_file_update_freq_msecs = STATS_UPDATE_SEC * 1000;
afl->stats_avg_exec = 0;
afl->skip_deterministic = 1;
afl->sync_time = SYNC_TIME;
@@ -203,6 +206,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_no_affinity =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_NO_WARN_INSTABILITY",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_no_warn_instability =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_TRY_AFFINITY",
afl_environment_variable_len)) {
@@ -291,6 +301,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_ignore_problems =
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+ } else if (!strncmp(env, "AFL_IGNORE_TIMEOUTS",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_ignore_timeouts =
+ get_afl_env(afl_environment_variables[i]) ? 1 : 0;
+
} else if (!strncmp(env, "AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES",
afl_environment_variable_len)) {
@@ -494,7 +511,14 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl_environment_variable_len)) {
- afl->afl_env.afl_kill_signal =
+ afl->afl_env.afl_child_kill_signal =
+ (u8 *)get_afl_env(afl_environment_variables[i]);
+
+ } else if (!strncmp(env, "AFL_FORK_SERVER_KILL_SIGNAL",
+
+ afl_environment_variable_len)) {
+
+ afl->afl_env.afl_fsrv_kill_signal =
(u8 *)get_afl_env(afl_environment_variables[i]);
} else if (!strncmp(env, "AFL_TARGET_ENV",
@@ -550,6 +574,26 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
+ } else if (!strncmp(env, "AFL_FUZZER_STATS_UPDATE_INTERVAL",
+
+ afl_environment_variable_len)) {
+
+ u64 stats_update_freq_sec =
+ strtoull(get_afl_env(afl_environment_variables[i]), NULL, 0);
+ if (stats_update_freq_sec >= UINT_MAX ||
+ 0 == stats_update_freq_sec) {
+
+ WARNF(
+ "Incorrect value given to AFL_FUZZER_STATS_UPDATE_INTERVAL, "
+ "using default of %d seconds\n",
+ STATS_UPDATE_SEC);
+
+ } else {
+
+ afl->stats_file_update_freq_msecs = stats_update_freq_sec * 1000;
+
+ }
+
}
} else {
@@ -611,10 +655,14 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
}
- if (afl->afl_env.afl_pizza_mode) {
+ if (afl->afl_env.afl_pizza_mode > 0) {
afl->pizza_is_served = 1;
+ } else if (afl->afl_env.afl_pizza_mode < 0) {
+
+ OKF("Pizza easter egg mode is now disabled.");
+
}
if (issue_detected) { sleep(2); }
@@ -665,8 +713,17 @@ void afl_states_stop(void) {
LIST_FOREACH(&afl_states, afl_state_t, {
- if (el->fsrv.child_pid > 0) kill(el->fsrv.child_pid, el->fsrv.kill_signal);
- if (el->fsrv.fsrv_pid > 0) kill(el->fsrv.fsrv_pid, el->fsrv.kill_signal);
+ /* NOTE: We need to make sure that the parent (the forkserver) reap the
+ * child (see below). */
+ if (el->fsrv.child_pid > 0)
+ kill(el->fsrv.child_pid, el->fsrv.child_kill_signal);
+ if (el->fsrv.fsrv_pid > 0) {
+
+ kill(el->fsrv.fsrv_pid, el->fsrv.fsrv_kill_signal);
+ /* Make sure the forkserver does not end up as zombie. */
+ waitpid(el->fsrv.fsrv_pid, NULL, 0);
+
+ }
});
diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c
index 51e292d8..07157bf7 100644
--- a/src/afl-fuzz-stats.c
+++ b/src/afl-fuzz-stats.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -62,7 +62,7 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
if (memchr(argv[i], '\'', strlen(argv[i]))) {
#else
- if (index(argv[i], '\'')) {
+ if (strchr(argv[i], '\'')) {
#endif
@@ -251,6 +251,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"fuzzer_pid : %u\n"
"cycles_done : %llu\n"
"cycles_wo_finds : %llu\n"
+ "time_wo_finds : %llu\n"
"execs_done : %llu\n"
"execs_per_sec : %0.02f\n"
"execs_ps_last_min : %0.02f\n"
@@ -291,6 +292,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
(afl->prev_run_time + cur_time - afl->start_time) / 1000, (u32)getpid(),
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
+ afl->longest_find_time > cur_time - afl->last_find_time
+ ? afl->longest_find_time / 1000
+ : ((afl->start_time == 0 || afl->last_find_time == 0)
+ ? 0
+ : (cur_time - afl->last_find_time) / 1000),
afl->fsrv.total_execs,
afl->fsrv.total_execs /
((double)(afl->prev_run_time + get_cur_time() - afl->start_time) /
@@ -365,6 +371,39 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
}
+#ifdef INTROSPECTION
+void write_queue_stats(afl_state_t *afl) {
+
+ FILE *f;
+ u8 *fn = alloc_printf("%s/queue_data", afl->out_dir);
+ if ((f = fopen(fn, "w")) != NULL) {
+
+ u32 id;
+ fprintf(f,
+ "# filename, length, exec_us, selected, skipped, mutations, finds, "
+ "crashes, timeouts, bitmap_size, perf_score, weight, colorized, "
+ "favored, disabled\n");
+ for (id = 0; id < afl->queued_items; ++id) {
+
+ struct queue_entry *q = afl->queue_buf[id];
+ fprintf(f, "\"%s\",%u,%llu,%u,%u,%llu,%u,%u,%u,%u,%.3f,%.3f,%u,%u,%u\n",
+ q->fname, q->len, q->exec_us, q->stats_selected, q->stats_skipped,
+ q->stats_mutated, q->stats_finds, q->stats_crashes,
+ q->stats_tmouts, q->bitmap_size, q->perf_score, q->weight,
+ q->colorized, q->favored, q->disabled);
+
+ }
+
+ fclose(f);
+
+ }
+
+ ck_free(fn);
+
+}
+
+#endif
+
/* Update the plot file if there is a reason to. */
void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
@@ -578,9 +617,10 @@ void show_stats_normal(afl_state_t *afl) {
/* Roughly every minute, update fuzzer stats and save auto tokens. */
- if (unlikely(!afl->non_instrumented_mode &&
- (afl->force_ui_update ||
- cur_ms - afl->stats_last_stats_ms > STATS_UPDATE_SEC * 1000))) {
+ if (unlikely(
+ !afl->non_instrumented_mode &&
+ (afl->force_ui_update || cur_ms - afl->stats_last_stats_ms >
+ afl->stats_file_update_freq_msecs))) {
afl->stats_last_stats_ms = cur_ms;
write_stats_file(afl, t_bytes, t_byte_ratio, stab_ratio,
@@ -613,6 +653,18 @@ void show_stats_normal(afl_state_t *afl) {
}
+ /* Every now and then, write queue data. */
+
+ if (unlikely(afl->force_ui_update ||
+ cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) {
+
+ afl->stats_last_queue_ms = cur_ms;
+#ifdef INTROSPECTION
+ write_queue_stats(afl);
+#endif
+
+ }
+
/* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
@@ -624,9 +676,14 @@ void show_stats_normal(afl_state_t *afl) {
/* AFL_EXIT_ON_TIME. */
- if (unlikely(afl->last_find_time && !afl->non_instrumented_mode &&
- afl->afl_env.afl_exit_on_time &&
- (cur_ms - afl->last_find_time) > afl->exit_on_time)) {
+ /* If no coverage was found yet, check whether run time is greater than
+ * exit_on_time. */
+
+ if (unlikely(!afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time &&
+ ((afl->last_find_time &&
+ (cur_ms - afl->last_find_time) > afl->exit_on_time) ||
+ (!afl->last_find_time &&
+ (cur_ms - afl->start_time) > afl->exit_on_time)))) {
afl->stop_soon = 2;
@@ -696,20 +753,20 @@ void show_stats_normal(afl_state_t *afl) {
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN "peruvian were-rabbit"
+ : cYEL "american fuzzy lop",
+ si, afl->use_banner, afl->power_name);
} else {
#endif
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "peruvian were-rabbit"
- : cYEL "american fuzzy lop",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN "peruvian were-rabbit"
+ : cYEL "american fuzzy lop",
+ si, afl->use_banner, afl->power_name);
#ifdef __linux__
@@ -1399,6 +1456,18 @@ void show_stats_pizza(afl_state_t *afl) {
}
+ /* Every now and then, write queue data. */
+
+ if (unlikely(afl->force_ui_update ||
+ cur_ms - afl->stats_last_queue_ms > QUEUE_UPDATE_SEC * 1000)) {
+
+ afl->stats_last_queue_ms = cur_ms;
+#ifdef INTROSPECTION
+ write_queue_stats(afl);
+#endif
+
+ }
+
/* Honor AFL_EXIT_WHEN_DONE and AFL_BENCH_UNTIL_CRASH. */
if (unlikely(!afl->non_instrumented_mode && afl->cycles_wo_finds > 100 &&
@@ -1410,9 +1479,14 @@ void show_stats_pizza(afl_state_t *afl) {
/* AFL_EXIT_ON_TIME. */
- if (unlikely(afl->last_find_time && !afl->non_instrumented_mode &&
- afl->afl_env.afl_exit_on_time &&
- (cur_ms - afl->last_find_time) > afl->exit_on_time)) {
+ /* If no coverage was found yet, check whether run time is greater than
+ * exit_on_time. */
+
+ if (unlikely(!afl->non_instrumented_mode && afl->afl_env.afl_exit_on_time &&
+ ((afl->last_find_time &&
+ (cur_ms - afl->last_find_time) > afl->exit_on_time) ||
+ (!afl->last_find_time &&
+ (cur_ms - afl->start_time) > afl->exit_on_time)))) {
afl->stop_soon = 2;
@@ -1483,20 +1557,22 @@ void show_stats_pizza(afl_state_t *afl) {
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
- afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
- : cYEL "Mozzarbella Pizzeria management system",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s] - Nyx",
+ afl->crash_mode ? cPIN
+ "Mozzarbella Pizzeria table booking system"
+ : cYEL "Mozzarbella Pizzeria management system",
+ si, afl->use_banner, afl->power_name);
} else {
#endif
- sprintf(banner + banner_pad,
- "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
- afl->crash_mode ? cPIN "Mozzarbella Pizzeria table booking system"
- : cYEL "Mozzarbella Pizzeria management system",
- si, afl->use_banner, afl->power_name);
+ snprintf(banner + banner_pad, sizeof(banner) - banner_pad,
+ "%s " cLCY VERSION cLBL " {%s} " cLGN "(%s) " cPIN "[%s]",
+ afl->crash_mode ? cPIN
+ "Mozzarbella Pizzeria table booking system"
+ : cYEL "Mozzarbella Pizzeria management system",
+ si, afl->use_banner, afl->power_name);
#ifdef __linux__
@@ -1727,10 +1803,10 @@ void show_stats_pizza(afl_state_t *afl) {
/* Show a warning about slow execution. */
- if (afl->stats_avg_exec < 100) {
+ if (afl->stats_avg_exec < 20) {
sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
- afl->stats_avg_exec < 20 ? "zzzz..." : "Gennarino is at it again!");
+ "zzzz...");
SAYF(bV bSTOP " pizza making speed : " cLRD
"%-22s ",
@@ -2105,7 +2181,9 @@ void show_init_stats(afl_state_t *afl) {
? 50000
: 10000)) {
- WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
+ WARNF(cLRD
+ "The target binary is pretty slow! See "
+ "%s/fuzzing_in_depth.md#i-improve-the-speed",
doc_path);
}
@@ -2134,13 +2212,17 @@ void show_init_stats(afl_state_t *afl) {
if (max_len > 50 * 1024) {
- WARNF(cLRD "Some test cases are huge (%s) - see %s/perf_tips.md!",
+ WARNF(cLRD
+ "Some test cases are huge (%s) - see "
+ "%s/fuzzing_in_depth.md#i-improve-the-speed",
stringify_mem_size(IB(0), max_len), doc_path);
} else if (max_len > 10 * 1024) {
- WARNF("Some test cases are big (%s) - see %s/perf_tips.md.",
- stringify_mem_size(IB(0), max_len), doc_path);
+ WARNF(
+ "Some test cases are big (%s) - see "
+ "%s/fuzzing_in_depth.md#i-improve-the-speed",
+ stringify_mem_size(IB(0), max_len), doc_path);
}
diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c
index b83af257..6b65c810 100644
--- a/src/afl-fuzz.c
+++ b/src/afl-fuzz.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -25,6 +25,7 @@
#include "afl-fuzz.h"
#include "cmplog.h"
+#include "common.h"
#include <limits.h>
#include <stdlib.h>
#ifndef USEMMAP
@@ -164,16 +165,16 @@ static void usage(u8 *argv0, int more_help) {
" pacemaker mode (minutes of no new finds). 0 = "
"immediately,\n"
" -1 = immediately and together with normal mutation.\n"
- " See docs/README.MOpt.md\n"
" -c program - enable CmpLog by specifying a binary compiled for "
"it.\n"
" if using QEMU/FRIDA or the fuzzing target is "
"compiled\n"
" for CmpLog then just use -c 0.\n"
- " -l cmplog_opts - CmpLog configuration values (e.g. \"2AT\"):\n"
+ " -l cmplog_opts - CmpLog configuration values (e.g. \"2ATR\"):\n"
" 1=small files, 2=larger files (default), 3=all "
"files,\n"
- " A=arithmetic solving, T=transformational solving.\n\n"
+ " A=arithmetic solving, T=transformational solving,\n"
+ " R=random colorization bytes.\n\n"
"Fuzzing behavior settings:\n"
" -Z - sequential queue selection instead of weighted "
"random\n"
@@ -192,9 +193,9 @@ static void usage(u8 *argv0, int more_help) {
"executions.\n\n"
"Other stuff:\n"
- " -M/-S id - distributed mode (see docs/parallel_fuzzing.md)\n"
- " -M auto-sets -D, -Z (use -d to disable -D) and no "
- "trimming\n"
+ " -M/-S id - distributed mode (-M sets -Z and disables trimming)\n"
+ " see docs/fuzzing_in_depth.md#c-using-multiple-cores\n"
+ " for effective recommendations for parallel fuzzing.\n"
" -F path - sync to a foreign fuzzer queue directory (requires "
"-M, can\n"
" be specified up to %u times)\n"
@@ -208,7 +209,8 @@ static void usage(u8 *argv0, int more_help) {
" -b cpu_id - bind the fuzzing process to the specified CPU core "
"(0-...)\n"
" -e ext - file extension for the fuzz test input file (if "
- "needed)\n\n",
+ "needed)\n"
+ "\n",
argv0, EXEC_TIMEOUT, MEM_LIMIT, MAX_FILE, FOREIGN_SYNCS_MAX);
if (more_help > 1) {
@@ -248,19 +250,25 @@ static void usage(u8 *argv0, int more_help) {
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
- "AFL_EXIT_ON_TIME: exit when no new coverage finds are made within the specified time period\n"
- "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60 minutes and a cycle without finds)\n"
+ "AFL_EXIT_ON_TIME: exit when no new coverage is found within the specified time\n"
+ "AFL_EXPAND_HAVOC_NOW: immediately enable expand havoc mode (default: after 60\n"
+ " minutes and a cycle without finds)\n"
"AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
"AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
- "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
+ "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in ms)\n"
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
+ "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
+ "AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
"AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
- "AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected during a run\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
"AFL_INPUT_LEN_MIN/AFL_INPUT_LEN_MAX: like -g/-G set min/max fuzz length produced\n"
"AFL_PIZZA_MODE: 1 - enforce pizza mode, 0 - disable for April 1st\n"
- "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
+ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n"
+ " (default: SIGKILL)\n"
+ "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n"
+ " (default: SIGTERM). If unset and AFL_KILL_SIGNAL is\n"
+ " set, that value will be used.\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
@@ -305,7 +313,9 @@ static void usage(u8 *argv0, int more_help) {
"AFL_EARLY_FORKSERVER: force an early forkserver in an afl-clang-fast/\n"
" afl-clang-lto/afl-gcc-fast target\n"
"AFL_PERSISTENT: enforce persistent mode (if __AFL_LOOP is in a shared lib\n"
- "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so\n"
+ "AFL_DEFER_FORKSRV: enforced deferred forkserver (__AFL_INIT is in a .so)\n"
+ "AFL_FUZZER_STATS_UPDATE_INTERVAL: interval to update fuzzer_stats file in seconds, "
+ "(default: 60, minimum: 1)\n"
"\n"
);
@@ -427,76 +437,13 @@ static void fasan_check_afl_preload(char *afl_preload) {
}
- #ifdef __linux__
- #include <dlfcn.h>
-
-nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary) {
-
- void *handle;
- nyx_plugin_handler_t *plugin = calloc(1, sizeof(nyx_plugin_handler_t));
-
- ACTF("Trying to load libnyx.so plugin...");
- handle = dlopen((char *)libnyx_binary, RTLD_NOW);
- if (!handle) { goto fail; }
-
- plugin->nyx_new = dlsym(handle, "nyx_new");
- if (plugin->nyx_new == NULL) { goto fail; }
-
- plugin->nyx_new_parent = dlsym(handle, "nyx_new_parent");
- if (plugin->nyx_new_parent == NULL) { goto fail; }
-
- plugin->nyx_new_child = dlsym(handle, "nyx_new_child");
- if (plugin->nyx_new_child == NULL) { goto fail; }
-
- plugin->nyx_shutdown = dlsym(handle, "nyx_shutdown");
- if (plugin->nyx_shutdown == NULL) { goto fail; }
-
- plugin->nyx_option_set_reload_mode =
- dlsym(handle, "nyx_option_set_reload_mode");
- if (plugin->nyx_option_set_reload_mode == NULL) { goto fail; }
-
- plugin->nyx_option_set_timeout = dlsym(handle, "nyx_option_set_timeout");
- if (plugin->nyx_option_set_timeout == NULL) { goto fail; }
-
- plugin->nyx_option_apply = dlsym(handle, "nyx_option_apply");
- if (plugin->nyx_option_apply == NULL) { goto fail; }
-
- plugin->nyx_set_afl_input = dlsym(handle, "nyx_set_afl_input");
- if (plugin->nyx_set_afl_input == NULL) { goto fail; }
-
- plugin->nyx_exec = dlsym(handle, "nyx_exec");
- if (plugin->nyx_exec == NULL) { goto fail; }
-
- plugin->nyx_get_bitmap_buffer = dlsym(handle, "nyx_get_bitmap_buffer");
- if (plugin->nyx_get_bitmap_buffer == NULL) { goto fail; }
-
- plugin->nyx_get_bitmap_buffer_size =
- dlsym(handle, "nyx_get_bitmap_buffer_size");
- if (plugin->nyx_get_bitmap_buffer_size == NULL) { goto fail; }
-
- plugin->nyx_get_aux_string = dlsym(handle, "nyx_get_aux_string");
- if (plugin->nyx_get_aux_string == NULL) { goto fail; }
-
- OKF("libnyx plugin is ready!");
- return plugin;
-
-fail:
-
- FATAL("failed to load libnyx: %s\n", dlerror());
- free(plugin);
- return NULL;
-
-}
-
- #endif
-
/* Main entry point */
int main(int argc, char **argv_orig, char **envp) {
s32 opt, auto_sync = 0 /*, user_set_cache = 0*/;
u64 prev_queued = 0;
- u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0,
+ u32 sync_interval_cnt = 0, seek_to = 0, show_help = 0, default_output = 1,
map_size = get_map_size();
u8 *extras_dir[4];
u8 mem_limit_given = 0, exit_1 = 0, debug = 0,
@@ -797,6 +744,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->fsrv.out_file = ck_strdup(optarg);
afl->fsrv.use_stdin = 0;
+ default_output = 0;
break;
case 'x': /* dictionary */
@@ -1109,6 +1057,10 @@ int main(int argc, char **argv_orig, char **envp) {
case 'T':
afl->cmplog_enable_transform = 1;
break;
+ case 'r':
+ case 'R':
+ afl->cmplog_random_colorization = 1;
+ break;
default:
FATAL("Unknown option value '%c' in -l %s", *c, optarg);
@@ -1287,6 +1239,13 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->is_main_node == 1 && afl->schedule != FAST &&
+ afl->schedule != EXPLORE) {
+
+ FATAL("-M is compatible only with fast and explore -p power schedules");
+
+ }
+
if (optind == argc || !afl->in_dir || !afl->out_dir || show_help) {
usage(argv[0], show_help);
@@ -1323,8 +1282,7 @@ int main(int argc, char **argv_orig, char **envp) {
"Eißfeldt, Andrea Fioraldi and Dominik Maier");
OKF("afl++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus");
- OKF("NOTE: This is v3.x which changes defaults and behaviours - see "
- "README.md");
+ OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md");
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
@@ -1335,12 +1293,11 @@ int main(int argc, char **argv_orig, char **envp) {
}
#endif
- if (afl->sync_id && afl->is_main_node &&
- afl->afl_env.afl_custom_mutator_only) {
+ if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
- WARNF(
- "Using -M main node with the AFL_CUSTOM_MUTATOR_ONLY mutator options "
- "will result in no deterministic mutations being done!");
+ FATAL(
+ "Using -D determinstic fuzzing is incompatible with "
+ "AFL_CUSTOM_MUTATOR_ONLY!");
}
@@ -1360,8 +1317,15 @@ int main(int argc, char **argv_orig, char **envp) {
#endif
- afl->fsrv.kill_signal =
- parse_afl_kill_signal_env(afl->afl_env.afl_kill_signal, SIGKILL);
+ configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal,
+ afl->afl_env.afl_fsrv_kill_signal,
+ (afl->fsrv.qemu_mode || afl->unicorn_mode
+ #ifdef __linux__
+ || afl->fsrv.nyx_mode
+ #endif
+ )
+ ? SIGKILL
+ : SIGTERM);
setup_signal_handlers();
check_asan_opts(afl);
@@ -1563,6 +1527,29 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
+
+ if (afl->custom_only) {
+
+ FATAL("Custom mutators are incompatible with MOpt (-L)");
+
+ }
+
+ u32 custom_fuzz = 0;
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz) { custom_fuzz = 1; }
+
+ });
+
+ if (custom_fuzz) {
+
+ WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
+
+ }
+
+ }
+
if (afl->afl_env.afl_max_det_extras) {
s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@@ -1895,6 +1882,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (aa_loc && !afl->fsrv.out_file) {
afl->fsrv.use_stdin = 0;
+ default_output = 0;
if (afl->file_extension) {
@@ -2064,6 +2052,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode;
afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
+ afl->cmplog_fsrv.target_path = afl->fsrv.target_path;
afl->cmplog_fsrv.init_child_func = cmplog_exec_child;
if ((map_size <= DEFAULT_SHMEM_SIZE ||
@@ -2134,6 +2123,24 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ if (afl->fsrv.out_file && afl->fsrv.use_shmem_fuzz) {
+
+ unlink(afl->fsrv.out_file);
+ afl->fsrv.out_file = NULL;
+ afl->fsrv.use_stdin = 0;
+ close(afl->fsrv.out_fd);
+ afl->fsrv.out_fd = -1;
+
+ if (!afl->unicorn_mode && !afl->fsrv.use_stdin && !default_output) {
+
+ WARNF(
+ "You specified -f or @@ on the command line but the target harness "
+ "specified fuzz cases via shmem, switching to shmem!");
+
+ }
+
+ }
+
deunicode_extras(afl);
dedup_extras(afl);
if (afl->extras_cnt) { OKF("Loaded a total of %u extras.", afl->extras_cnt); }
@@ -2181,14 +2188,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (!afl->pending_not_fuzzed || !valid_seeds) {
- #ifdef __linux__
- if (afl->fsrv.nyx_mode) {
-
- afl->fsrv.nyx_handlers->nyx_shutdown(afl->fsrv.nyx_runner);
-
- }
-
- #endif
FATAL("We need at least one valid input seed that does not crash!");
}
@@ -2247,8 +2246,10 @@ int main(int argc, char **argv_orig, char **envp) {
// real start time, we reset, so this works correctly with -V
afl->start_time = get_cur_time();
- u32 runs_in_current_cycle = (u32)-1;
- u32 prev_queued_items = 0;
+ #ifdef INTROSPECTION
+ u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
+ #endif
+ u32 prev_queued_items = 0, runs_in_current_cycle = (u32)-1;
u8 skipped_fuzz;
#ifdef INTROSPECTION
@@ -2276,6 +2277,12 @@ int main(int argc, char **argv_orig, char **envp) {
(!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
afl->sync_id)) {
+ if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
+
+ OKF("Syncing queues from other fuzzer instances first ...");
+
+ }
+
sync_fuzzers(afl);
}
@@ -2419,10 +2426,22 @@ int main(int argc, char **argv_orig, char **envp) {
}
#ifdef INTROSPECTION
- fprintf(afl->introspection_file,
- "CYCLE cycle=%llu cycle_wo_finds=%llu expand_havoc=%u queue=%u\n",
- afl->queue_cycle, afl->cycles_wo_finds, afl->expand_havoc,
- afl->queued_items);
+ {
+
+ u64 cur_time = get_cur_time();
+ fprintf(afl->introspection_file,
+ "CYCLE cycle=%llu cycle_wo_finds=%llu time_wo_finds=%llu "
+ "expand_havoc=%u queue=%u\n",
+ afl->queue_cycle, afl->cycles_wo_finds,
+ afl->longest_find_time > cur_time - afl->last_find_time
+ ? afl->longest_find_time / 1000
+ : ((afl->start_time == 0 || afl->last_find_time == 0)
+ ? 0
+ : (cur_time - afl->last_find_time) / 1000),
+ afl->expand_havoc, afl->queued_items);
+
+ }
+
#endif
if (afl->cycle_schedules) {
@@ -2493,27 +2512,70 @@ int main(int argc, char **argv_orig, char **envp) {
}
- afl->current_entry = select_next_queue_entry(afl);
+ do {
+
+ afl->current_entry = select_next_queue_entry(afl);
+
+ } while (unlikely(afl->current_entry >= afl->queued_items));
+
afl->queue_cur = afl->queue_buf[afl->current_entry];
}
skipped_fuzz = fuzz_one(afl);
+ #ifdef INTROSPECTION
+ ++afl->queue_cur->stats_selected;
+
+ if (unlikely(skipped_fuzz)) {
+
+ ++afl->queue_cur->stats_skipped;
+
+ } else {
+
+ if (unlikely(afl->queued_items > prev_queued_items)) {
+
+ afl->queue_cur->stats_finds += afl->queued_items - prev_queued_items;
+ prev_queued_items = afl->queued_items;
+
+ }
+
+ if (unlikely(afl->saved_crashes > prev_saved_crashes)) {
+
+ afl->queue_cur->stats_crashes +=
+ afl->saved_crashes - prev_saved_crashes;
+ prev_saved_crashes = afl->saved_crashes;
+
+ }
+
+ if (unlikely(afl->saved_tmouts > prev_saved_tmouts)) {
+
+ afl->queue_cur->stats_tmouts += afl->saved_tmouts - prev_saved_tmouts;
+ prev_saved_tmouts = afl->saved_tmouts;
+
+ }
+
+ }
+
+ #endif
if (unlikely(!afl->stop_soon && exit_1)) { afl->stop_soon = 2; }
if (unlikely(afl->old_seed_selection)) {
while (++afl->current_entry < afl->queued_items &&
- afl->queue_buf[afl->current_entry]->disabled)
- ;
+ afl->queue_buf[afl->current_entry]->disabled) {};
if (unlikely(afl->current_entry >= afl->queued_items ||
afl->queue_buf[afl->current_entry] == NULL ||
- afl->queue_buf[afl->current_entry]->disabled))
+ afl->queue_buf[afl->current_entry]->disabled)) {
+
afl->queue_cur = NULL;
- else
+
+ } else {
+
afl->queue_cur = afl->queue_buf[afl->current_entry];
+ }
+
}
} while (skipped_fuzz && afl->queue_cur && !afl->stop_soon);
@@ -2558,6 +2620,7 @@ int main(int argc, char **argv_orig, char **envp) {
stop_fuzzing:
afl->force_ui_update = 1; // ensure the screen is reprinted
+ afl->stop_soon = 1; // ensure everything is written
show_stats(afl); // print the screen one last time
write_bitmap(afl);
save_auto(afl);
diff --git a/src/afl-gotcpu.c b/src/afl-gotcpu.c
index 539206ce..4f851099 100644
--- a/src/afl-gotcpu.c
+++ b/src/afl-gotcpu.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -19,7 +19,8 @@
This tool provides a fairly accurate measurement of CPU preemption rate.
It is meant to complement the quick-and-dirty load average widget shown
- in the afl-fuzz UI. See docs/parallel_fuzzing.md for more info.
+ in the afl-fuzz UI. See docs/fuzzing_in_depth.md#c-using-multiple-cores
+ for more info.
For some work loads, the tool may actually suggest running more instances
than you have CPU cores. This can happen if the tested program is spending
@@ -91,7 +92,7 @@ static u32 measure_preemption(u32 target_ms) {
volatile u32 v1, v2 = 0;
u64 st_t, en_t, st_c, en_c, real_delta, slice_delta;
- s32 loop_repeats = 0;
+ // s32 loop_repeats = 0;
st_t = get_cur_time_us();
st_c = get_cpu_usage_us();
@@ -112,7 +113,7 @@ repeat_loop:
if (en_t - st_t < target_ms * 1000) {
- loop_repeats++;
+ // loop_repeats++;
goto repeat_loop;
}
@@ -173,7 +174,12 @@ int main(int argc, char **argv) {
if (c == NULL) PFATAL("cpuset_create failed");
cpuset_set(i, c);
- #elif defined(__APPLE__)
+ #elif defined(__APPLE__) && defined(__x86_64__)
+ // the api is not workable on arm64, core's principle
+ // differs significantly hive of core per type vs individual ones.
+ // Possible TODO: For arm64 is to slightly change the meaning
+ // of gotcpu since it makes no sense on this platform
+ // but rather just displaying current policy ?
thread_affinity_policy_data_t c = {i};
thread_port_t native_thread = pthread_mach_thread_np(pthread_self());
if (thread_policy_set(native_thread, THREAD_AFFINITY_POLICY,
@@ -208,7 +214,13 @@ int main(int argc, char **argv) {
#if defined(__linux__)
if (sched_setaffinity(0, sizeof(c), &c)) {
- PFATAL("sched_setaffinity failed for cpu %d", i);
+ const char *error_code = "Unkown error code";
+ if (errno == EFAULT) error_code = "EFAULT";
+ if (errno == EINVAL) error_code = "EINVAL";
+ if (errno == EPERM) error_code = "EPERM";
+ if (errno == ESRCH) error_code = "ESRCH";
+
+ PFATAL("sched_setaffinity failed for cpu %d, error: %s", i, error_code);
}
diff --git a/src/afl-ld-lto.c b/src/afl-ld-lto.c
index 5797def8..5438bd9f 100644
--- a/src/afl-ld-lto.c
+++ b/src/afl-ld-lto.c
@@ -9,7 +9,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Dominik Maier <domenukk@gmail.com>
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/src/afl-sharedmem.c b/src/afl-sharedmem.c
index b48c6fb3..a2c81586 100644
--- a/src/afl-sharedmem.c
+++ b/src/afl-sharedmem.c
@@ -11,7 +11,7 @@
Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
diff --git a/src/afl-showmap.c b/src/afl-showmap.c
index 07f30326..b5a61de5 100644
--- a/src/afl-showmap.c
+++ b/src/afl-showmap.c
@@ -12,7 +12,7 @@
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -30,8 +30,10 @@
*/
#define AFL_MAIN
+#define AFL_SHOWMAP
#include "config.h"
+#include "afl-fuzz.h"
#include "types.h"
#include "debug.h"
#include "alloc-inl.h"
@@ -62,6 +64,8 @@
#include <sys/types.h>
#include <sys/resource.h>
+static afl_state_t *afl;
+
static char *stdin_file; /* stdin file */
static u8 *in_dir = NULL, /* input folder */
@@ -129,7 +133,7 @@ static void kill_child() {
timed_out = 1;
if (fsrv->child_pid > 0) {
- kill(fsrv->child_pid, fsrv->kill_signal);
+ kill(fsrv->child_pid, fsrv->child_kill_signal);
fsrv->child_pid = -1;
}
@@ -308,12 +312,73 @@ static u32 write_results_to_file(afl_forkserver_t *fsrv, u8 *outfile) {
}
+void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem, u32 len) {
+
+ static u8 buf[MAX_FILE];
+ u32 sent = 0;
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ ssize_t new_size = len;
+ u8 *new_mem = mem;
+ u8 *new_buf = NULL;
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_post_process) {
+
+ new_size =
+ el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
+
+ if (unlikely(!new_buf || new_size <= 0)) {
+
+ return;
+
+ } else {
+
+ new_mem = new_buf;
+ len = new_size;
+
+ }
+
+ }
+
+ });
+
+ if (new_mem != mem && new_mem != NULL) {
+
+ mem = buf;
+ memcpy(mem, new_mem, new_size);
+
+ }
+
+ if (unlikely(afl->custom_mutators_count)) {
+
+ LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
+
+ if (el->afl_custom_fuzz_send) {
+
+ el->afl_custom_fuzz_send(el->data, mem, len);
+ sent = 1;
+
+ }
+
+ });
+
+ }
+
+ }
+
+ if (likely(!sent)) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
+
+}
+
/* Execute target application. */
static void showmap_run_target_forkserver(afl_forkserver_t *fsrv, u8 *mem,
u32 len) {
- afl_fsrv_write_to_testcase(fsrv, mem, len);
+ pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
if (!quiet_mode) { SAYF("-- Program output begins --\n" cRST); }
@@ -434,6 +499,23 @@ static u32 read_file(u8 *in_file) {
}
+#ifdef __linux__
+/* Execute the target application with an empty input (in Nyx mode). */
+static void showmap_run_target_nyx_mode(afl_forkserver_t *fsrv) {
+
+ afl_fsrv_write_to_testcase(fsrv, NULL, 0);
+
+ if (afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon) ==
+ FSRV_RUN_ERROR) {
+
+ FATAL("Error running target in Nyx mode");
+
+ }
+
+}
+
+#endif
+
/* Execute target application. */
static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
@@ -515,11 +597,11 @@ static void showmap_run_target(afl_forkserver_t *fsrv, char **argv) {
it.it_value.tv_sec = (fsrv->exec_tmout / 1000);
it.it_value.tv_usec = (fsrv->exec_tmout % 1000) * 1000;
- }
+ signal(SIGALRM, kill_child);
- signal(SIGALRM, kill_child);
+ setitimer(ITIMER_REAL, &it, NULL);
- setitimer(ITIMER_REAL, &it, NULL);
+ }
if (waitpid(fsrv->child_pid, &status, 0) <= 0) { FATAL("waitpid() failed"); }
@@ -597,49 +679,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
char *afl_preload;
char *frida_afl_preload = NULL;
- setenv("ASAN_OPTIONS",
- "abort_on_error=1:"
- "detect_leaks=0:"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "detect_odr_violation=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 0);
-
- setenv("LSAN_OPTIONS",
- "exitcode=" STRINGIFY(LSAN_ERROR) ":"
- "fast_unwind_on_malloc=0:"
- "symbolize=0:"
- "print_suppressions=0",
- 0);
-
- setenv("UBSAN_OPTIONS",
- "halt_on_error=1:"
- "abort_on_error=1:"
- "malloc_context_size=0:"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 0);
-
- setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "abort_on_error=1:"
- "msan_track_origins=0"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0", 0);
+
+ set_sanitizer_defaults();
if (get_afl_env("AFL_PRELOAD")) {
@@ -695,7 +736,11 @@ static void setup_signal_handlers(void) {
struct sigaction sa;
sa.sa_handler = NULL;
+#ifdef SA_RESTART
sa.sa_flags = SA_RESTART;
+#else
+ sa.sa_flags = 0;
+#endif
sa.sa_sigaction = NULL;
sigemptyset(&sa.sa_mask);
@@ -822,8 +867,8 @@ static void usage(u8 *argv0) {
" -o file - file to write the trace data to\n\n"
"Execution control settings:\n"
- " -t msec - timeout for each run (none)\n"
- " -m megs - memory limit for child process (%u MB)\n"
+ " -t msec - timeout for each run (default: 1000ms)\n"
+ " -m megs - memory limit for child process (default: none)\n"
#if defined(__linux__) && defined(__aarch64__)
" -A - use binary-only instrumentation (ARM CoreSight mode)\n"
#endif
@@ -834,6 +879,7 @@ static void usage(u8 *argv0) {
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
" (Not necessary, here for consistency with other afl-* "
"tools)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
"Other settings:\n"
@@ -854,6 +900,10 @@ static void usage(u8 *argv0) {
"This tool displays raw tuple data captured by AFL instrumentation.\n"
"For additional help, consult %s/README.md.\n\n"
+ "If you use -i mode, then custom mutator post_process send send "
+ "functionality\n"
+ "is supported.\n\n"
+
"Environment variables used:\n"
"LD_BIND_LAZY: do not set LD_BIND_NOW env var for target\n"
"AFL_CMIN_CRASHES_ONLY: (cmin_mode) only write tuples for crashing "
@@ -865,15 +915,22 @@ static void usage(u8 *argv0) {
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
"startup (in milliseconds)\n"
"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, "
- "etc. (default: SIGKILL)\n"
+ "etc.\n"
+ " (default: SIGKILL)\n"
+ "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on "
+ "termination\n"
+ " (default: SIGTERM). If unset and "
+ "AFL_KILL_SIGNAL is\n"
+ " set, that value will be used.\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the "
- "size the target was compiled for\n"
+ "size the\n"
+ " target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
- "AFL_PRINT_FILENAMES: If set, the filename currently processed will be "
- "printed to stdout\n"
+ "AFL_PRINT_FILENAMES: Print the queue entry currently processed will to "
+ "stdout\n"
"AFL_QUIET: do not print extra informational output\n"
"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n",
- argv0, MEM_LIMIT, doc_path);
+ argv0, doc_path);
exit(1);
@@ -905,7 +962,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrsh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
switch (opt) {
@@ -1009,6 +1066,16 @@ int main(int argc, char **argv_orig, char **envp) {
}
+ } else {
+
+ // The forkserver code does not have a way to completely
+ // disable the timeout, so we'll use a very, very long
+ // timeout instead.
+ WARNF(
+ "Setting an execution timeout of 120 seconds ('none' is not "
+ "allowed).");
+ fsrv->exec_tmout = 120 * 1000;
+
}
break;
@@ -1083,6 +1150,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'Y': // fallthough
+#ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv->nyx_mode = 1;
+ fsrv->nyx_parent = true;
+ fsrv->nyx_standalone = true;
+
+ break;
+#else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+#endif
+
case 'b':
/* Secret undocumented mode. Writes output in raw binary format
@@ -1154,7 +1238,21 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
+#ifdef __linux__
+ if (!fsrv->nyx_mode) {
+
+ fsrv->target_path = find_binary(argv[optind]);
+
+ } else {
+
+ fsrv->target_path = ck_strdup(argv[optind]);
+
+ }
+
+#else
fsrv->target_path = find_binary(argv[optind]);
+#endif
+
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
if (!quiet_mode) {
@@ -1210,13 +1308,75 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv =
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+#ifdef __linux__
+
+ } else if (fsrv->nyx_mode) {
+
+ use_argv = ck_alloc(sizeof(char *) * (1));
+ use_argv[0] = argv[0];
+
+ fsrv->nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(use_argv[0], "libnyx.so");
+ fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv->nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv->nyx_use_tmp_workdir = true;
+ fsrv->nyx_bind_cpu_id = 0;
+#endif
+
} else {
use_argv = argv + optind;
}
+ afl = calloc(1, sizeof(afl_state_t));
+
+ if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
+
+ s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
+ if (forksrv_init_tmout < 1) {
+
+ FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
+
+ }
+
+ fsrv->init_tmout = (u32)forksrv_init_tmout;
+
+ }
+
+ if (getenv("AFL_CRASH_EXITCODE")) {
+
+ long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
+ if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
+ exitcode < -127 || exitcode > 128) {
+
+ FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
+ getenv("AFL_CRASH_EXITCODE"));
+
+ }
+
+ fsrv->uses_crash_exitcode = true;
+ // WEXITSTATUS is 8 bit unsigned
+ fsrv->crash_exitcode = (u8)exitcode;
+
+ }
+
+#ifdef __linux__
+ if (!fsrv->nyx_mode && in_dir) {
+
+ (void)check_binary_signatures(fsrv->target_path);
+
+ }
+
+#else
if (in_dir) { (void)check_binary_signatures(fsrv->target_path); }
+#endif
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
@@ -1236,16 +1396,29 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz_len = (u32 *)map;
fsrv->shmem_fuzz = map + sizeof(u32);
+ configure_afl_kill_signals(fsrv, NULL, NULL,
+ (fsrv->qemu_mode || unicorn_mode
+#ifdef __linux__
+ || fsrv->nyx_mode
+#endif
+ )
+ ? SIGKILL
+ : SIGTERM);
+
if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) {
u32 save_be_quiet = be_quiet;
be_quiet = !debug;
if (map_size > 4194304) {
- fsrv->map_size = map_size;
- }
- else {
- fsrv->map_size = 4194304; // dummy temporary value
+
+ fsrv->map_size = map_size;
+
+ } else {
+
+ fsrv->map_size = 4194304; // dummy temporary value
+
}
+
u32 new_map_size =
afl_fsrv_get_mapsize(fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") ||
@@ -1254,9 +1427,6 @@ int main(int argc, char **argv_orig, char **envp) {
: 0);
be_quiet = save_be_quiet;
- fsrv->kill_signal =
- parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
-
if (new_map_size) {
// only reinitialize when it makes sense
@@ -1264,7 +1434,7 @@ int main(int argc, char **argv_orig, char **envp) {
(new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) {
if (!be_quiet)
- ACTF("Aquired new map size for target: %u bytes\n", new_map_size);
+ ACTF("Acquired new map size for target: %u bytes\n", new_map_size);
afl_shm_deinit(&shm);
afl_fsrv_kill(fsrv);
@@ -1283,6 +1453,26 @@ int main(int argc, char **argv_orig, char **envp) {
if (in_dir) {
+ afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
+ afl->afl_env.afl_custom_mutator_library =
+ getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
+ afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
+ setup_custom_mutators(afl);
+
+ } else {
+
+ if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
+
+ WARNF(
+ "Custom mutator environment detected, this is only supported in -i "
+ "mode!\n");
+
+ }
+
+ }
+
+ if (in_dir) {
+
DIR *dir_in, *dir_out = NULL;
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
@@ -1343,36 +1533,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
- if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
-
- s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
- if (forksrv_init_tmout < 1) {
-
- FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
-
- }
-
- fsrv->init_tmout = (u32)forksrv_init_tmout;
-
- }
-
- if (getenv("AFL_CRASH_EXITCODE")) {
-
- long exitcode = strtol(getenv("AFL_CRASH_EXITCODE"), NULL, 10);
- if ((!exitcode && (errno == EINVAL || errno == ERANGE)) ||
- exitcode < -127 || exitcode > 128) {
-
- FATAL("Invalid crash exitcode, expected -127 to 128, but got %s",
- getenv("AFL_CRASH_EXITCODE"));
-
- }
-
- fsrv->uses_crash_exitcode = true;
- // WEXITSTATUS is 8 bit unsigned
- fsrv->crash_exitcode = (u8)exitcode;
-
- }
-
afl_fsrv_start(fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") ||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
@@ -1406,7 +1566,20 @@ int main(int argc, char **argv_orig, char **envp) {
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
- showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+ if (!fsrv->nyx_mode) {
+
+#endif
+ showmap_run_target(fsrv, use_argv);
+#ifdef __linux__
+
+ } else {
+
+ showmap_run_target_nyx_mode(fsrv);
+
+ }
+
+#endif
tcnt = write_results_to_file(fsrv, out_file);
if (!quiet_mode) {
diff --git a/src/afl-tmin.c b/src/afl-tmin.c
index 78537f9f..e7442d1d 100644
--- a/src/afl-tmin.c
+++ b/src/afl-tmin.c
@@ -12,7 +12,7 @@
Dominik Maier <mail@dmnk.co>
Copyright 2016, 2017 Google Inc. All rights reserved.
- Copyright 2019-2022 AFLplusplus Project. All rights reserved.
+ Copyright 2019-2023 AFLplusplus Project. All rights reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@@ -113,7 +113,7 @@ static void kill_child() {
if (fsrv->child_pid > 0) {
- kill(fsrv->child_pid, fsrv->kill_signal);
+ kill(fsrv->child_pid, fsrv->child_kill_signal);
fsrv->child_pid = -1;
}
@@ -674,27 +674,6 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
/* Set sane defaults... */
- x = get_afl_env("ASAN_OPTIONS");
-
- if (x) {
-
- if (!strstr(x, "abort_on_error=1")) {
-
- FATAL("Custom ASAN_OPTIONS set without abort_on_error=1 - please fix!");
-
- }
-
-#ifndef ASAN_BUILD
- if (!getenv("AFL_DEBUG") && !strstr(x, "symbolize=0")) {
-
- FATAL("Custom ASAN_OPTIONS set without symbolize=0 - please fix!");
-
- }
-
-#endif
-
- }
-
x = get_afl_env("MSAN_OPTIONS");
if (x) {
@@ -706,69 +685,9 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
}
- if (!strstr(x, "symbolize=0")) {
-
- FATAL("Custom MSAN_OPTIONS set without symbolize=0 - please fix!");
-
- }
-
}
- x = get_afl_env("LSAN_OPTIONS");
-
- if (x) {
-
- if (!strstr(x, "symbolize=0")) {
-
- FATAL("Custom LSAN_OPTIONS set without symbolize=0 - please fix!");
-
- }
-
- }
-
- setenv("ASAN_OPTIONS",
- "abort_on_error=1:"
- "detect_leaks=0:"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "detect_odr_violation=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 0);
-
- setenv("UBSAN_OPTIONS",
- "halt_on_error=1:"
- "abort_on_error=1:"
- "malloc_context_size=0:"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0",
- 0);
-
- setenv("MSAN_OPTIONS", "exit_code=" STRINGIFY(MSAN_ERROR) ":"
- "abort_on_error=1:"
- "msan_track_origins=0"
- "allocator_may_return_null=1:"
- "symbolize=0:"
- "handle_segv=0:"
- "handle_sigbus=0:"
- "handle_abort=0:"
- "handle_sigfpe=0:"
- "handle_sigill=0", 0);
-
- setenv("LSAN_OPTIONS",
- "exitcode=" STRINGIFY(LSAN_ERROR) ":"
- "fast_unwind_on_malloc=0:"
- "symbolize=0:"
- "print_suppressions=0",
- 0);
+ set_sanitizer_defaults();
if (get_afl_env("AFL_PRELOAD")) {
@@ -824,7 +743,11 @@ static void setup_signal_handlers(void) {
struct sigaction sa;
sa.sa_handler = NULL;
+#ifdef SA_RESTART
sa.sa_flags = SA_RESTART;
+#else
+ sa.sa_flags = 0;
+#endif
sa.sa_sigaction = NULL;
sigemptyset(&sa.sa_mask);
@@ -866,6 +789,7 @@ static void usage(u8 *argv0) {
"mode)\n"
" (Not necessary, here for consistency with other afl-* "
"tools)\n"
+ " -X - use Nyx mode\n"
#endif
"\n"
@@ -879,8 +803,12 @@ static void usage(u8 *argv0) {
"Environment variables used:\n"
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n"
- "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
- "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
+ "AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in ms)\n"
+ "AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc.\n"
+ " (default: SIGKILL)\n"
+ "AFL_FORK_SERVER_KILL_SIGNAL: Kill signal for the fork server on termination\n"
+ " (default: SIGTERM). If unset and AFL_KILL_SIGNAL is\n"
+ " set, that value will be used.\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
@@ -918,7 +846,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
- while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) {
+ while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
switch (opt) {
@@ -1076,6 +1004,23 @@ int main(int argc, char **argv_orig, char **envp) {
break;
+ case 'Y': // fallthough
+#ifdef __linux__
+ case 'X': /* NYX mode */
+
+ if (fsrv->nyx_mode) { FATAL("Multiple -X options not supported"); }
+
+ fsrv->nyx_mode = 1;
+ fsrv->nyx_parent = true;
+ fsrv->nyx_standalone = true;
+
+ break;
+#else
+ case 'X':
+ FATAL("Nyx mode is only availabe on linux...");
+ break;
+#endif
+
case 'H': /* Hang Mode */
/* Minimizes a testcase to the minimum that still times out */
@@ -1141,7 +1086,21 @@ int main(int argc, char **argv_orig, char **envp) {
set_up_environment(fsrv, argv);
+#ifdef __linux__
+ if (!fsrv->nyx_mode) {
+
+ fsrv->target_path = find_binary(argv[optind]);
+
+ } else {
+
+ fsrv->target_path = ck_strdup(argv[optind]);
+
+ }
+
+#else
fsrv->target_path = find_binary(argv[optind]);
+#endif
+
fsrv->trace_bits = afl_shm_init(&shm, map_size, 0);
detect_file_args(argv + optind, out_file, &fsrv->use_stdin);
signal(SIGALRM, kill_child);
@@ -1165,6 +1124,26 @@ int main(int argc, char **argv_orig, char **envp) {
use_argv =
get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind);
+#ifdef __linux__
+
+ } else if (fsrv->nyx_mode) {
+
+ fsrv->nyx_id = 0;
+
+ u8 *libnyx_binary = find_afl_binary(argv[0], "libnyx.so");
+ fsrv->nyx_handlers = afl_load_libnyx_plugin(libnyx_binary);
+ if (fsrv->nyx_handlers == NULL) {
+
+ FATAL("failed to initialize libnyx.so...");
+
+ }
+
+ fsrv->nyx_use_tmp_workdir = true;
+ fsrv->nyx_bind_cpu_id = 0;
+
+ use_argv = argv + optind;
+#endif
+
} else {
use_argv = argv + optind;
@@ -1195,8 +1174,8 @@ int main(int argc, char **argv_orig, char **envp) {
}
- fsrv->kill_signal =
- parse_afl_kill_signal_env(getenv("AFL_KILL_SIGNAL"), SIGKILL);
+ configure_afl_kill_signals(
+ fsrv, NULL, NULL, (fsrv->qemu_mode || unicorn_mode) ? SIGKILL : SIGTERM);
if (getenv("AFL_CRASH_EXITCODE")) {
@@ -1234,7 +1213,12 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz = map + sizeof(u32);
read_initial_file();
+
+#ifdef __linux__
+ if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }
+#else
(void)check_binary_signatures(fsrv->target_path);
+#endif
if (!fsrv->qemu_mode && !unicorn_mode) {
@@ -1252,7 +1236,7 @@ int main(int argc, char **argv_orig, char **envp) {
(new_map_size > map_size && new_map_size - map_size > MAP_SIZE)) {
if (!be_quiet)
- ACTF("Aquired new map size for target: %u bytes\n", new_map_size);
+ ACTF("Acquired new map size for target: %u bytes\n", new_map_size);
afl_shm_deinit(&shm);
afl_fsrv_kill(fsrv);