Skip to content

Commit

Permalink
Disable hermetic /tmp with conflicting mount pairs
Browse files Browse the repository at this point in the history
When a mount pair has a source or target under `/tmp`, the hermetic
`/tmp` remount setup conflicts with the path specifications provided on
the command line, so it has to be disabled in this case.
  • Loading branch information
fmeum committed Dec 18, 2023
1 parent cadfc6d commit 6f24a98
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@
import java.util.Optional;
import java.util.SortedMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.stream.Stream;
import javax.annotation.Nullable;

/** Spawn runner that uses linux sandboxing APIs to execute a local subprocess. */
Expand Down Expand Up @@ -206,17 +207,23 @@ private boolean useHermeticTmp() {
return false;
}

Optional<PathFragment> tmpfsPathUnderTmp =
getSandboxOptions().sandboxTmpfsPath.stream()
Optional<PathFragment> mountUnderTmp =
Stream.concat(
getSandboxOptions().sandboxTmpfsPath.stream(),
Stream.concat(
getSandboxOptions().sandboxAdditionalMounts.stream().map(Map.Entry::getKey),
getSandboxOptions().sandboxAdditionalMounts.stream()
.map(Map.Entry::getValue))
.map(PathFragment::create))
.filter(path -> path.startsWith(SLASH_TMP))
.findFirst();
if (tmpfsPathUnderTmp.isPresent()) {
if (mountUnderTmp.isPresent()) {
if (warnedAboutNonHermeticTmp.compareAndSet(false, true)) {
reporter.handle(
Event.warn(
String.format(
"Falling back to non-hermetic '/tmp' in sandbox due to '%s' being a tmpfs path",
tmpfsPathUnderTmp.get())));
"Falling back to non-hermetic '/tmp' in sandbox due to '%s' being a tmpfs path, mount target or mount source",
mountUnderTmp.get())));
}

return false;
Expand Down
53 changes: 53 additions & 0 deletions src/test/shell/integration/sandboxing_test.sh
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,59 @@ EOF
[[ -f "${temp_dir}/file" ]] || fail "Expected ${temp_dir}/file to exist"
}

function test_hermetic_tmp_as_mount_pair_source() {
if [[ "$(uname -s)" != Linux ]]; then
echo "Skipping test: --incompatible_sandbox_hermetic_tmp is only supported in Linux" 1>&2
return 0
fi
sed -i.bak '/sandbox_tmpfs_path/d' "$bazelrc"

temp_dir=$(mktemp -d /tmp/test.XXXXXX)
trap 'rm -rf ${temp_dir}' EXIT
touch "$temp_dir"/some_file

mkdir -p pkg
cat > pkg/BUILD <<'EOF'
genrule(
name = "gen",
outs = ["out"],
cmd = """ls /etc > $@""",
)
EOF

out="$(bazel cquery --output=files //pkg:gen)"
bazel build //pkg:gen --incompatible_sandbox_hermetic_tmp \
--sandbox_add_mount_pair="$temp_dir":/etc || fail "Expected build to pass"
assert_contains 'some_file' "$out"
}

function test_hermetic_tmp_as_mount_pair_target() {
if [[ "$(uname -s)" != Linux ]]; then
echo "Skipping test: --incompatible_sandbox_hermetic_tmp is only supported in Linux" 1>&2
return 0
fi
sed -i.bak '/sandbox_tmpfs_path/d' "$bazelrc"

temp_dir=$(mktemp -d /tmp/test.XXXXXX)
trap 'rm -rf ${temp_dir}' EXIT
touch "$temp_dir"/some_file

mkdir -p pkg
cat > pkg/BUILD <<EOF
genrule(
name = "gen",
outs = ["out"],
cmd = """ls "$temp_dir" > \$@""",
)
EOF

out="$(bazel cquery --output=files //pkg:gen)"
bazel build //pkg:gen --incompatible_sandbox_hermetic_tmp \
--sandbox_add_mount_pair=/etc:"$temp_dir" || fail "Expected build to pass"
assert_not_contains 'some_file' "$out"
assert_contains 'passwd' "$out"
}

function test_sandbox_reuse_stashes_sandbox() {
mkdir pkg
cat >pkg/BUILD <<'EOF'
Expand Down

0 comments on commit 6f24a98

Please sign in to comment.