Add --incompatible_sandbox_hermetic_tmp #16336
Add --incompatible_sandbox_hermetic_tmp #16336fmeum wants to merge 1 commit intobazelbuild:masterfrom
Conversation
c870104 to
d984b32
Compare
|
@larsrc-google @philwo Would you be able to take a look? This realizes #3236 (comment) as an incompatible flag as I believe these kind of bugs should not occur with default settings. Happy to discuss alternative ways to ship this though. |
| @@ -283,9 +289,15 @@ protected ImmutableSet<Path> getWritableDirs(Path sandboxExecRoot, Map<String, S | |||
| } | |||
|
|
|||
| private SortedMap<Path, Path> getReadOnlyBindMounts( | |||
There was a problem hiding this comment.
Is it just me, or is this very poorly named?
There was a problem hiding this comment.
Not just you, it was very poorly named after my changes. Fixed it.
| // /tmp instead by mounting /tmp to /tmp, if desired. | ||
| bindMounts.put(tmpPath, sandboxTmp); | ||
| } | ||
| if (blazeDirs.getWorkspace().startsWith(tmpPath)) { |
There was a problem hiding this comment.
Do these two following remounts work with hermetic tmp?
There was a problem hiding this comment.
Not as far as I can tell. I used the commands from test_write_hermetic_tmp to run it within /tmp and elsewhere, and it works elsewhere but fails within /tmp:
$ /tmp/bazel-hermeticsandbox --bazelrc=/dev/null test pkg:tmp_test --spawn_strategy=sandboxed --incompatible_sandbox_hermetic_tmp --sandbox_debug --verbose_failures
INFO: Analyzed target //pkg:tmp_test (1 packages loaded, 2 targets configured).
INFO: Found 1 test target...
ERROR: /tmp/hermetictmptest/pkg/BUILD:1:8: Testing //pkg:tmp_test failed: (Exit 1): linux-sandbox failed: error executing command
(cd /usr/local/google/home/larsrc/.cache/bazel/_bazel_larsrc/5aee95154b6da9eb556a8fb39d46f41c/sandbox/linux-sandbox/8/execroot/__main__ && \
exec env - \
EXPERIMENTAL_SPLIT_XML_GENERATION=1 \
JAVA_RUNFILES=bazel-out/k8-fastbuild/bin/pkg/tmp_test.runfiles \
PATH=/usr/local/google/home/larsrc/.local/bin:/usr/local/google/home/larsrc/bin:/usr/lib/google-golang/bin:/usr/local/buildtools/java/jdk/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/intellij-idea/bin:/usr/local/google/home/larsrc/bin \
PYTHON_RUNFILES=bazel-out/k8-fastbuild/bin/pkg/tmp_test.runfiles \
RUNFILES_DIR=bazel-out/k8-fastbuild/bin/pkg/tmp_test.runfiles \
RUN_UNDER_RUNFILES=1 \
TEST_BINARY=pkg/tmp_test \
TEST_INFRASTRUCTURE_FAILURE_FILE=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.infrastructure_failure \
TEST_LOGSPLITTER_OUTPUT_FILE=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.raw_splitlogs/test.splitlogs \
TEST_NAME=//pkg:tmp_test \
TEST_PREMATURE_EXIT_FILE=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.exited_prematurely \
TEST_SHARD_INDEX=0 \
TEST_SIZE=medium \
TEST_SRCDIR=bazel-out/k8-fastbuild/bin/pkg/tmp_test.runfiles \
TEST_TARGET=//pkg:tmp_test \
TEST_TIMEOUT=300 \
TEST_TMPDIR=_tmp/dce7d97fa01edd02eaaa2ea9bd7d11f5 \
TEST_TOTAL_SHARDS=0 \
TEST_UNDECLARED_OUTPUTS_ANNOTATIONS=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.outputs_manifest/ANNOTATIONS \
TEST_UNDECLARED_OUTPUTS_ANNOTATIONS_DIR=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.outputs_manifest \
TEST_UNDECLARED_OUTPUTS_DIR=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.outputs \
TEST_UNDECLARED_OUTPUTS_MANIFEST=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.outputs_manifest/MANIFEST \
TEST_UNDECLARED_OUTPUTS_ZIP=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.outputs/outputs.zip \
TEST_UNUSED_RUNFILES_LOG_FILE=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.unused_runfiles_log \
TEST_WARNINGS_OUTPUT_FILE=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.warnings \
TEST_WORKSPACE=__main__ \
TMPDIR=/tmp \
TZ=UTC \
XML_OUTPUT_FILE=bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.xml \
/usr/local/google/home/larsrc/.cache/bazel/_bazel_larsrc/install/cd380c01deb6ae3b758a4940bc515c99/linux-sandbox -t 15 -w /usr/local/google/home/larsrc/.cache/bazel/_bazel_larsrc/5aee95154b6da9eb556a8fb39d46f41c/sandbox/linux-sandbox/8/execroot/__main__ -w /usr/local/google/home/larsrc/.cache/bazel/_bazel_larsrc/5aee95154b6da9eb556a8fb39d46f41c/sandbox/linux-sandbox/8/execroot/__main__/_tmp/dce7d97fa01edd02eaaa2ea9bd7d11f5 -w /tmp -w /dev/shm -e /tmp -M /usr/local/google/home/larsrc/.cache/bazel/_bazel_larsrc/5aee95154b6da9eb556a8fb39d46f41c/sandbox/linux-sandbox/8/_tmp -m /tmp -M /tmp/hermetictmptest -S /usr/local/google/home/larsrc/.cache/bazel/_bazel_larsrc/5aee95154b6da9eb556a8fb39d46f41c/sandbox/linux-sandbox/8/stats.out -D -- external/bazel_tools/tools/test/generate-xml.sh bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.log bazel-out/k8-fastbuild/testlogs/pkg/tmp_test/test.xml 0 1)
Target //pkg:tmp_test up-to-date:
bazel-bin/pkg/tmp_test
INFO: Elapsed time: 0.259s, Critical Path: 0.02s
INFO: 3 processes: 3 internal.
FAILED: Build did NOT complete successfully
//pkg:tmp_test NO STATUS
FAILED: Build did NOT complete successfully
There was a problem hiding this comment.
Good catch, that doesn't seem to work. I think that getting this to work would be possible but slightly involved: It requires mounting the workspace/output base somewhere else first, then mounting /tmp, then mounting that "somewhere else" into the expected paths. That "somewhere else" may require cleanup though.
Do you think that this would be worth the effort? Alternatively, I could disable hermetic /tmp in this case and emit a warning once.
There was a problem hiding this comment.
At least for now, let's disallow hermetic /tmp when inside /tmp, whether by disabling it with a warning or maybe downright failing. I would expect it to be rare.
There was a problem hiding this comment.
I added a warning and am now also taking --sandbox_tmpfs_path=/tmp into account.
21c5265 to
5094411
Compare
| sandboxExecRoot.createDirectory(); | ||
|
|
||
| Path sandboxTmp = null; | ||
| if (getSandboxOptions().sandboxHermeticTmp && !getSandboxOptions().sandboxTmpfsPath.contains(PathFragment.create("/tmp"))) { |
There was a problem hiding this comment.
Should this check for starting with /tmp (or rather either being /tmp or starting with /tmp/) instead of containing /tmp? Not sure what would happen if --sandbox_tmpfs_path is /tmp/foobar.
There was a problem hiding this comment.
Added a check for this as well as a descriptive warning. I think we should be able to support it by sorting the tmpfs paths into the bind mounts, but would prefer to ignore this edge case for now.
5094411 to
0ba0349
Compare
| .findFirst(); | ||
| // Mounting a tmpfs strictly below the hermetic /tmp isn't supported. Mounting a tmpfs on /tmp | ||
| // makes mounting the disk-based hermetic /tmp unnecessary. | ||
| if (tmpfsPathUnderTmp.isPresent() && !getSandboxOptions().sandboxTmpfsPath.contains(tmpRoot) |
There was a problem hiding this comment.
The ifs for the warning and the actual logic should not be separate. It would be better to have one if with the logic and an inner if with just the warnedAboutNonHermeticTmp check.
There was a problem hiding this comment.
I rearranged the control flow and also moved the comments around. PTAL.
4f3852b to
65105dd
Compare
|
Looks nice now. With this much new logic, could you add some unit tests in |
With the new flag, each Linux sandbox will have its own dedicated empty
directory mounted as /tmp rather than sharing /tmp with the host
filesystem.
This is necessary since the Linux sandbox uses a PID namespace, but many
tools (e.g. the JVM) create files at well-known locations such as
`/tmp/.javapid${PID}`, which leads to collisions between different
sandboxes and the host. These collisions can result in crashes or
surprising situations such as Java agents being attached to a JVM in a
different sandbox.
With the flag enabled, `--sandbox_add_mount_pair=/tmp` can be used to
restore the old behavior of a non-hermetic /tmp directory.
This is made possible by a small change to linux-sandbox which allows
mount pair source directories to also be marked as writable directories.
65105dd to
bece15b
Compare
I added unit tests for three scenarios. I wasn't able to figure out how to:
@larsrc-google In case you want me to add coverage for any of these cases, I would need some hlep. |
With the new flag, each Linux sandbox will have its own dedicated empty
directory mounted as `/tmp` rather than sharing `/tmp` with the host
filesystem.
This is necessary since the Linux sandbox uses a PID namespace, but many
tools (e.g. the JVM) create files at well-known locations such as
`/tmp/.javapid${PID}`, which leads to collisions between different
sandboxes and the host. These collisions can result in crashes or
surprising situations such as Java agents being attached to a JVM in a
different sandbox.
With the flag enabled, `--sandbox_add_mount_pair=/tmp` can be used to
restore the old behavior of a non-hermetic `/tmp` directory.
This is made possible by a small change to linux-sandbox which allows
mount pair source directories to also be marked as writable directories.
Work towards bazelbuild#3236
Closes bazelbuild#16336.
PiperOrigin-RevId: 481570131
Change-Id: I01b654a1f4b0223a8f272cf644e23a7d0572ea09
|
@fmeum you may be interested in my recent findings, I was trying this feature for some yarn stuff that otherwise fails to build and is hard to migrate to rules_js, so we call yarn directly, only that we do it inside a sandbox, thing is when I started enabling this flag I started getting a weird bug about files not existing: I managed to create a repro repository https://github.com/bookingcom/test-sandbox-hermetic-tmp, turns out it's a weird interaction with |
With the new flag, each Linux sandbox will have its own dedicated empty
directory mounted as
/tmprather than sharing/tmpwith the hostfilesystem.
This is necessary since the Linux sandbox uses a PID namespace, but many
tools (e.g. the JVM) create files at well-known locations such as
/tmp/.javapid${PID}, which leads to collisions between differentsandboxes and the host. These collisions can result in crashes or
surprising situations such as Java agents being attached to a JVM in a
different sandbox.
With the flag enabled,
--sandbox_add_mount_pair=/tmpcan be used torestore the old behavior of a non-hermetic
/tmpdirectory.This is made possible by a small change to linux-sandbox which allows
mount pair source directories to also be marked as writable directories.
Work towards #3236