Skip to content

Commit 70691f2

Browse files
lberkicopybara-github
authored andcommitted
Make the Linux sandbox work with ActionInputs with absolute "exec paths".
Progress towards #3236. RELNOTES: None. PiperOrigin-RevId: 493542957 Change-Id: Iff396e77d7624bdb033b198068aa137397495db0
1 parent 0e8de27 commit 70691f2

File tree

8 files changed

+86
-11
lines changed

8 files changed

+86
-11
lines changed

src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedSpawnRunner.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,11 @@ protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context
232232

233233
SandboxInputs inputs =
234234
helpers.processInputFiles(
235-
context.getInputMapping(PathFragment.EMPTY_FRAGMENT), execRoot, execRoot, null);
235+
context.getInputMapping(PathFragment.EMPTY_FRAGMENT),
236+
execRoot,
237+
execRoot,
238+
ImmutableList.of(),
239+
null);
236240
SandboxOutputs outputs = helpers.getOutputs(spawn);
237241

238242
final Path sandboxConfigPath = sandboxPath.getRelative("sandbox.sb");

src/main/java/com/google/devtools/build/lib/sandbox/DockerSandboxedSpawnRunner.java

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context
222222

223223
SandboxInputs inputs =
224224
helpers.processInputFiles(
225-
context.getInputMapping(PathFragment.EMPTY_FRAGMENT), execRoot, execRoot, null);
225+
context.getInputMapping(PathFragment.EMPTY_FRAGMENT),
226+
execRoot,
227+
execRoot,
228+
ImmutableList.of(),
229+
null);
226230
SandboxOutputs outputs = helpers.getOutputs(spawn);
227231

228232
Duration timeout = context.getTimeout();

src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
import com.google.devtools.build.lib.vfs.FileSystem;
4949
import com.google.devtools.build.lib.vfs.Path;
5050
import com.google.devtools.build.lib.vfs.PathFragment;
51+
import com.google.devtools.build.lib.vfs.Root;
5152
import com.google.devtools.build.lib.vfs.Symlinks;
5253
import java.io.File;
5354
import java.io.IOException;
@@ -128,6 +129,7 @@ private static boolean computeIsSupported(CommandEnvironment cmdEnv, Path linuxS
128129
private final boolean sandboxfsMapSymlinkTargets;
129130
private final TreeDeleter treeDeleter;
130131
private final Reporter reporter;
132+
private final ImmutableList<Root> packageRoots;
131133

132134
/**
133135
* Creates a sandboxed spawn runner that uses the {@code linux-sandbox} tool.
@@ -168,6 +170,7 @@ private static boolean computeIsSupported(CommandEnvironment cmdEnv, Path linuxS
168170
this.localEnvProvider = new PosixLocalEnvProvider(cmdEnv.getClientEnv());
169171
this.treeDeleter = treeDeleter;
170172
this.reporter = cmdEnv.getReporter();
173+
this.packageRoots = cmdEnv.getPackageLocator().getPathEntries();
171174
}
172175

173176
@Override
@@ -219,7 +222,11 @@ protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context
219222

220223
SandboxInputs inputs =
221224
helpers.processInputFiles(
222-
context.getInputMapping(PathFragment.EMPTY_FRAGMENT), execRoot, execRoot, null);
225+
context.getInputMapping(PathFragment.EMPTY_FRAGMENT),
226+
execRoot,
227+
execRoot,
228+
packageRoots,
229+
null);
223230
SandboxOutputs outputs = helpers.getOutputs(spawn);
224231

225232
Duration timeout = context.getTimeout();

src/main/java/com/google/devtools/build/lib/sandbox/ProcessWrapperSandboxedSpawnRunner.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
package com.google.devtools.build.lib.sandbox;
1616

17+
import com.google.common.collect.ImmutableList;
1718
import com.google.common.collect.ImmutableMap;
1819
import com.google.common.collect.ImmutableSet;
1920
import com.google.devtools.build.lib.actions.ForbiddenActionInputException;
@@ -111,7 +112,11 @@ protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context
111112

112113
SandboxInputs inputs =
113114
helpers.processInputFiles(
114-
context.getInputMapping(PathFragment.EMPTY_FRAGMENT), execRoot, execRoot, null);
115+
context.getInputMapping(PathFragment.EMPTY_FRAGMENT),
116+
execRoot,
117+
execRoot,
118+
ImmutableList.of(),
119+
null);
115120
SandboxOutputs outputs = helpers.getOutputs(spawn);
116121

117122
if (sandboxfsProcess != null) {

src/main/java/com/google/devtools/build/lib/sandbox/SandboxHelpers.java

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import com.google.auto.value.AutoValue;
2222
import com.google.common.base.Preconditions;
23+
import com.google.common.collect.ImmutableList;
2324
import com.google.common.collect.ImmutableMap;
2425
import com.google.common.collect.ImmutableSet;
2526
import com.google.common.collect.Iterables;
@@ -461,16 +462,50 @@ private static byte[] writeVirtualInputTo(VirtualActionInput input, Path target)
461462
return digest;
462463
}
463464

465+
/**
466+
* Returns the appropriate {@link RootedPath} for a Fileset symlink.
467+
*
468+
* <p>Filesets are weird because sometimes exec paths of the {@link ActionInput}s in them are not
469+
* relative, as exec paths should be, but absolute and point to under one of the package roots. In
470+
* order to handle this, if we find such an absolute exec path, we iterate over the package path
471+
* entries to turn it into a {@link RootedPath}.
472+
*
473+
* <p>The inputs to this function should be symlinks that are contained within Filesets; in
474+
* particular, this is different from "unresolved symlinks" in that Fileset contents are regular
475+
* files (but implemented by symlinks in the output tree) whose contents matter and unresolved
476+
* symlinks are symlinks for which the important content is the result of {@code readlink()}
477+
*/
478+
private static RootedPath processFilesetSymlink(
479+
PathFragment symlink, ImmutableList<Root> packageRoots) {
480+
for (Root packageRoot : packageRoots) {
481+
if (packageRoot.contains(symlink)) {
482+
return RootedPath.toRootedPath(packageRoot, packageRoot.relativize(symlink));
483+
}
484+
}
485+
486+
throw new IllegalStateException(
487+
String.format(
488+
"absolute action input path '%s' not found under package roots",
489+
symlink.getPathString()));
490+
}
491+
464492
/**
465493
* Returns the inputs of a Spawn as a map of PathFragments relative to an execRoot to paths in the
466494
* host filesystem where the input files can be found.
467495
*
496+
* @param inputMap the map of action inputs and where they should be visible in the action
497+
* @param execRootPath the exec root from the point of view of the Bazel server
498+
* @param withinSandboxExecRootPath the exec root from within the sandbox (different from {@code
499+
* execRootPath} because the sandbox does magic with fiile system namespaces)
500+
* @param packageRoots the package path entries during this build
501+
* @param sandboxSourceRoots the directory where source roots are mapped within the sandbox
468502
* @throws IOException if processing symlinks fails
469503
*/
470504
public SandboxInputs processInputFiles(
471505
Map<PathFragment, ActionInput> inputMap,
472506
Path execRootPath,
473507
Path withinSandboxExecRootPath,
508+
ImmutableList<Root> packageRoots,
474509
Path sandboxSourceRoots)
475510
throws IOException {
476511
Root withinSandboxExecRoot = Root.fromPath(withinSandboxExecRootPath);
@@ -503,7 +538,14 @@ public SandboxInputs processInputFiles(
503538
if (actionInput instanceof EmptyActionInput) {
504539
inputPath = null;
505540
} else {
506-
inputPath = RootedPath.toRootedPath(execRoot, actionInput.getExecPath());
541+
PathFragment execPath = actionInput.getExecPath();
542+
if (execPath.isAbsolute()) {
543+
// This happens for ActionInputs that are part of Filesets (see the Javadoc on
544+
// processFilesetSymlink())
545+
inputPath = processFilesetSymlink(actionInput.getExecPath(), packageRoots);
546+
} else {
547+
inputPath = RootedPath.toRootedPath(execRoot, actionInput.getExecPath());
548+
}
507549
}
508550

509551
inputFiles.put(pathFragment, inputPath);

src/main/java/com/google/devtools/build/lib/sandbox/WindowsSandboxedSpawnRunner.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.google.devtools.build.lib.sandbox;
1616

1717
import com.google.common.base.Joiner;
18+
import com.google.common.collect.ImmutableList;
1819
import com.google.common.collect.ImmutableMap;
1920
import com.google.common.collect.ImmutableSet;
2021
import com.google.devtools.build.lib.actions.ActionInput;
@@ -71,7 +72,11 @@ protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context
7172

7273
SandboxInputs readablePaths =
7374
helpers.processInputFiles(
74-
context.getInputMapping(PathFragment.EMPTY_FRAGMENT), execRoot, execRoot, null);
75+
context.getInputMapping(PathFragment.EMPTY_FRAGMENT),
76+
execRoot,
77+
execRoot,
78+
ImmutableList.of(),
79+
null);
7580

7681
ImmutableSet.Builder<Path> writablePaths = ImmutableSet.builder();
7782
writablePaths.addAll(getWritableDirs(execRoot, environment));

src/main/java/com/google/devtools/build/lib/worker/WorkerSpawnRunner.java

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import com.google.common.annotations.VisibleForTesting;
2121
import com.google.common.base.Stopwatch;
22+
import com.google.common.collect.ImmutableList;
2223
import com.google.common.collect.ImmutableMap;
2324
import com.google.common.hash.HashCode;
2425
import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
@@ -187,7 +188,11 @@ public SpawnResult exec(Spawn spawn, SpawnExecutionContext context)
187188
Profiler.instance().profile(ProfilerTask.WORKER_SETUP, "Setting up inputs")) {
188189
inputFiles =
189190
helpers.processInputFiles(
190-
context.getInputMapping(PathFragment.EMPTY_FRAGMENT), execRoot, execRoot, null);
191+
context.getInputMapping(PathFragment.EMPTY_FRAGMENT),
192+
execRoot,
193+
execRoot,
194+
ImmutableList.of(),
195+
null);
191196
}
192197
SandboxOutputs outputs = helpers.getOutputs(spawn);
193198

src/test/java/com/google/devtools/build/lib/sandbox/SandboxHelpersTest.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,8 @@ public void processInputFiles_materializesParamFile() throws Exception {
101101
UTF_8);
102102

103103
SandboxInputs inputs =
104-
sandboxHelpers.processInputFiles(inputMap(paramFile), execRootPath, execRootPath, null);
104+
sandboxHelpers.processInputFiles(
105+
inputMap(paramFile), execRootPath, execRootPath, ImmutableList.of(), null);
105106

106107
assertThat(inputs.getFiles())
107108
.containsExactly(PathFragment.create("paramFile"), execRootedPath("paramFile"));
@@ -121,7 +122,8 @@ public void processInputFiles_materializesBinToolsFile() throws Exception {
121122
PathFragment.create("_bin/say_hello"));
122123

123124
SandboxInputs inputs =
124-
sandboxHelpers.processInputFiles(inputMap(tool), execRootPath, execRootPath, null);
125+
sandboxHelpers.processInputFiles(
126+
inputMap(tool), execRootPath, execRootPath, ImmutableList.of(), null);
125127

126128
assertThat(inputs.getFiles())
127129
.containsExactly(PathFragment.create("_bin/say_hello"), execRootedPath("_bin/say_hello"));
@@ -167,14 +169,15 @@ protected void setExecutable(PathFragment path, boolean executable) throws IOExc
167169
try {
168170
var unused =
169171
sandboxHelpers.processInputFiles(
170-
inputMap(input), customExecRoot, customExecRoot, null);
172+
inputMap(input), customExecRoot, customExecRoot, ImmutableList.of(), null);
171173
finishProcessingSemaphore.release();
172174
} catch (IOException e) {
173175
throw new IllegalArgumentException(e);
174176
}
175177
});
176178
var unused =
177-
sandboxHelpers.processInputFiles(inputMap(input), customExecRoot, customExecRoot, null);
179+
sandboxHelpers.processInputFiles(
180+
inputMap(input), customExecRoot, customExecRoot, ImmutableList.of(), null);
178181
finishProcessingSemaphore.release();
179182
future.get();
180183

0 commit comments

Comments
 (0)