Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[7.2.0] Cherry-pick sandboxing changes #22342

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

/** 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. */
Expand Down Expand Up @@ -99,7 +100,7 @@ public static void validateBindMounts(Map<Path, Path> bindMounts) throws UserExe
public static Path getInaccessibleHelperFile(Path sandboxBase) throws IOException {
// The order of the permissions settings calls matters, see
// https://github.com/bazelbuild/bazel/issues/16364
Path inaccessibleHelperFile = sandboxBase.getRelative("inaccessibleHelperFile");
Path inaccessibleHelperFile = sandboxBase.getRelative(SandboxHelpers.INACCESSIBLE_HELPER_FILE);
FileSystemUtils.touchFile(inaccessibleHelperFile);
inaccessibleHelperFile.setExecutable(false);
inaccessibleHelperFile.setWritable(false);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
public final class SandboxHelpers {

public static final String INACCESSIBLE_HELPER_DIR = "inaccessibleHelperDir";
public static final String INACCESSIBLE_HELPER_FILE = "inaccessibleHelperFile";

private static final GoogleLogger logger = GoogleLogger.forEnclosingClass();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,8 @@
package com.google.devtools.build.lib.sandbox;

import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.ImmutableList.toImmutableList;

import com.google.common.base.Preconditions;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
Expand Down Expand Up @@ -59,8 +58,10 @@
import java.io.IOException;
import java.time.Duration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Collectors;
import javax.annotation.Nullable;

/** This module provides the Sandbox spawn strategy. */
Expand Down Expand Up @@ -531,13 +532,34 @@ public void cleanStarting(@SuppressWarnings("unused") CleanStartingEvent event)
*/
private static void checkSandboxBaseTopOnlyContainsPersistentDirs(Path sandboxBase) {
try {
Preconditions.checkState(
SANDBOX_BASE_PERSISTENT_DIRS.containsAll(
sandboxBase.getDirectoryEntries().stream()
.map(Path::getBaseName)
.collect(toImmutableList())),
"Found unexpected files in sandbox base. Please report this in"
+ " https://github.com/bazelbuild/bazel/issues.");
List<String> directoryEntries =
sandboxBase.getDirectoryEntries().stream()
.map(Path::getBaseName)
.collect(Collectors.toList());
// If sandbox initialization failed in-between creating the inaccessible dir/file and adding
// the Linux sandboxing strategy to spawnRunners, then the sandbox base will be in a bad
// state. We check for that here and clean up.
if (directoryEntries.contains(SandboxHelpers.INACCESSIBLE_HELPER_DIR)) {
Path inaccessibleHelperDir = sandboxBase.getChild(SandboxHelpers.INACCESSIBLE_HELPER_DIR);
inaccessibleHelperDir.chmod(0700);
directoryEntries.remove(SandboxHelpers.INACCESSIBLE_HELPER_DIR);
inaccessibleHelperDir.deleteTree();
}
if (directoryEntries.contains(SandboxHelpers.INACCESSIBLE_HELPER_FILE)) {
Path inaccessibleHelperFile = sandboxBase.getChild(SandboxHelpers.INACCESSIBLE_HELPER_FILE);
directoryEntries.remove(SandboxHelpers.INACCESSIBLE_HELPER_FILE);
inaccessibleHelperFile.delete();
}

if (!SANDBOX_BASE_PERSISTENT_DIRS.containsAll(directoryEntries)) {
StringBuilder message =
new StringBuilder(
"Found unexpected entries in sandbox base. Please report this in"
+ " https://github.com/bazelbuild/bazel/issues.");
message.append(" The entries are: ");
Joiner.on(", ").appendTo(message, directoryEntries);
throw new IllegalStateException(message.toString());
}
} catch (IOException e) {
logger.atWarning().withCause(e).log("Failed to clean up sandbox base %s", sandboxBase);
}
Expand Down
23 changes: 23 additions & 0 deletions src/test/shell/integration/sandboxing_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,29 @@ EOF
|| fail "Expected build to succeed"
}

function test_bad_state_linux_sandboxing() {
mkdir pkg

# This test is meant to catch a bad state being left over by an unfinished
# linux-sandboxing initialization. Since it's difficult to replicate the same
# conditions that end up in that state, this instead runs a null build
# where linux-sandboxing is unsupported by passing -1 grace seconds.
# Then we create inaccessibleHelperFile/Dir (the bad state) artificially and
# run a null build again making sure there is no crash.
bazel build --local_termination_grace_seconds=-1 \
|| fail "Expected build to succeed"
file_path="$(bazel info output_base)/sandbox/inaccessibleHelperFile"
dir_path="$(bazel info output_base)/sandbox/inaccessibleHelperDir"

touch $file_path
mkdir $dir_path
chmod 000 $file_path
chmod 000 $dir_path

bazel build --local_termination_grace_seconds=-1 \
|| fail "Expected build to succeed"
}

function is_bazel() {
[ $TEST_WORKSPACE == "_main" ]
}
Expand Down
Loading