diff options
7 files changed, 471 insertions, 86 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/runtime/LinuxSandboxUtil.java b/src/main/java/com/google/devtools/build/lib/runtime/LinuxSandboxUtil.java new file mode 100644 index 0000000000..97d6427400 --- /dev/null +++ b/src/main/java/com/google/devtools/build/lib/runtime/LinuxSandboxUtil.java @@ -0,0 +1,264 @@ +// 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.runtime; + +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; +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.time.Duration; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +/** Utility functions for the {@code linux-sandbox} embedded tool. */ +public final class LinuxSandboxUtil { + private static final String LINUX_SANDBOX = "linux-sandbox" + OsUtils.executableExtension(); + + /** Returns whether using the {@code linux-sandbox} is supported in the command environment. */ + public static boolean isSupported(CommandEnvironment cmdEnv) { + // We can only use the linux-sandbox if the linux-sandbox exists in the embedded tools. + // This might not always be the case, e.g. while bootstrapping. + return getLinuxSandbox(cmdEnv) != null; + } + + /** Returns the path of the {@code linux-sandbox} binary, or null if it doesn't exist. */ + public static Path getLinuxSandbox(CommandEnvironment cmdEnv) { + PathFragment execPath = cmdEnv.getBlazeWorkspace().getBinTools().getExecPath(LINUX_SANDBOX); + return execPath != null ? cmdEnv.getExecRoot().getRelative(execPath) : null; + } + + /** Returns a new command line builder for the {@code linux-sandbox} tool. */ + public static CommandLineBuilder commandLineBuilder( + String linuxSandboxPath, Collection<String> commandArguments) { + return new CommandLineBuilder() + .setLinuxSandboxPath(linuxSandboxPath) + .setCommandArguments(commandArguments); + } + + /** + * A builder class for constructing the full command line to run a command using the {@code + * linux-sandbox} tool. + */ + public static class CommandLineBuilder { + // TODO(b/62588075): Reconsider using Path/PathFragment instead of Strings for file paths. + private Optional<String> linuxSandboxPath = Optional.empty(); + private Optional<String> workingDirectory = Optional.empty(); + private Optional<Duration> timeout = Optional.empty(); + private Optional<Duration> killDelay = Optional.empty(); + private Optional<String> stdoutPath = Optional.empty(); + private Optional<String> stderrPath = Optional.empty(); + private Optional<Iterable<Path>> writableFilesAndDirectories = Optional.empty(); + private Optional<Iterable<Path>> tmpfsDirectories = Optional.empty(); + private Optional<Map<Path, Path>> bindMounts = Optional.empty(); + private Optional<String> statisticsPath = Optional.empty(); + private boolean useFakeHostname = false; + private boolean createNetworkNamespace = false; + private boolean useFakeRoot = false; + private boolean useFakeUsername = false; + private boolean useDebugMode = false; + private Optional<Collection<String>> commandArguments = Optional.empty(); + + private CommandLineBuilder() { + // Prevent external construction via "new". + } + + /** Sets the path of the {@code linux-sandbox} tool. */ + public CommandLineBuilder setLinuxSandboxPath(String linuxSandboxPath) { + this.linuxSandboxPath = Optional.of(linuxSandboxPath); + return this; + } + + /** Sets the working directory to use, if any. */ + public CommandLineBuilder setWorkingDirectory(String workingDirectory) { + this.workingDirectory = Optional.of(workingDirectory); + return this; + } + + /** Sets the timeout for the command run using the {@code linux-sandbox} tool. */ + public CommandLineBuilder setTimeout(Duration timeout) { + this.timeout = Optional.of(timeout); + return this; + } + + /** + * Sets the kill delay for commands run using the {@code linux-sandbox} tool that exceed their + * timeout. + */ + public CommandLineBuilder setKillDelay(Duration killDelay) { + this.killDelay = Optional.of(killDelay); + return this; + } + + /** Sets the path to use for redirecting stdout, if any. */ + public CommandLineBuilder setStdoutPath(String stdoutPath) { + this.stdoutPath = Optional.of(stdoutPath); + return this; + } + + /** Sets the path to use for redirecting stderr, if any. */ + public CommandLineBuilder setStderrPath(String stderrPath) { + this.stderrPath = Optional.of(stderrPath); + return this; + } + + /** Sets the files or directories to make writable for the sandboxed process, if any. */ + public CommandLineBuilder setWritableFilesAndDirectories( + Iterable<Path> writableFilesAndDirectories) { + this.writableFilesAndDirectories = Optional.of(writableFilesAndDirectories); + return this; + } + + /** Sets the directories where to mount an empty tmpfs, if any. */ + public CommandLineBuilder setTmpfsDirectories(Iterable<Path> tmpfsDirectories) { + this.tmpfsDirectories = Optional.of(tmpfsDirectories); + return this; + } + + /** + * Sets the sources and targets of files or directories to explicitly bind-mount in the sandbox, + * if any. + */ + public CommandLineBuilder setBindMounts(Map<Path, Path> bindMounts) { + this.bindMounts = Optional.of(bindMounts); + return this; + } + + /** Sets the path for writing execution statistics (e.g. resource usage). */ + public CommandLineBuilder setStatisticsPath(String statisticsPath) { + this.statisticsPath = Optional.of(statisticsPath); + return this; + } + + /** Sets whether to use a fake 'localhost' hostname inside the sandbox. */ + public CommandLineBuilder setUseFakeHostname(boolean useFakeHostname) { + this.useFakeHostname = useFakeHostname; + return this; + } + + /** Sets whether to create a new network namespace. */ + public CommandLineBuilder setCreateNetworkNamespace(boolean createNetworkNamespace) { + this.createNetworkNamespace = createNetworkNamespace; + return this; + } + + /** Sets whether to pretend to be 'root' inside the namespace. */ + public CommandLineBuilder setUseFakeRoot(boolean useFakeRoot) { + this.useFakeRoot = useFakeRoot; + return this; + } + + /** Sets whether to use a fake 'nobody' username inside the sandbox. */ + public CommandLineBuilder setUseFakeUsername(boolean useFakeUsername) { + this.useFakeUsername = useFakeUsername; + return this; + } + + /** Sets whether to enable debug mode (e.g. to print debugging messages). */ + public CommandLineBuilder setUseDebugMode(boolean useDebugMode) { + this.useDebugMode = useDebugMode; + return this; + } + + /** Sets the command (and its arguments) to run using the {@code linux-sandbox} tool. */ + public CommandLineBuilder setCommandArguments(Collection<String> commandArguments) { + this.commandArguments = Optional.of(commandArguments); + return this; + } + + /** + * Builds the command line to invoke a specific command using the {@code linux-sandbox} tool. + */ + public List<String> build() { + Preconditions.checkState(this.linuxSandboxPath.isPresent(), "linuxSandboxPath is required"); + Preconditions.checkState(this.commandArguments.isPresent(), "commandArguments are required"); + Preconditions.checkState( + !(this.useFakeUsername && this.useFakeRoot), + "useFakeUsername and useFakeRoot are exclusive"); + + ImmutableList.Builder<String> commandLineBuilder = ImmutableList.<String>builder(); + + commandLineBuilder.add(linuxSandboxPath.get()); + if (workingDirectory.isPresent()) { + commandLineBuilder.add("-W", workingDirectory.get()); + } + if (timeout.isPresent()) { + commandLineBuilder.add("-T", Long.toString(timeout.get().getSeconds())); + } + if (killDelay.isPresent()) { + commandLineBuilder.add("-t", Long.toString(killDelay.get().getSeconds())); + } + if (stdoutPath.isPresent()) { + commandLineBuilder.add("-l", stdoutPath.get()); + } + if (stderrPath.isPresent()) { + commandLineBuilder.add("-L", stderrPath.get()); + } + if (writableFilesAndDirectories.isPresent()) { + for (Path writablePath : writableFilesAndDirectories.get()) { + commandLineBuilder.add("-w", writablePath.getPathString()); + } + } + if (tmpfsDirectories.isPresent()) { + for (Path tmpfsPath : tmpfsDirectories.get()) { + commandLineBuilder.add("-e", tmpfsPath.getPathString()); + } + } + if (bindMounts.isPresent()) { + for (Path bindMountTarget : bindMounts.get().keySet()) { + Path bindMountSource = bindMounts.get().get(bindMountTarget); + commandLineBuilder.add("-M", bindMountSource.getPathString()); + // The file is mounted in a custom location inside the sandbox. + if (!bindMountSource.equals(bindMountTarget)) { + commandLineBuilder.add("-m", bindMountTarget.getPathString()); + } + } + } + if (statisticsPath.isPresent()) { + commandLineBuilder.add("-S", statisticsPath.get()); + } + if (useFakeHostname) { + commandLineBuilder.add("-H"); + } + if (createNetworkNamespace) { + commandLineBuilder.add("-N"); + } + if (useFakeRoot) { + commandLineBuilder.add("-R"); + } + if (useFakeUsername) { + commandLineBuilder.add("-U"); + } + if (useDebugMode) { + commandLineBuilder.add("-D"); + } + commandLineBuilder.add("--"); + commandLineBuilder.addAll(commandArguments.get()); + + return commandLineBuilder.build(); + } + + /** + * Builds the command line to invoke a specific command using the {@code linux-sandbox} tool. + * + * @return the command line as an array of strings + */ + public String[] buildAsArray() { + return build().toArray(new String[0]); + } + } +} diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java b/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java index a16497febc..00caa70d64 100644 --- a/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java +++ b/src/main/java/com/google/devtools/build/lib/sandbox/LinuxSandboxedSpawnRunner.java @@ -14,6 +14,7 @@ package com.google.devtools.build.lib.sandbox; +import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Maps; @@ -27,6 +28,7 @@ import com.google.devtools.build.lib.actions.UserExecException; import com.google.devtools.build.lib.analysis.BlazeDirectories; import com.google.devtools.build.lib.exec.local.LocalEnvProvider; import com.google.devtools.build.lib.runtime.CommandEnvironment; +import com.google.devtools.build.lib.runtime.LinuxSandboxUtil; import com.google.devtools.build.lib.shell.Command; import com.google.devtools.build.lib.shell.CommandException; import com.google.devtools.build.lib.util.OS; @@ -37,7 +39,6 @@ import com.google.devtools.build.lib.vfs.Symlinks; import java.io.File; import java.io.IOException; import java.time.Duration; -import java.util.ArrayList; import java.util.List; import java.util.Map; import java.util.Set; @@ -45,30 +46,25 @@ import java.util.SortedMap; /** Spawn runner that uses linux sandboxing APIs to execute a local subprocess. */ final class LinuxSandboxedSpawnRunner extends AbstractSandboxSpawnRunner { - private static final String LINUX_SANDBOX = "linux-sandbox"; public static boolean isSupported(CommandEnvironment cmdEnv) { if (OS.getCurrent() != OS.LINUX) { return false; } - Path embeddedTool = getLinuxSandbox(cmdEnv); - if (embeddedTool == null) { - // The embedded tool does not exist, meaning that we don't support sandboxing (e.g., while - // bootstrapping). + if (!LinuxSandboxUtil.isSupported(cmdEnv)) { return false; } - Path execRoot = cmdEnv.getExecRoot(); - - List<String> args = new ArrayList<>(); - args.add(embeddedTool.getPathString()); - args.add("--"); - args.add("/bin/true"); - + List<String> linuxSandboxArgv = + LinuxSandboxUtil.commandLineBuilder( + LinuxSandboxUtil.getLinuxSandbox(cmdEnv).getPathString(), + ImmutableList.of("/bin/true")) + .build(); ImmutableMap<String, String> env = ImmutableMap.of(); + Path execRoot = cmdEnv.getExecRoot(); File cwd = execRoot.getPathFile(); - Command cmd = new Command(args.toArray(new String[0]), env, cwd); + Command cmd = new Command(linuxSandboxArgv.toArray(new String[0]), env, cwd); try { cmd.execute(ByteStreams.nullOutputStream(), ByteStreams.nullOutputStream()); } catch (CommandException e) { @@ -78,11 +74,6 @@ final class LinuxSandboxedSpawnRunner extends AbstractSandboxSpawnRunner { return true; } - private static Path getLinuxSandbox(CommandEnvironment cmdEnv) { - PathFragment execPath = cmdEnv.getBlazeWorkspace().getBinTools().getExecPath(LINUX_SANDBOX); - return execPath != null ? cmdEnv.getExecRoot().getRelative(execPath) : null; - } - private final FileSystem fileSystem; private final BlazeDirectories blazeDirs; private final Path execRoot; @@ -107,7 +98,7 @@ final class LinuxSandboxedSpawnRunner extends AbstractSandboxSpawnRunner { this.execRoot = cmdEnv.getExecRoot(); this.productName = productName; this.allowNetwork = SandboxHelpers.shouldAllowNetwork(cmdEnv.getOptions()); - this.linuxSandbox = getLinuxSandbox(cmdEnv); + this.linuxSandbox = LinuxSandboxUtil.getLinuxSandbox(cmdEnv); this.inaccessibleHelperFile = inaccessibleHelperFile; this.inaccessibleHelperDir = inaccessibleHelperDir; this.timeoutGraceSeconds = timeoutGraceSeconds; @@ -162,67 +153,23 @@ final class LinuxSandboxedSpawnRunner extends AbstractSandboxSpawnRunner { Map<Path, Path> bindMounts, boolean allowNetwork, boolean requiresFakeRoot) { - List<String> commandLineArgs = new ArrayList<>(); - commandLineArgs.add(linuxSandbox.getPathString()); - - if (getSandboxOptions().sandboxDebug) { - commandLineArgs.add("-D"); - } - - // Kill the process after a timeout. + LinuxSandboxUtil.CommandLineBuilder commandLineBuilder = + LinuxSandboxUtil.commandLineBuilder(linuxSandbox.getPathString(), spawn.getArguments()) + .setWritableFilesAndDirectories(writableDirs) + .setTmpfsDirectories(tmpfsPaths) + .setBindMounts(bindMounts) + .setUseFakeHostname(getSandboxOptions().sandboxFakeHostname) + .setCreateNetworkNamespace(!allowNetwork) + .setUseFakeRoot(requiresFakeRoot) + .setUseFakeUsername(getSandboxOptions().sandboxFakeUsername) + .setUseDebugMode(getSandboxOptions().sandboxDebug); if (!timeout.isZero()) { - commandLineArgs.add("-T"); - commandLineArgs.add(Long.toString(timeout.getSeconds())); + commandLineBuilder.setTimeout(timeout); } - if (timeoutGraceSeconds != -1) { - commandLineArgs.add("-t"); - commandLineArgs.add(Integer.toString(timeoutGraceSeconds)); + commandLineBuilder.setKillDelay(Duration.ofSeconds(timeoutGraceSeconds)); } - - // Create all needed directories. - for (Path writablePath : writableDirs) { - commandLineArgs.add("-w"); - commandLineArgs.add(writablePath.getPathString()); - } - - for (Path tmpfsPath : tmpfsPaths) { - commandLineArgs.add("-e"); - commandLineArgs.add(tmpfsPath.getPathString()); - } - - for (ImmutableMap.Entry<Path, Path> bindMount : bindMounts.entrySet()) { - commandLineArgs.add("-M"); - commandLineArgs.add(bindMount.getValue().getPathString()); - - // The file is mounted in a custom location inside the sandbox. - if (!bindMount.getKey().equals(bindMount.getValue())) { - commandLineArgs.add("-m"); - commandLineArgs.add(bindMount.getKey().getPathString()); - } - } - - if (!allowNetwork) { - // Block network access out of the namespace. - commandLineArgs.add("-N"); - } - - if (getSandboxOptions().sandboxFakeHostname) { - // Use a fake hostname ("localhost") inside the sandbox. - commandLineArgs.add("-H"); - } - - if (requiresFakeRoot) { - // Use fake root. - commandLineArgs.add("-R"); - } else if (getSandboxOptions().sandboxFakeUsername) { - // Use a fake username ("nobody") inside the sandbox. - commandLineArgs.add("-U"); - } - - commandLineArgs.add("--"); - commandLineArgs.addAll(spawn.getArguments()); - return commandLineArgs; + return commandLineBuilder.build(); } @Override diff --git a/src/test/java/com/google/devtools/build/lib/runtime/LinuxSandboxUtilTest.java b/src/test/java/com/google/devtools/build/lib/runtime/LinuxSandboxUtilTest.java new file mode 100644 index 0000000000..def19f901e --- /dev/null +++ b/src/test/java/com/google/devtools/build/lib/runtime/LinuxSandboxUtilTest.java @@ -0,0 +1,166 @@ +// 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.runtime; + +import static com.google.common.truth.Truth.assertThat; +import static com.google.devtools.build.lib.testutil.MoreAsserts.expectThrows; + +import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableSortedMap; +import com.google.devtools.build.lib.vfs.FileSystem; +import com.google.devtools.build.lib.vfs.Path; +import com.google.devtools.build.lib.vfs.inmemoryfs.InMemoryFileSystem; +import java.time.Duration; +import java.util.List; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; + +/** Unit tests for {@link LinuxSandboxUtil}. */ +@RunWith(JUnit4.class) +public final class LinuxSandboxUtilTest { + @Test + public void testLinuxSandboxCommandLineBuilder_fakeRootAndFakeUsernameAreExclusive() { + String linuxSandboxPath = "linux-sandbox"; + ImmutableList<String> commandArguments = ImmutableList.of("echo", "hello, flo"); + + Exception e = + expectThrows( + IllegalStateException.class, + () -> + LinuxSandboxUtil.commandLineBuilder(linuxSandboxPath, commandArguments) + .setUseFakeRoot(true) + .setUseFakeUsername(true) + .build()); + assertThat(e).hasMessageThat().contains("exclusive"); + } + + @Test + public void testLinuxSandboxCommandLineBuilder_BuildsWithoutOptionalArguments() { + String linuxSandboxPath = "linux-sandbox"; + + ImmutableList<String> commandArguments = ImmutableList.of("echo", "hello, max"); + + ImmutableList<String> expectedCommandLine = + ImmutableList.<String>builder() + .add(linuxSandboxPath) + .add("--") + .addAll(commandArguments) + .build(); + + List<String> commandLine = + LinuxSandboxUtil.commandLineBuilder(linuxSandboxPath, commandArguments).build(); + + assertThat(commandLine).containsExactlyElementsIn(expectedCommandLine).inOrder(); + } + + @Test + public void testLinuxSandboxCommandLineBuilder_BuildsWithOptionalArguments() { + String linuxSandboxPath = "linux-sandbox"; + + ImmutableList<String> commandArguments = ImmutableList.of("echo", "hello, tom"); + + Duration timeout = Duration.ofSeconds(10); + Duration killDelay = Duration.ofSeconds(2); + String statisticsPath = "stats.out"; + + String workingDirectory = "/all-work-and-no-play"; + String stdoutPath = "stdout.txt"; + String stderrPath = "stderr.txt"; + + // These two flags are exclusive. + boolean useFakeUsername = true; + boolean useFakeRoot = false; + + boolean createNetworkNamespace = true; + boolean useFakeHostname = true; + boolean useDebugMode = true; + + FileSystem fileSystem = new InMemoryFileSystem(); + Path workDir = fileSystem.getPath("/work"); + Path concreteDir = workDir.getRelative("concrete"); + Path sandboxDir = workDir.getRelative("sandbox"); + + Path bindMountSource1 = concreteDir.getRelative("bindMountSource1"); + Path bindMountSource2 = concreteDir.getRelative("bindMountSource2"); + Path mountDir = sandboxDir.getRelative("mount"); + Path bindMountTarget1 = mountDir.getRelative("bindMountTarget1"); + Path bindMountTarget2 = mountDir.getRelative("bindMountTarget2"); + Path bindMountSameSourceAndTarget = mountDir.getRelative("bindMountSourceAndTarget"); + + Path writableDir1 = sandboxDir.getRelative("writable1"); + Path writableDir2 = sandboxDir.getRelative("writable2"); + + Path tmpfsDir1 = sandboxDir.getRelative("tmpfs1"); + Path tmpfsDir2 = sandboxDir.getRelative("tmpfs2"); + + ImmutableList<Path> writableFilesAndDirectories = ImmutableList.of(writableDir1, writableDir2); + + ImmutableList<Path> tmpfsDirectories = ImmutableList.of(tmpfsDir1, tmpfsDir2); + + ImmutableSortedMap<Path, Path> bindMounts = + ImmutableSortedMap.<Path, Path>naturalOrder() + .put(bindMountTarget1, bindMountSource1) + .put(bindMountTarget2, bindMountSource2) + .put(bindMountSameSourceAndTarget, bindMountSameSourceAndTarget) + .build(); + + ImmutableList<String> expectedCommandLine = + ImmutableList.<String>builder() + .add(linuxSandboxPath) + .add("-W", workingDirectory) + .add("-T", Long.toString(timeout.getSeconds())) + .add("-t", Long.toString(killDelay.getSeconds())) + .add("-l", stdoutPath) + .add("-L", stderrPath) + .add("-w", writableDir1.getPathString()) + .add("-w", writableDir2.getPathString()) + .add("-e", tmpfsDir1.getPathString()) + .add("-e", tmpfsDir2.getPathString()) + .add("-M", bindMountSameSourceAndTarget.getPathString()) + .add("-M", bindMountSource1.getPathString()) + .add("-m", bindMountTarget1.getPathString()) + .add("-M", bindMountSource2.getPathString()) + .add("-m", bindMountTarget2.getPathString()) + .add("-S", statisticsPath) + .add("-H") + .add("-N") + .add("-U") + .add("-D") + .add("--") + .addAll(commandArguments) + .build(); + + List<String> commandLine = + LinuxSandboxUtil.commandLineBuilder(linuxSandboxPath, commandArguments) + .setWorkingDirectory(workingDirectory) + .setStdoutPath(stdoutPath) + .setStderrPath(stderrPath) + .setTimeout(timeout) + .setKillDelay(killDelay) + .setWritableFilesAndDirectories(writableFilesAndDirectories) + .setTmpfsDirectories(tmpfsDirectories) + .setBindMounts(bindMounts) + .setUseFakeHostname(useFakeHostname) + .setCreateNetworkNamespace(createNetworkNamespace) + .setUseFakeRoot(useFakeRoot) + .setStatisticsPath(statisticsPath) + .setUseFakeUsername(useFakeUsername) + .setUseDebugMode(useDebugMode) + .build(); + + assertThat(commandLine).containsExactlyElementsIn(expectedCommandLine).inOrder(); + } +} diff --git a/src/test/java/com/google/devtools/build/lib/runtime/ProcessWrapperUtilTest.java b/src/test/java/com/google/devtools/build/lib/runtime/ProcessWrapperUtilTest.java index 6d182f29a8..043e3e38ef 100644 --- a/src/test/java/com/google/devtools/build/lib/runtime/ProcessWrapperUtilTest.java +++ b/src/test/java/com/google/devtools/build/lib/runtime/ProcessWrapperUtilTest.java @@ -71,7 +71,7 @@ public final class ProcessWrapperUtilTest { .setCommandArguments(commandArguments) .build(); - assertThat(commandLine).containsExactlyElementsIn(expectedCommandLine); + assertThat(commandLine).containsExactlyElementsIn(expectedCommandLine).inOrder(); } @Test @@ -108,6 +108,6 @@ public final class ProcessWrapperUtilTest { .setStatisticsPath(statisticsPath) .build(); - assertThat(commandLine).containsExactlyElementsIn(expectedCommandLine); + assertThat(commandLine).containsExactlyElementsIn(expectedCommandLine).inOrder(); } } diff --git a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java index 6a3ca2b7ae..9151cde23e 100644 --- a/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java +++ b/src/test/java/com/google/devtools/build/lib/testutil/TestConstants.java @@ -59,13 +59,17 @@ public class TestConstants { */ public static final String JAVATESTS_ROOT = "io_bazel/src/test/java/"; - /** Relative path to the process-wrapper tool. */ - public static final String PROCESS_WRAPPER_PATH - = "io_bazel/src/main/tools/process-wrapper"; + /** Relative path to the {@code process-wrapper} tool. */ + public static final String PROCESS_WRAPPER_PATH = + "io_bazel/src/main/tools/process-wrapper"; - /** Relative path to the spend_cpu_time testing tool. */ - public static final String CPU_TIME_SPENDER_PATH - = "io_bazel/src/test/shell/integration/spend_cpu_time"; + /** Relative path to the {@code linux-sandbox} tool. */ + public static final String LINUX_SANDBOX_PATH = + "io_bazel/src/main/tools/linux-sandbox"; + + /** Relative path to the {@code spend_cpu_time} testing tool. */ + public static final String CPU_TIME_SPENDER_PATH = + "io_bazel/src/test/shell/integration/spend_cpu_time"; public static final String TEST_RULE_CLASS_PROVIDER = "com.google.devtools.build.lib.bazel.rules.BazelRuleClassProvider"; diff --git a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD index 9918895963..ee2abe9e45 100644 --- a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD +++ b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/BUILD @@ -15,6 +15,7 @@ java_library( "//src/main/java/com/google/devtools/build/lib:os_util", "//src/main/java/com/google/devtools/build/lib:packages-internal", "//src/main/java/com/google/devtools/build/lib:process_util", + "//src/main/java/com/google/devtools/build/lib:runtime", "//src/main/java/com/google/devtools/build/lib:single-line-formatter", "//src/main/java/com/google/devtools/build/lib:unix", "//src/main/java/com/google/devtools/build/lib:util", diff --git a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java index 8463bb0091..12a98d348b 100644 --- a/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java +++ b/src/tools/remote/src/main/java/com/google/devtools/build/remote/worker/RemoteWorker.java @@ -32,6 +32,7 @@ import com.google.devtools.build.lib.remote.TracingMetadataUtils; import com.google.devtools.build.lib.remote.blobstore.ConcurrentMapBlobStore; import com.google.devtools.build.lib.remote.blobstore.OnDiskBlobStore; import com.google.devtools.build.lib.remote.blobstore.SimpleBlobStore; +import com.google.devtools.build.lib.runtime.LinuxSandboxUtil; import com.google.devtools.build.lib.shell.Command; import com.google.devtools.build.lib.shell.CommandException; import com.google.devtools.build.lib.shell.CommandResult; @@ -317,7 +318,9 @@ public final class RemoteWorker { CommandResult cmdResult = null; Command cmd = new Command( - ImmutableList.of(sandboxPath.getPathString(), "--", "true").toArray(new String[0]), + LinuxSandboxUtil.commandLineBuilder( + sandboxPath.getPathString(), ImmutableList.of("true")) + .buildAsArray(), ImmutableMap.<String, String>of(), sandboxPath.getParentDirectory().getPathFile()); try { |