[compiler-rt] 44aaca3 - [libFuzzer] Allow discarding output in ExecuteCommand in Fuchsia.

Marco Vanotti via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 17 12:15:59 PST 2020


Author: Marco Vanotti
Date: 2020-01-17T12:15:46-08:00
New Revision: 44aaca3de4f4918b6178a28d855b153ab335e6a3

URL: https://github.com/llvm/llvm-project/commit/44aaca3de4f4918b6178a28d855b153ab335e6a3
DIFF: https://github.com/llvm/llvm-project/commit/44aaca3de4f4918b6178a28d855b153ab335e6a3.diff

LOG: [libFuzzer] Allow discarding output in ExecuteCommand in Fuchsia.

Summary:
This commit modifies the way `ExecuteCommand` works in fuchsia by adding
special logic to handle `/dev/null`.

The FuzzerCommand interface does not have a way to "discard" the output,
so other parts of the code just set the output file to `getDevNull()`.
The problem is that fuchsia does not have a named file that is
equivalent to `/dev/null`, so opening that file just fails.

This commit detects whether the specified output file is `getDevNull`,
and if that's the case, it will not copy the file descriptor for stdout
in the spawned process.

NOTE that modifying `FuzzerCommand` to add a "discardOutput" function
involves a significant refactor of all the other platforms, as they all
rely on the `toString()` method of `FuzzerCommand`.

This allows libfuzzer in fuchsia to run with `fork=1`, as the merge
process (`FuzzerMerge.cpp`) invoked `ExecuteCommand` with `/dev/null` as the
output.

Reviewers: aarongreen, phosek

Reviewed By: aarongreen

Subscribers: #sanitizers, llvm-commits

Tags: #sanitizers, #llvm

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

Added: 
    

Modified: 
    compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp

Removed: 
    


################################################################################
diff  --git a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
index bde9f68d62aa..a9fff254dff0 100644
--- a/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
+++ b/compiler-rt/lib/fuzzer/FuzzerUtilFuchsia.cpp
@@ -34,6 +34,8 @@
 #include <zircon/syscalls/object.h>
 #include <zircon/types.h>
 
+#include <vector>
+
 namespace fuzzer {
 
 // Given that Fuchsia doesn't have the POSIX signals that libFuzzer was written
@@ -424,6 +426,17 @@ RunOnDestruction<Fn> at_scope_exit(Fn fn) {
   return RunOnDestruction<Fn>(fn);
 }
 
+static fdio_spawn_action_t clone_fd_action(int localFd, int targetFd) {
+  return {
+      .action = FDIO_SPAWN_ACTION_CLONE_FD,
+      .fd =
+          {
+              .local_fd = localFd,
+              .target_fd = targetFd,
+          },
+  };
+}
+
 int ExecuteCommand(const Command &Cmd) {
   zx_status_t rc;
 
@@ -442,17 +455,26 @@ int ExecuteCommand(const Command &Cmd) {
   // so write the log file(s) there.
   // However, we don't want to apply this logic for absolute paths.
   int FdOut = STDOUT_FILENO;
+  bool discardStdout = false;
+  bool discardStderr = false;
+
   if (Cmd.hasOutputFile()) {
     std::string Path = Cmd.getOutputFile();
-    bool IsAbsolutePath = Path.length() > 1 && Path[0] == '/';
-    if (!IsAbsolutePath && Cmd.hasFlag("artifact_prefix"))
-      Path = Cmd.getFlagValue("artifact_prefix") + "/" + Path;
-
-    FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
-    if (FdOut == -1) {
-      Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),
-             strerror(errno));
-      return ZX_ERR_IO;
+    if (Path == getDevNull()) {
+      // On Fuchsia, there's no "/dev/null" like-file, so we
+      // just don't copy the FDs into the spawned process.
+      discardStdout = true;
+    } else {
+      bool IsAbsolutePath = Path.length() > 1 && Path[0] == '/';
+      if (!IsAbsolutePath && Cmd.hasFlag("artifact_prefix"))
+        Path = Cmd.getFlagValue("artifact_prefix") + "/" + Path;
+
+      FdOut = open(Path.c_str(), O_WRONLY | O_CREAT | O_TRUNC, 0);
+      if (FdOut == -1) {
+        Printf("libFuzzer: failed to open %s: %s\n", Path.c_str(),
+               strerror(errno));
+        return ZX_ERR_IO;
+      }
     }
   }
   auto CloseFdOut = at_scope_exit([FdOut]() {
@@ -462,43 +484,29 @@ int ExecuteCommand(const Command &Cmd) {
 
   // Determine stderr
   int FdErr = STDERR_FILENO;
-  if (Cmd.isOutAndErrCombined())
+  if (Cmd.isOutAndErrCombined()) {
     FdErr = FdOut;
+    if (discardStdout)
+      discardStderr = true;
+  }
 
   // Clone the file descriptors into the new process
-  fdio_spawn_action_t SpawnAction[] = {
-      {
-          .action = FDIO_SPAWN_ACTION_CLONE_FD,
-          .fd =
-              {
-                  .local_fd = STDIN_FILENO,
-                  .target_fd = STDIN_FILENO,
-              },
-      },
-      {
-          .action = FDIO_SPAWN_ACTION_CLONE_FD,
-          .fd =
-              {
-                  .local_fd = FdOut,
-                  .target_fd = STDOUT_FILENO,
-              },
-      },
-      {
-          .action = FDIO_SPAWN_ACTION_CLONE_FD,
-          .fd =
-              {
-                  .local_fd = FdErr,
-                  .target_fd = STDERR_FILENO,
-              },
-      },
-  };
+  std::vector<fdio_spawn_action_t> SpawnActions;
+  SpawnActions.push_back(clone_fd_action(STDIN_FILENO, STDIN_FILENO));
+
+  if (!discardStdout)
+    SpawnActions.push_back(clone_fd_action(FdOut, STDOUT_FILENO));
+  if (!discardStderr)
+    SpawnActions.push_back(clone_fd_action(FdErr, STDERR_FILENO));
 
   // Start the process.
   char ErrorMsg[FDIO_SPAWN_ERR_MSG_MAX_LENGTH];
   zx_handle_t ProcessHandle = ZX_HANDLE_INVALID;
-  rc = fdio_spawn_etc(
-      ZX_HANDLE_INVALID, FDIO_SPAWN_CLONE_ALL & (~FDIO_SPAWN_CLONE_STDIO),
-      Argv[0], Argv.get(), nullptr, 3, SpawnAction, &ProcessHandle, ErrorMsg);
+  rc = fdio_spawn_etc(ZX_HANDLE_INVALID,
+                      FDIO_SPAWN_CLONE_ALL & (~FDIO_SPAWN_CLONE_STDIO), Argv[0],
+                      Argv.get(), nullptr, SpawnActions.size(),
+                      SpawnActions.data(), &ProcessHandle, ErrorMsg);
+
   if (rc != ZX_OK) {
     Printf("libFuzzer: failed to launch '%s': %s, %s\n", Argv[0], ErrorMsg,
            _zx_status_get_string(rc));


        


More information about the llvm-commits mailing list