aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Philipp Wollermann <philwo@google.com>2017-03-24 21:26:02 +0000
committerGravatar Philipp Wollermann <philwo@google.com>2017-03-27 11:36:36 +0000
commit21c1073612760a0f011257197b98152e3356d7ae (patch)
tree6d2352e3d990b71fd50e9c14f0435a12e49961aa
parent6f1d60839c6dc16d7e8b9d5c0d85acadc3fab1f6 (diff)
sandbox: Enable the process-wrapper + symlink tree sandbox on FreeBSD.
Extract the process-wrapper + symlink tree sandbox strategy into its own class and allow its use in FreeBSD. RELNOTES: Bazel can now use the process-wrapper + symlink tree based sandbox implementation in FreeBSD. -- PiperOrigin-RevId: 151171652 MOS_MIGRATED_REVID=151171652
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java42
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperRunner.java20
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedStrategy.java126
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/SandboxActionContextProvider.java24
4 files changed, 163 insertions, 49 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java b/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java
index 8825025ebf..22a980bc07 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java
@@ -47,14 +47,8 @@ import java.util.concurrent.atomic.AtomicReference;
contextType = SpawnActionContext.class
)
public class LinuxSandboxedStrategy extends SandboxStrategy {
- private static Boolean sandboxingSupported = null;
-
public static boolean isSupported(CommandEnvironment env) {
- if (sandboxingSupported == null) {
- sandboxingSupported =
- ProcessWrapperRunner.isSupported(env) || LinuxSandboxRunner.isSupported(env);
- }
- return sandboxingSupported.booleanValue();
+ return LinuxSandboxRunner.isSupported(env);
}
private final SandboxOptions sandboxOptions;
@@ -62,7 +56,6 @@ public class LinuxSandboxedStrategy extends SandboxStrategy {
private final Path execRoot;
private final boolean verboseFailures;
private final String productName;
- private final boolean fullySupported;
private final UUID uuid = UUID.randomUUID();
private final AtomicInteger execCounter = new AtomicInteger();
@@ -71,8 +64,7 @@ public class LinuxSandboxedStrategy extends SandboxStrategy {
BuildRequest buildRequest,
BlazeDirectories blazeDirs,
boolean verboseFailures,
- String productName,
- boolean fullySupported) {
+ String productName) {
super(
buildRequest,
blazeDirs,
@@ -83,7 +75,6 @@ public class LinuxSandboxedStrategy extends SandboxStrategy {
this.execRoot = blazeDirs.getExecRoot();
this.verboseFailures = verboseFailures;
this.productName = productName;
- this.fullySupported = fullySupported;
}
@Override
@@ -113,7 +104,17 @@ public class LinuxSandboxedStrategy extends SandboxStrategy {
throw new UserExecException("I/O error during sandboxed execution", e);
}
- SandboxRunner runner = getSandboxRunner(sandboxPath, sandboxExecRoot, writableDirs);
+ SandboxRunner runner =
+ new LinuxSandboxRunner(
+ execRoot,
+ sandboxPath,
+ sandboxExecRoot,
+ writableDirs,
+ getTmpfsPaths(),
+ getReadOnlyBindMounts(blazeDirs, sandboxExecRoot),
+ verboseFailures,
+ sandboxOptions.sandboxDebug);
+
try {
runSpawn(
spawn,
@@ -140,23 +141,6 @@ public class LinuxSandboxedStrategy extends SandboxStrategy {
}
}
- private SandboxRunner getSandboxRunner(
- Path sandboxPath, Path sandboxExecRoot, Set<Path> writableDirs) throws UserExecException {
- if (fullySupported) {
- return new LinuxSandboxRunner(
- execRoot,
- sandboxPath,
- sandboxExecRoot,
- writableDirs,
- getTmpfsPaths(),
- getReadOnlyBindMounts(blazeDirs, sandboxExecRoot),
- verboseFailures,
- sandboxOptions.sandboxDebug);
- } else {
- return new ProcessWrapperRunner(execRoot, sandboxExecRoot, verboseFailures);
- }
- }
-
@Override
protected ImmutableSet<Path> getWritableDirs(Path sandboxExecRoot, Map<String, String> env)
throws IOException {
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperRunner.java
index f3ee9d14d1..1d6271925f 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperRunner.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperRunner.java
@@ -18,7 +18,6 @@ import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.shell.Command;
import com.google.devtools.build.lib.util.OsUtils;
import com.google.devtools.build.lib.vfs.Path;
-import com.google.devtools.build.lib.vfs.PathFragment;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -28,28 +27,21 @@ import java.util.Map;
* platforms and gives at least some isolation between running actions.
*/
final class ProcessWrapperRunner extends SandboxRunner {
+ private static final String PROCESS_WRAPPER = "process-wrapper" + OsUtils.executableExtension();
+
private final Path execRoot;
private final Path sandboxExecRoot;
- ProcessWrapperRunner(
- Path execRoot, Path sandboxExecRoot, boolean verboseFailures) {
+ ProcessWrapperRunner(Path execRoot, Path sandboxExecRoot, boolean verboseFailures) {
super(verboseFailures);
this.execRoot = execRoot;
this.sandboxExecRoot = sandboxExecRoot;
}
static boolean isSupported(CommandEnvironment commandEnv) {
- PathFragment embeddedTool =
- commandEnv
- .getBlazeWorkspace()
- .getBinTools()
- .getExecPath("process-wrapper" + OsUtils.executableExtension());
- if (embeddedTool == null) {
- // The embedded tool does not exist, meaning that we don't support sandboxing (e.g., while
- // bootstrapping).
- return false;
- }
- return true;
+ // We can only use this runner, if the process-wrapper exists in the embedded tools.
+ // This might not always be the case, e.g. while bootstrapping.
+ return commandEnv.getBlazeWorkspace().getBinTools().getExecPath(PROCESS_WRAPPER) != null;
}
@Override
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedStrategy.java b/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedStrategy.java
new file mode 100644
index 0000000000..f7b310a2fe
--- /dev/null
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedStrategy.java
@@ -0,0 +1,126 @@
+// Copyright 2017 The Bazel Authors. 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.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.devtools.build.lib.sandbox;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionStatusMessage;
+import com.google.devtools.build.lib.actions.ExecException;
+import com.google.devtools.build.lib.actions.ExecutionStrategy;
+import com.google.devtools.build.lib.actions.Executor;
+import com.google.devtools.build.lib.actions.Spawn;
+import com.google.devtools.build.lib.actions.SpawnActionContext;
+import com.google.devtools.build.lib.actions.UserExecException;
+import com.google.devtools.build.lib.analysis.BlazeDirectories;
+import com.google.devtools.build.lib.buildtool.BuildRequest;
+import com.google.devtools.build.lib.events.Event;
+import com.google.devtools.build.lib.runtime.CommandEnvironment;
+import com.google.devtools.build.lib.vfs.FileSystemUtils;
+import com.google.devtools.build.lib.vfs.Path;
+import com.google.devtools.build.lib.vfs.PathFragment;
+import java.io.IOException;
+import java.util.Set;
+import java.util.UUID;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+
+/** Strategy that uses sandboxing to execute a process. */
+@ExecutionStrategy(
+ name = {"sandboxed"},
+ contextType = SpawnActionContext.class
+)
+public class ProcessWrapperSandboxedStrategy extends SandboxStrategy {
+ public static boolean isSupported(CommandEnvironment env) {
+ return ProcessWrapperRunner.isSupported(env);
+ }
+
+ private final SandboxOptions sandboxOptions;
+ private final BlazeDirectories blazeDirs;
+ private final Path execRoot;
+ private final boolean verboseFailures;
+ private final String productName;
+
+ private final UUID uuid = UUID.randomUUID();
+ private final AtomicInteger execCounter = new AtomicInteger();
+
+ ProcessWrapperSandboxedStrategy(
+ BuildRequest buildRequest,
+ BlazeDirectories blazeDirs,
+ boolean verboseFailures,
+ String productName) {
+ super(buildRequest, blazeDirs, verboseFailures, buildRequest.getOptions(SandboxOptions.class));
+ this.sandboxOptions = buildRequest.getOptions(SandboxOptions.class);
+ this.blazeDirs = blazeDirs;
+ this.execRoot = blazeDirs.getExecRoot();
+ this.verboseFailures = verboseFailures;
+ this.productName = productName;
+ }
+
+ @Override
+ protected void actuallyExec(
+ Spawn spawn,
+ ActionExecutionContext actionExecutionContext,
+ AtomicReference<Class<? extends SpawnActionContext>> writeOutputFiles)
+ throws ExecException, InterruptedException {
+ Executor executor = actionExecutionContext.getExecutor();
+ executor
+ .getEventBus()
+ .post(
+ ActionStatusMessage.runningStrategy(
+ spawn.getResourceOwner(), "processwrapper-sandbox"));
+ SandboxHelpers.reportSubcommand(executor, spawn);
+
+ // Each invocation of "exec" gets its own sandbox.
+ Path sandboxPath = SandboxHelpers.getSandboxRoot(blazeDirs, productName, uuid, execCounter);
+ Path sandboxExecRoot = sandboxPath.getRelative("execroot").getRelative(execRoot.getBaseName());
+
+ Set<Path> writableDirs;
+ SymlinkedExecRoot symlinkedExecRoot = new SymlinkedExecRoot(sandboxExecRoot);
+ ImmutableSet<PathFragment> outputs = SandboxHelpers.getOutputFiles(spawn);
+ try {
+ writableDirs = getWritableDirs(sandboxExecRoot, spawn.getEnvironment());
+ symlinkedExecRoot.createFileSystem(
+ getMounts(spawn, actionExecutionContext), outputs, writableDirs);
+ } catch (IOException e) {
+ throw new UserExecException("I/O error during sandboxed execution", e);
+ }
+
+ SandboxRunner runner = new ProcessWrapperRunner(execRoot, sandboxExecRoot, verboseFailures);
+ try {
+ runSpawn(
+ spawn,
+ actionExecutionContext,
+ spawn.getEnvironment(),
+ symlinkedExecRoot,
+ outputs,
+ runner,
+ writeOutputFiles);
+ } finally {
+ if (!sandboxOptions.sandboxDebug) {
+ try {
+ FileSystemUtils.deleteTree(sandboxPath);
+ } catch (IOException e) {
+ executor
+ .getEventHandler()
+ .handle(
+ Event.warn(
+ String.format(
+ "Cannot delete sandbox directory after action execution: %s (%s)",
+ sandboxPath.getPathString(), e)));
+ }
+ }
+ }
+ }
+}
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 d27bd5517f..26bf01ec69 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
@@ -49,18 +49,22 @@ final class SandboxActionContextProvider extends ActionContextProvider {
switch (OS.getCurrent()) {
case LINUX:
if (LinuxSandboxedStrategy.isSupported(env)) {
- boolean fullySupported = LinuxSandboxRunner.isSupported(env);
- if (!fullySupported
- && !buildRequest.getOptions(SandboxOptions.class).ignoreUnsupportedSandboxing) {
+ contexts.add(
+ new LinuxSandboxedStrategy(
+ buildRequest,
+ env.getDirectories(),
+ verboseFailures,
+ env.getRuntime().getProductName()));
+ } else {
+ if (!buildRequest.getOptions(SandboxOptions.class).ignoreUnsupportedSandboxing) {
env.getReporter().handle(Event.warn(SANDBOX_NOT_SUPPORTED_MESSAGE));
}
contexts.add(
- new LinuxSandboxedStrategy(
+ new ProcessWrapperSandboxedStrategy(
buildRequest,
env.getDirectories(),
verboseFailures,
- env.getRuntime().getProductName(),
- fullySupported));
+ env.getRuntime().getProductName()));
}
break;
case DARWIN:
@@ -78,6 +82,14 @@ final class SandboxActionContextProvider extends ActionContextProvider {
}
}
break;
+ case FREEBSD:
+ contexts.add(
+ new ProcessWrapperSandboxedStrategy(
+ buildRequest,
+ env.getDirectories(),
+ verboseFailures,
+ env.getRuntime().getProductName()));
+ break;
default:
// No sandboxing available.
}