[compiler-rt] r358703 - Summary:

Jonathan Metzman via llvm-commits llvm-commits at lists.llvm.org
Thu Apr 18 11:49:12 PDT 2019


Author: metzman
Date: Thu Apr 18 11:49:11 2019
New Revision: 358703

URL: http://llvm.org/viewvc/llvm-project?rev=358703&view=rev
Log:
Summary:
Add close_fd_mask functionality to AFL driver.

Summary:
Add support for env var AFL_DRIVER_CLOSE_FD_MASK which behaves
the same as libFuzzer's -close_fd_mask=1.

Also add tests.

Reviewers: kcc, vitalybuka, morehouse

Reviewed By: morehouse

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

Differential Revision: https://reviews.llvm.org/D60334

Added:
    compiler-rt/trunk/test/fuzzer/afl-driver-close-fd-mask.test
Modified:
    compiler-rt/trunk/lib/fuzzer/afl/afl_driver.cpp
    compiler-rt/trunk/test/fuzzer/AFLDriverTest.cpp
    compiler-rt/trunk/test/fuzzer/afl-driver.test

Modified: compiler-rt/trunk/lib/fuzzer/afl/afl_driver.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/lib/fuzzer/afl/afl_driver.cpp?rev=358703&r1=358702&r2=358703&view=diff
==============================================================================
--- compiler-rt/trunk/lib/fuzzer/afl/afl_driver.cpp (original)
+++ compiler-rt/trunk/lib/fuzzer/afl/afl_driver.cpp Thu Apr 18 11:49:11 2019
@@ -31,10 +31,14 @@ clang++ afl_driver.cpp test_fuzzer.o afl
 rm -rf IN OUT; mkdir IN OUT; echo z > IN/z;
 $AFL_HOME/afl-fuzz -i IN -o OUT ./a.out
 ################################################################################
-AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this environment variable
-*appends* stderr to the file specified. If the file does not exist, it is
-created. This is useful for getting stack traces (when using ASAN for example)
-or original error messages on hard to reproduce bugs.
+AFL_DRIVER_STDERR_DUPLICATE_FILENAME: Setting this *appends* stderr to the file
+specified. If the file does not exist, it is created. This is useful for getting
+stack traces (when using ASAN for example) or original error messages on hard
+to reproduce bugs. Note that any content written to stderr will be written to
+this file instead of stderr's usual location.
+
+AFL_DRIVER_CLOSE_FD_MASK: Similar to libFuzzer's -close_fd_mask behavior option.
+If 1, close stdout at startup. If 2 close stderr; if 3 close both.
 
 */
 #include <assert.h>
@@ -97,16 +101,24 @@ static volatile char suppress_warning2 =
 
 // Notify AFL about deferred forkserver.
 static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
-extern "C" void  __afl_manual_init();
+extern "C" void __afl_manual_init();
 static volatile char suppress_warning1 = AFL_DEFER_FORKSVR[0];
 
 // Input buffer.
 static const size_t kMaxAflInputSize = 1 << 20;
 static uint8_t AflInputBuf[kMaxAflInputSize];
 
+// Use this optionally defined function to output sanitizer messages even if
+// user asks to close stderr.
+__attribute__((weak)) extern "C" void __sanitizer_set_report_fd(void *);
+
+// Keep track of where stderr content is being written to, so that
+// dup_and_close_stderr can use the correct one.
+static FILE *output_file = stderr;
+
 // Experimental feature to use afl_driver without AFL's deferred mode.
 // Needs to run before __afl_auto_init.
-__attribute__((constructor(0))) void __decide_deferred_forkserver(void) {
+__attribute__((constructor(0))) static void __decide_deferred_forkserver(void) {
   if (getenv("AFL_DRIVER_DONT_DEFER")) {
     if (unsetenv("__AFL_DEFER_FORKSRV")) {
       perror("Failed to unset __AFL_DEFER_FORKSRV");
@@ -117,13 +129,13 @@ __attribute__((constructor(0))) void __d
 
 // If the user asks us to duplicate stderr, then do it.
 static void maybe_duplicate_stderr() {
-  char* stderr_duplicate_filename =
+  char *stderr_duplicate_filename =
       getenv("AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
 
   if (!stderr_duplicate_filename)
     return;
 
-  FILE* stderr_duplicate_stream =
+  FILE *stderr_duplicate_stream =
       freopen(stderr_duplicate_filename, "a+", stderr);
 
   if (!stderr_duplicate_stream) {
@@ -132,6 +144,54 @@ static void maybe_duplicate_stderr() {
         "Failed to duplicate stderr to AFL_DRIVER_STDERR_DUPLICATE_FILENAME");
     abort();
   }
+  output_file = stderr_duplicate_stream;
+}
+
+// Most of these I/O functions were inspired by/copied from libFuzzer's code.
+static void discard_output(int fd) {
+  FILE *temp = fopen("/dev/null", "w");
+  if (!temp)
+    abort();
+  dup2(fileno(temp), fd);
+  fclose(temp);
+}
+
+static void close_stdout() { discard_output(STDOUT_FILENO); }
+
+// Prevent the targeted code from writing to "stderr" but allow sanitizers and
+// this driver to do so.
+static void dup_and_close_stderr() {
+  int output_fileno = fileno(output_file);
+  int output_fd = dup(output_fileno);
+  if (output_fd <= 0)
+    abort();
+  FILE *new_output_file = fdopen(output_fd, "w");
+  if (!new_output_file)
+    abort();
+  if (!__sanitizer_set_report_fd)
+    return;
+  __sanitizer_set_report_fd(reinterpret_cast<void *>(output_fd));
+  discard_output(output_fileno);
+}
+
+static void Printf(const char *Fmt, ...) {
+  va_list ap;
+  va_start(ap, Fmt);
+  vfprintf(output_file, Fmt, ap);
+  va_end(ap);
+  fflush(output_file);
+}
+
+// Close stdout and/or stderr if user asks for it.
+static void maybe_close_fd_mask() {
+  char *fd_mask_str = getenv("AFL_DRIVER_CLOSE_FD_MASK");
+  if (!fd_mask_str)
+    return;
+  int fd_mask = atoi(fd_mask_str);
+  if (fd_mask & 2)
+    dup_and_close_stderr();
+  if (fd_mask & 1)
+    close_stdout();
 }
 
 // Define LLVMFuzzerMutate to avoid link failures for targets that use it
@@ -142,7 +202,7 @@ extern "C" size_t LLVMFuzzerMutate(uint8
 }
 
 // Execute any files provided as parameters.
-int ExecuteFilesOnyByOne(int argc, char **argv) {
+static int ExecuteFilesOnyByOne(int argc, char **argv) {
   for (int i = 1; i < argc; i++) {
     std::ifstream in(argv[i], std::ios::binary);
     in.seekg(0, in.end);
@@ -161,7 +221,7 @@ int ExecuteFilesOnyByOne(int argc, char
 }
 
 int main(int argc, char **argv) {
-  fprintf(stderr,
+  Printf(
       "======================= INFO =========================\n"
       "This binary is built for AFL-fuzz.\n"
       "To run the target function on individual input(s) execute this:\n"
@@ -174,12 +234,13 @@ int main(int argc, char **argv) {
       "re-spawning the process (default: 1000)\n"
       "======================================================\n",
           argv[0], argv[0], argv[0]);
+
+  maybe_duplicate_stderr();
+  maybe_close_fd_mask();
   if (LLVMFuzzerInitialize)
     LLVMFuzzerInitialize(&argc, &argv);
   // Do any other expensive one-time initialization here.
 
-  maybe_duplicate_stderr();
-
   if (!getenv("AFL_DRIVER_DONT_DEFER"))
     __afl_manual_init();
 
@@ -187,8 +248,7 @@ int main(int argc, char **argv) {
   if (argc == 2 && argv[1][0] == '-')
       N = atoi(argv[1] + 1);
   else if(argc == 2 && (N = atoi(argv[1])) > 0)
-      fprintf(stderr, "WARNING: using the deprecated call style `%s %d`\n",
-              argv[0], N);
+      Printf("WARNING: using the deprecated call style `%s %d`\n", argv[0], N);
   else if (argc > 1)
     return ExecuteFilesOnyByOne(argc, argv);
 
@@ -212,5 +272,5 @@ int main(int argc, char **argv) {
       delete[] copy;
     }
   }
-  fprintf(stderr, "%s: successfully executed %d input(s)\n", argv[0], num_runs);
+  Printf("%s: successfully executed %d input(s)\n", argv[0], num_runs);
 }

Modified: compiler-rt/trunk/test/fuzzer/AFLDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/AFLDriverTest.cpp?rev=358703&r1=358702&r2=358703&view=diff
==============================================================================
--- compiler-rt/trunk/test/fuzzer/AFLDriverTest.cpp (original)
+++ compiler-rt/trunk/test/fuzzer/AFLDriverTest.cpp Thu Apr 18 11:49:11 2019
@@ -2,28 +2,33 @@
 // See https://llvm.org/LICENSE.txt for license information.
 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
-// Contains dummy functions used to avoid dependency on AFL.
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
 
+// Dummy functions used to avoid dependency on AFL.
 extern "C" void __afl_manual_init() {}
 
 extern "C" int __afl_persistent_loop(unsigned int N) {
   static int Count = N;
-  fprintf(stderr, "__afl_persistent_loop calle, Count = %d\n", Count);
-  if (Count--) return 1;
-  return 0;
+  fprintf(stderr, "__afl_persistent_loop called, Count = %d\n", Count);
+  return Count--;
 }
 
 // This declaration exists to prevent the Darwin linker
 // from complaining about this being a missing weak symbol.
 extern "C" int LLVMFuzzerInitialize(int *argc, char ***argv) {
-  fprintf(stderr, "LLVMFuzzerInitialize called\n");
   return 0;
 }
 
 extern "C" int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) {
-  fprintf(stderr, "LLVMFuzzerTestOneInput called; Size = %zd\n", Size);
-  return 0;
+  puts("STDOUT MESSAGE");
+  fflush(stdout);
+  fprintf(stderr, "STDERR MESSAGE\n"
+                  "LLVMFuzzerTestOneInput called; Size = %zd\n",
+          Size);
+  if (Size < 4)
+    return 0;
+
+  return Data[Size];
 }

Added: compiler-rt/trunk/test/fuzzer/afl-driver-close-fd-mask.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/afl-driver-close-fd-mask.test?rev=358703&view=auto
==============================================================================
--- compiler-rt/trunk/test/fuzzer/afl-driver-close-fd-mask.test (added)
+++ compiler-rt/trunk/test/fuzzer/afl-driver-close-fd-mask.test Thu Apr 18 11:49:11 2019
@@ -0,0 +1,31 @@
+REQUIRES: linux
+RUN: %no_fuzzer_cpp_compiler %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest
+
+; Test that not specifying AFL_DRIVER_CLOSE_FD_MASK works as intended.
+RUN: echo -n "abc" > %t.file3
+RUN: unset AFL_DRIVER_CLOSE_FD_MASK
+RUN: %run %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefixes=STDERR,STDOUT
+STDOUT: STDOUT MESSAGE
+STDERR: STDERR MESSAGE
+
+; Test that stdout is closed properly.
+RUN: AFL_DRIVER_CLOSE_FD_MASK=1 %run %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefixes=NOT_STDOUT,STDERR
+NOT_STDOUT-NOT: STDOUT MESSAGE
+
+; Test that stderr is closed properly.
+RUN: AFL_DRIVER_CLOSE_FD_MASK=2 %run %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefixes=NOT_STDERR,STDOUT
+NOT_STDERR-NOT: STDERR MESSAGE
+
+; Test that both are closed properly.
+RUN: AFL_DRIVER_CLOSE_FD_MASK=3 %run %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefixes=NOT_STDERR,NOT_STDOUT
+
+; Test that a stack is printed when we close stderr
+RUN: echo -n "abcd" > %t.file4
+RUN: AFL_DRIVER_CLOSE_FD_MASK=2 not %run %t-AFLDriverTest < %t.file4 2>&1  | FileCheck %s --check-prefixes=ASAN_CRASH,STDOUT,NOT_STDERR
+ASAN_CRASH: ERROR: AddressSanitizer
+
+; Test that a stack is written to the stderr duplicate file when we close stderr
+; and specify a duplicate.
+RUN: rm -f %t.stderr
+RUN: AFL_DRIVER_STDERR_DUPLICATE_FILENAME=%t.stderr AFL_DRIVER_CLOSE_FD_MASK=2 not %run %t-AFLDriverTest < %t.file4
+RUN: cat %t.stderr | FileCheck %s --check-prefixes=ASAN_CRASH,NOT_STDERR

Modified: compiler-rt/trunk/test/fuzzer/afl-driver.test
URL: http://llvm.org/viewvc/llvm-project/compiler-rt/trunk/test/fuzzer/afl-driver.test?rev=358703&r1=358702&r2=358703&view=diff
==============================================================================
--- compiler-rt/trunk/test/fuzzer/afl-driver.test (original)
+++ compiler-rt/trunk/test/fuzzer/afl-driver.test Thu Apr 18 11:49:11 2019
@@ -3,27 +3,23 @@ REQUIRES: linux
 RUN: %no_fuzzer_cpp_compiler %S/AFLDriverTest.cpp %libfuzzer_src/afl/afl_driver.cpp -o %t-AFLDriverTest
 
 RUN: echo -n "abc" > %t.file3
-RUN: echo -n "abcd" > %t.file4
-
 RUN: %run %t-AFLDriverTest < %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK1
-CHECK1: __afl_persistent_loop calle, Count = 1000
+CHECK1: __afl_persistent_loop called, Count = 1000
 CHECK1: LLVMFuzzerTestOneInput called; Size = 3
 
-
 RUN: %run %t-AFLDriverTest < %t.file3 -42 2>&1 | FileCheck %s --check-prefix=CHECK2
-CHECK2: __afl_persistent_loop calle, Count = 42
+CHECK2: __afl_persistent_loop called, Count = 42
 CHECK2: LLVMFuzzerTestOneInput called; Size = 3
 
-
 RUN: %run %t-AFLDriverTest < %t.file3 666 2>&1 | FileCheck %s --check-prefix=CHECK3
 CHECK3: WARNING: using the deprecated call style
-CHECK3: __afl_persistent_loop calle, Count = 666
+CHECK3: __afl_persistent_loop called, Count = 666
 CHECK3: LLVMFuzzerTestOneInput called; Size = 3
 
-
 RUN: %run %t-AFLDriverTest %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK4
 CHECK4: LLVMFuzzerTestOneInput called; Size = 3
 
-RUN: %run %t-AFLDriverTest %t.file3 %t.file4  2>&1 | FileCheck %s --check-prefix=CHECK5
-CHECK5: LLVMFuzzerTestOneInput called; Size = 3
-CHECK5: LLVMFuzzerTestOneInput called; Size = 4
+RUN: echo -n "ab" > %t.file2
+RUN: %run %t-AFLDriverTest %t.file2 %t.file3 2>&1 | FileCheck %s --check-prefix=CHECK5
+CHECK5: LLVMFuzzerTestOneInput called; Size = 2
+CHECK5: LLVMFuzzerTestOneInput called; Size = 3
\ No newline at end of file




More information about the llvm-commits mailing list