aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/sandbox
diff options
context:
space:
mode:
authorGravatar jmmv <jmmv@google.com>2018-03-22 15:12:00 -0700
committerGravatar Copybara-Service <copybara-piper@google.com>2018-03-22 15:13:47 -0700
commit3a7b8bc2abeaf8b8647c037bed1dd5fd73b8392b (patch)
tree3da0966322e6c347efbc59851f2a9acb9a1fd13d /src/main/java/com/google/devtools/build/lib/sandbox
parent4ef3dc67e8226ee56a098e3174be5dce2685c70f (diff)
Add support for sandboxfs-based sandboxing to macOS.
This only modifies the DarwinSandboxedSpawnRunner for now and leaves behind the Linux version. The latter is a bit more complex to do because of the need to deal with tmpfs and bind-mount interactions. We expect sandboxfs to have the biggest impact on macOS anyway, not Linux, so this can wait until this has proven that it deserves staying for the long-term. Tested: Manually ran a self-build of Bazel on a version of Bazel built with these changes and the build passed. RELNOTES: None. PiperOrigin-RevId: 190133429
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/sandbox')
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedSpawnRunner.java103
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/SandboxActionContextProvider.java4
2 files changed, 76 insertions, 31 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedSpawnRunner.java
index 6bf48fe22b..e80edf03f1 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedSpawnRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedSpawnRunner.java
@@ -16,6 +16,7 @@ package com.google.devtools.build.lib.sandbox;
import static java.nio.charset.StandardCharsets.UTF_8;
+import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
@@ -49,6 +50,7 @@ import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
+import javax.annotation.Nullable;
/** Spawn runner that uses Darwin (macOS) sandboxing to execute a process. */
@ExecutionStrategy(
@@ -56,7 +58,14 @@ import java.util.Set;
contextType = SpawnActionContext.class
)
final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
- private static final String SANDBOX_EXEC = "/usr/bin/sandbox-exec";
+
+ /** Path to the {@code getconf} system tool to use. */
+ @VisibleForTesting
+ static String getconfBinary = "/usr/bin/getconf";
+
+ /** Path to the {@code sandbox-exec} system tool to use. */
+ @VisibleForTesting
+ static String sandboxExecBinary = "/usr/bin/sandbox-exec";
public static boolean isSupported(CommandEnvironment cmdEnv) {
if (OS.getCurrent() != OS.DARWIN) {
@@ -67,7 +76,7 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
}
List<String> args = new ArrayList<>();
- args.add(SANDBOX_EXEC);
+ args.add(sandboxExecBinary);
args.add("-p");
args.add("(version 1) (allow default)");
args.add("/usr/bin/true");
@@ -90,6 +99,7 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
private final String productName;
private final Path processWrapper;
private final Optional<Duration> timeoutKillDelay;
+ private final @Nullable SandboxfsProcess sandboxfsProcess;
/**
* The set of directories that always should be writable, independent of the Spawn itself.
@@ -109,7 +119,7 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
*/
DarwinSandboxedSpawnRunner(CommandEnvironment cmdEnv, Path sandboxBase, String productName)
throws IOException {
- this(cmdEnv, sandboxBase, productName, Optional.empty());
+ this(cmdEnv, sandboxBase, productName, Optional.empty(), null);
}
/**
@@ -125,7 +135,7 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
DarwinSandboxedSpawnRunner(
CommandEnvironment cmdEnv, Path sandboxBase, String productName, Duration timeoutKillDelay)
throws IOException {
- this(cmdEnv, sandboxBase, productName, Optional.of(timeoutKillDelay));
+ this(cmdEnv, sandboxBase, productName, Optional.of(timeoutKillDelay), null);
}
/**
@@ -137,12 +147,15 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
* @param productName the product name to use
* @param timeoutKillDelay an optional, additional grace period before killing timing out
* commands. If not present, then no grace period is used and commands are killed instantly.
+ * @param sandboxfsProcess instance of the sandboxfs process to use; may be null for none, in
+ * which case the runner uses a symlinked sandbox
*/
DarwinSandboxedSpawnRunner(
CommandEnvironment cmdEnv,
Path sandboxBase,
String productName,
- Optional<Duration> timeoutKillDelay)
+ Optional<Duration> timeoutKillDelay,
+ @Nullable SandboxfsProcess sandboxfsProcess)
throws IOException {
super(cmdEnv, sandboxBase);
this.execRoot = cmdEnv.getExecRoot();
@@ -153,6 +166,7 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
this.localEnvProvider =
new XcodeLocalEnvProvider(cmdEnv.getRuntime().getProductName(), cmdEnv.getClientEnv());
this.timeoutKillDelay = timeoutKillDelay;
+ this.sandboxfsProcess = sandboxfsProcess;
}
private static void addPathToSetIfExists(FileSystem fs, Set<Path> paths, String path)
@@ -200,7 +214,7 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
*/
private static String getConfStr(String confVar) throws IOException {
String[] commandArr = new String[2];
- commandArr[0] = "/usr/bin/getconf";
+ commandArr[0] = getconfBinary;
commandArr[1] = confVar;
Command cmd = new Command(commandArr);
CommandResult res;
@@ -219,9 +233,13 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
Path sandboxPath = getSandboxRoot();
Path sandboxExecRoot = sandboxPath.getRelative("execroot").getRelative(execRoot.getBaseName());
- // Each sandboxed action runs in its own execroot, so we don't need to make the temp directory's
+ // Each sandboxed action runs in its own directory so we don't need to make the temp directory's
// name unique (like we have to with standalone execution strategy).
- Path tmpDir = sandboxExecRoot.getRelative("tmp");
+ //
+ // Note that, for sandboxfs-based executions, this temp directory lives outside of the sandboxfs
+ // instance. This is perfectly fine (because sandbox-exec controls accesses to this directory)
+ // and is actually desirable for performance reasons.
+ Path tmpDir = sandboxPath.getRelative("tmp");
Map<String, String> environment =
localEnvProvider.rewriteLocalEnv(spawn.getEnvironment(), execRoot, tmpDir.getPathString());
@@ -253,33 +271,60 @@ final class DarwinSandboxedSpawnRunner extends AbstractSandboxSpawnRunner {
ImmutableList<String> commandLine =
ImmutableList.<String>builder()
- .add(SANDBOX_EXEC)
+ .add(sandboxExecBinary)
.add("-f")
.add(sandboxConfigPath.getPathString())
.addAll(processWrapperCommandLineBuilder.build())
.build();
boolean allowNetworkForThisSpawn = allowNetwork || Spawns.requiresNetwork(spawn);
- SandboxedSpawn sandbox =
- new SymlinkedSandboxedSpawn(
- sandboxPath,
- sandboxExecRoot,
- commandLine,
- environment,
- SandboxHelpers.getInputFiles(spawn, policy, execRoot),
- outputs,
- writableDirs) {
- @Override
- public void createFileSystem() throws IOException {
- super.createFileSystem();
- writeConfig(
- sandboxConfigPath,
- writableDirs,
- getInaccessiblePaths(),
- allowNetworkForThisSpawn,
- statisticsPath);
- }
- };
+
+ Map<PathFragment, Path> inputs = SandboxHelpers.getInputFiles(spawn, policy, execRoot);
+
+ SandboxedSpawn sandbox;
+ if (sandboxfsProcess != null) {
+ sandbox =
+ new SandboxfsSandboxedSpawn(
+ sandboxfsProcess,
+ sandboxPath,
+ commandLine,
+ environment,
+ inputs,
+ outputs,
+ ImmutableSet.of()) {
+ @Override
+ public void createFileSystem() throws IOException {
+ super.createFileSystem();
+ writeConfig(
+ sandboxConfigPath,
+ writableDirs,
+ getInaccessiblePaths(),
+ allowNetworkForThisSpawn,
+ statisticsPath);
+ }
+ };
+ } else {
+ sandbox =
+ new SymlinkedSandboxedSpawn(
+ sandboxPath,
+ sandboxExecRoot,
+ commandLine,
+ environment,
+ inputs,
+ outputs,
+ writableDirs) {
+ @Override
+ public void createFileSystem() throws IOException {
+ super.createFileSystem();
+ writeConfig(
+ sandboxConfigPath,
+ writableDirs,
+ getInaccessiblePaths(),
+ allowNetworkForThisSpawn,
+ statisticsPath);
+ }
+ };
+ }
return runSpawn(spawn, sandbox, policy, execRoot, tmpDir, timeout, statisticsPath);
}
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxActionContextProvider.java
index 9067ba42e5..37b100cf6d 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxActionContextProvider.java
@@ -84,11 +84,11 @@ final class SandboxActionContextProvider extends ActionContextProvider {
// This is the preferred sandboxing strategy on macOS.
if (DarwinSandboxedSpawnRunner.isSupported(cmdEnv)) {
- // TODO(jmmv): Inject process into spawn runner.
SpawnRunner spawnRunner =
withFallback(
cmdEnv,
- new DarwinSandboxedSpawnRunner(cmdEnv, sandboxBase, productName, timeoutKillDelay));
+ new DarwinSandboxedSpawnRunner(cmdEnv, sandboxBase, productName, timeoutKillDelay,
+ process));
contexts.add(new DarwinSandboxedStrategy(cmdEnv.getExecRoot(), spawnRunner));
}