about summary refs log tree commit diff
path: root/src/afl-common.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/afl-common.c')
-rw-r--r--src/afl-common.c139
1 files changed, 136 insertions, 3 deletions
diff --git a/src/afl-common.c b/src/afl-common.c
index 31005804..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.
@@ -58,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);
@@ -69,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);
@@ -94,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);
@@ -1275,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
+