diff options
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java')
-rw-r--r-- | src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedStrategy.java | 74 |
1 files changed, 67 insertions, 7 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 b4ed542ab1..dc4578ef61 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 @@ -14,7 +14,9 @@ package com.google.devtools.build.lib.sandbox; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; +import com.google.common.collect.Maps; import com.google.devtools.build.lib.actions.ActionExecutionContext; import com.google.devtools.build.lib.actions.ExecException; import com.google.devtools.build.lib.actions.ExecutionStrategy; @@ -31,6 +33,7 @@ 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.SortedMap; import java.util.UUID; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; @@ -149,7 +152,8 @@ public class LinuxSandboxedStrategy extends SandboxStrategy { } private SandboxRunner getSandboxRunner( - Spawn spawn, Path sandboxPath, Path sandboxExecRoot, Path sandboxTempDir) { + Spawn spawn, Path sandboxPath, Path sandboxExecRoot, Path sandboxTempDir) + throws UserExecException { if (fullySupported) { return new LinuxSandboxRunner( execRoot, @@ -159,7 +163,7 @@ public class LinuxSandboxedStrategy extends SandboxStrategy { getWritableDirs(sandboxExecRoot, spawn.getEnvironment()), getInaccessiblePaths(), getTmpfsPaths(), - getBindMounts(blazeDirs), + getReadOnlyBindMounts(blazeDirs, sandboxExecRoot), verboseFailures, sandboxOptions.sandboxDebug); } else { @@ -175,15 +179,71 @@ public class LinuxSandboxedStrategy extends SandboxStrategy { return tmpfsPaths.build(); } - private ImmutableSet<Path> getBindMounts(BlazeDirectories blazeDirs) { + private SortedMap<Path, Path> getReadOnlyBindMounts( + BlazeDirectories blazeDirs, Path sandboxExecRoot) throws UserExecException { Path tmpPath = blazeDirs.getFileSystem().getPath("/tmp"); - ImmutableSet.Builder<Path> bindMounts = ImmutableSet.builder(); + final SortedMap<Path, Path> bindMounts = Maps.newTreeMap(); if (blazeDirs.getWorkspace().startsWith(tmpPath)) { - bindMounts.add(blazeDirs.getWorkspace()); + bindMounts.put(blazeDirs.getWorkspace(), blazeDirs.getWorkspace()); } if (blazeDirs.getOutputBase().startsWith(tmpPath)) { - bindMounts.add(blazeDirs.getOutputBase()); + bindMounts.put(blazeDirs.getOutputBase(), blazeDirs.getOutputBase()); + } + for (ImmutableMap.Entry<String, String> additionalMountPath : + sandboxOptions.sandboxAdditionalMounts) { + try { + final Path mountTarget = blazeDirs.getFileSystem().getPath(additionalMountPath.getValue()); + // If source path is relative, treat it as a relative path inside the execution root + final Path mountSource = sandboxExecRoot.getRelative(additionalMountPath.getKey()); + // If a target has more than one source path, the latter one will take effect. + bindMounts.put(mountTarget, mountSource); + } catch (IllegalArgumentException e) { + throw new UserExecException( + String.format("Error occurred when analyzing bind mount pairs. %s", e.getMessage())); + } + } + validateBindMounts(bindMounts); + return bindMounts; + } + + /** + * This method does the following things: - If mount source does not exist on the host system, + * throw an error message - If mount target exists, check whether the source and target are of the + * same type - If mount target does not exist on the host system, throw an error message + * + * @param bindMounts the bind mounts map with target as key and source as value + * @throws UserExecException + */ + private void validateBindMounts(SortedMap<Path, Path> bindMounts) throws UserExecException { + for (SortedMap.Entry<Path, Path> bindMount : bindMounts.entrySet()) { + final Path source = bindMount.getValue(); + final Path target = bindMount.getKey(); + // Mount source should exist in the file system + if (!source.exists()) { + throw new UserExecException(String.format("Mount source '%s' does not exist.", source)); + } + // If target exists, but is not of the same type as the source, then we cannot mount it. + if (target.exists()) { + boolean areBothDirectories = source.isDirectory() && target.isDirectory(); + boolean isSourceFile = source.isFile() || source.isSymbolicLink(); + boolean isTargetFile = target.isFile() || target.isSymbolicLink(); + boolean areBothFiles = isSourceFile && isTargetFile; + if (!(areBothDirectories || areBothFiles)) { + // Source and target are not of the same type; we cannot mount it. + throw new UserExecException( + String.format( + "Mount target '%s' is not of the same type as mount source '%s'.", + target, source)); + } + } else { + // Mount target should exist in the file system + throw new UserExecException( + String.format( + "Mount target '%s' does not exist. Bazel only supports bind mounting on top of " + + "existing files/directories. Please create an empty file or directory at " + + "the mount target path according to the type of mount source.", + target)); + } } - return bindMounts.build(); } } |