Add sandboxfs support to the processwrapper-sandbox spawn runner.

The lack of this is an overlook from when I first added sandboxfs support
to the linux-sandbox and darwin-sandbox spawn runners.  I noticed this
by chance when doing some sandboxfs work on a Debian VM, where namespaces
are not allowed for unprivileged users.  I saw that my builds were using
the processwrapper-sandbox, not the linux-sandbox, and that they were not
using sandboxfs.

I know that this comes with no tests.  There currently are not tests to
validate a real build with sandboxfs enabled.  If there were, these tests
should verify the behavior with the platform-specific spawn runner and
now also with the more generic processwrapper-sandbox.  However, adding
these tests is pretty complicated and their benefit would be pretty low
at this point (because sandboxfs is not present in Bazel CI so we would
not run them automatically).  I'll work on these later if we decide to
make further progress on this feature.

RELNOTES: None.
PiperOrigin-RevId: 299846783
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedSpawnRunner.java
index 7da26c9..6a743b1 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedSpawnRunner.java
@@ -15,16 +15,20 @@
 package com.google.devtools.build.lib.sandbox;
 
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
 import com.google.devtools.build.lib.actions.ExecException;
 import com.google.devtools.build.lib.actions.Spawn;
 import com.google.devtools.build.lib.exec.TreeDeleter;
 import com.google.devtools.build.lib.exec.local.LocalEnvProvider;
 import com.google.devtools.build.lib.runtime.CommandEnvironment;
 import com.google.devtools.build.lib.runtime.ProcessWrapperUtil;
+import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs;
+import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxOutputs;
 import com.google.devtools.build.lib.util.OS;
 import com.google.devtools.build.lib.vfs.Path;
 import java.io.IOException;
 import java.time.Duration;
+import javax.annotation.Nullable;
 
 /** Strategy that uses sandboxing to execute a process. */
 final class ProcessWrapperSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
@@ -38,6 +42,8 @@
   private final Path sandboxBase;
   private final LocalEnvProvider localEnvProvider;
   private final Duration timeoutKillDelay;
+  @Nullable private final SandboxfsProcess sandboxfsProcess;
+  private final boolean sandboxfsMapSymlinkTargets;
   private final TreeDeleter treeDeleter;
 
   /**
@@ -46,11 +52,16 @@
    * @param cmdEnv the command environment to use
    * @param sandboxBase path to the sandbox base directory
    * @param timeoutKillDelay additional grace period before killing timing out commands
+   * @param sandboxfsProcess instance of the sandboxfs process to use; may be null for none, in
+   *     which case the runner uses a symlinked sandbox
+   * @param sandboxfsMapSymlinkTargets map the targets of symlinks within the sandbox if true
    */
   ProcessWrapperSandboxedSpawnRunner(
       CommandEnvironment cmdEnv,
       Path sandboxBase,
       Duration timeoutKillDelay,
+      @Nullable SandboxfsProcess sandboxfsProcess,
+      boolean sandboxfsMapSymlinkTargets,
       TreeDeleter treeDeleter) {
     super(cmdEnv);
     this.processWrapper = ProcessWrapperUtil.getProcessWrapper(cmdEnv);
@@ -58,6 +69,8 @@
     this.localEnvProvider = LocalEnvProvider.forCurrentOs(cmdEnv.getClientEnv());
     this.sandboxBase = sandboxBase;
     this.timeoutKillDelay = timeoutKillDelay;
+    this.sandboxfsProcess = sandboxfsProcess;
+    this.sandboxfsMapSymlinkTargets = sandboxfsMapSymlinkTargets;
     this.treeDeleter = treeDeleter;
   }
 
@@ -94,20 +107,38 @@
       commandLineBuilder.setStatisticsPath(statisticsPath);
     }
 
-    return new SymlinkedSandboxedSpawn(
-        sandboxPath,
-        sandboxExecRoot,
-        commandLineBuilder.build(),
-        environment,
+    SandboxInputs inputs =
         SandboxHelpers.processInputFiles(
             spawn,
             context,
             execRoot,
-            getSandboxOptions().symlinkedSandboxExpandsTreeArtifactsInRunfilesTree),
-        SandboxHelpers.getOutputs(spawn),
-        getWritableDirs(sandboxExecRoot, environment),
-        treeDeleter,
-        statisticsPath);
+            getSandboxOptions().symlinkedSandboxExpandsTreeArtifactsInRunfilesTree);
+    SandboxOutputs outputs = SandboxHelpers.getOutputs(spawn);
+
+    if (sandboxfsProcess != null) {
+      return new SandboxfsSandboxedSpawn(
+          sandboxfsProcess,
+          sandboxPath,
+          commandLineBuilder.build(),
+          environment,
+          inputs,
+          outputs,
+          ImmutableSet.of(),
+          sandboxfsMapSymlinkTargets,
+          treeDeleter,
+          statisticsPath);
+    } else {
+      return new SymlinkedSandboxedSpawn(
+          sandboxPath,
+          sandboxExecRoot,
+          commandLineBuilder.build(),
+          environment,
+          inputs,
+          outputs,
+          getWritableDirs(sandboxExecRoot, environment),
+          treeDeleter,
+          statisticsPath);
+    }
   }
 
   @Override
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java
index 878b4c7..10ae634 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java
@@ -272,6 +272,8 @@
                   cmdEnv,
                   sandboxBase,
                   timeoutKillDelay,
+                  sandboxfsProcess,
+                  options.sandboxfsMapSymlinkTargets,
                   treeDeleter));
       spawnRunners.add(spawnRunner);
       builder.addActionContext(