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

Support other output modes than 0555 #5588

Open
wking opened this issue Jul 13, 2018 · 16 comments
Open

Support other output modes than 0555 #5588

wking opened this issue Jul 13, 2018 · 16 comments
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) team-Core Skyframe, bazel query, BEP, options parsing, bazelrc type: feature request

Comments

@wking
Copy link

wking commented Jul 13, 2018

Description of the problem / feature request:

When building tarballs with pkg_tar, the output tarball has a 0555 mode. But tarballs are generally not going to be executable. I think the default mode should be 0666 or, if you want to be very conservative 0444. In both those cases, it would be nice to respect the user's umask, as long as it did not interfere with reproducible builds. An alternative would be to provide an explicit pkg_tar parameter that functions similarly to the existing mode (although mode is for files packaged inside the tarball, not for the tarball itself, #2925).

Feature requests: what underlying problem are you trying to solve with this feature?

Claiming that output tarballs are executable makes it harder to auto-complete sibling paths that are executable. And if you attempt to execute the tarball, I think an EPERM is more obvious than "cannot execute binary file".

Bugs: what's the simplest, easiest way to reproduce this bug? Please provide a minimal example if possible.

$ bazel version
Build label: 0.15.0- (@non-git)
Build target: bazel-out/k8-opt/bin/src/main/java/com/google/devtools/build/lib/bazel/BazelServer_deploy.jar
Build time: Wed Jun 27 14:43:20 2018 (1530110600)
Build timestamp: 1530110600
Build timestamp as int: 1530110600
$ cat WORKSPACE 
workspace(name = "test")
$ cat BUILD.bazel 
load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")

pkg_tar(
    name = "test",
    srcs = glob(
        ["*.txt"],
        exclude_directories = 1,
    ),
    mode = "0666",
)
$ touch text.txt 
$ bazel build test
Starting local Bazel server and connecting to it...
........
INFO: Analysed target //:test (16 packages loaded).
INFO: Found 1 target...
Target //:test up-to-date:
  bazel-bin/test.tar
INFO: Elapsed time: 1.360s, Critical Path: 0.11s
INFO: 1 process: 1 processwrapper-sandbox.
INFO: Build completed successfully, 6 total actions
$ ls -l bazel-bin/test.tar 
-r-xr-xr-x. 1 wking wking 10240 Jul 12 21:49 bazel-bin/test.tar

What operating system are you running Bazel on?

RHEL 7.5 (Linux).

What's the output of bazel info release?

$ bazel info release
release 0.15.0- (@non-git)

If bazel info release returns "development version" or "(@non-git)", tell us how you built Bazel.

Installed from COPR.

Have you found anything relevant by searching the web?

#2925 is similar, but (as mentioned above), it's about the content of the tarball and not the tarball itself. I didn't see anything on SO or bazel-discuss@.

wking added a commit to wking/openshift-installer that referenced this issue Jul 13, 2018
Overriding the default 0555 [1,2], which doesn't make sense for
Terraform configs, etc.  Bazel still (as of 0.15.0) doesn't support
setting permissions for the tarball itself [3], but we can address
that in followup work if/when it becomes possible.

[1]: https://docs.bazel.build/versions/master/be/pkg.html#pkg_tar
[2]: bazelbuild/bazel#2925
[3]: bazelbuild/bazel#5588
@aehlig
Copy link
Contributor

aehlig commented Jul 18, 2018

The output of pkg_tar is an artefact as any other artefact generated by bazel hence gets the same permissions. So, while it is questionable that outputs always have permissions 0555, this has nothing to do with pkg_tar. The most simple way to demonstrate that generic bazel behavior is a BUILD file with the following contents.

genrule(
  name = "hello",
  outs = ["hello.txt"],
  cmd = "echo Hello World > $@ && chmod 0444 $@",
)

Even then, bazel build :hello will generate a file with permissions 0555.

@aehlig aehlig removed their assignment Jul 18, 2018
@aehlig aehlig changed the title pkg_tar makes output mode 0555 feature reqeust: support other output modes than 0555 Jul 18, 2018
@aehlig aehlig added the P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) label Jul 18, 2018
@wking wking changed the title feature reqeust: support other output modes than 0555 feature request: support other output modes than 0555 Jul 18, 2018
yifan-gu pushed a commit to yifan-gu/installer that referenced this issue Jul 25, 2018
Overriding the default 0555 [1,2], which doesn't make sense for
Terraform configs, etc.  Bazel still (as of 0.15.0) doesn't support
setting permissions for the tarball itself [3], but we can address
that in followup work if/when it becomes possible.

[1]: https://docs.bazel.build/versions/master/be/pkg.html#pkg_tar
[2]: bazelbuild/bazel#2925
[3]: bazelbuild/bazel#5588
wking added a commit to wking/openshift-installer that referenced this issue Sep 11, 2018
Avoiding:

  $ ./tests/run.sh
  ...
  cp: cannot create regular file ‘tectonic-dev/smoke’: Permission denied
  $ ls -l tectonic-dev/smoke
  -r-xr-xr-x. 1 trking trking 48972051 Sep 10 12:14 tectonic-dev/smoke

Ideally the Bazel output would have appropriate permissions by
default, but it currently provides no way to set write permission on
its output files [1].  With this commit, you can run run.sh multiple
times in succession without blowing away tectonic-dev between runs.

[1]: bazelbuild/bazel#5588
wking added a commit to wking/openshift-installer that referenced this issue Sep 11, 2018
Avoiding:

  $ ./tests/run.sh
  ...
  cp: cannot create regular file ‘tectonic-dev/smoke’: Permission denied
  $ ls -l tectonic-dev/smoke
  -r-xr-xr-x. 1 trking trking 48972051 Sep 10 12:14 tectonic-dev/smoke

Ideally the Bazel output would have appropriate permissions by
default, but it currently provides no way to set write permission on
its output files [1].  With this commit, you can run run.sh multiple
times in succession without blowing away tectonic-dev between runs.

[1]: bazelbuild/bazel#5588
wking added a commit to wking/openshift-installer that referenced this issue Sep 11, 2018
Avoiding:

  $ ./tests/run.sh
  ...
  cp: cannot create regular file ‘tectonic-dev/smoke’: Permission denied
  $ ls -l tectonic-dev/smoke
  -r-xr-xr-x. 1 trking trking 48972051 Sep 10 12:14 tectonic-dev/smoke

Ideally the Bazel output would have appropriate permissions by
default, but it currently provides no way to set write permission on
its output files [1].  With this commit, you can run run.sh multiple
times in succession without blowing away tectonic-dev between runs.

[1]: bazelbuild/bazel#5588
wking added a commit to wking/openshift-installer that referenced this issue Sep 12, 2018
Avoiding:

  $ ./tests/run.sh
  ...
  cp: cannot create regular file ‘tectonic-dev/smoke’: Permission denied
  $ ls -l tectonic-dev/smoke
  -r-xr-xr-x. 1 trking trking 48972051 Sep 10 12:14 tectonic-dev/smoke

Ideally the Bazel output would have appropriate permissions by
default, but it currently provides no way to set write permission on
its output files [1].  With this commit, you can run run.sh multiple
times in succession without blowing away tectonic-dev between runs.

[1]: bazelbuild/bazel#5588
wking added a commit to wking/openshift-installer that referenced this issue Sep 13, 2018
Avoiding:

  $ ./tests/run.sh
  ...
  cp: cannot create regular file ‘tectonic-dev/smoke’: Permission denied
  $ ls -l tectonic-dev/smoke
  -r-xr-xr-x. 1 trking trking 48972051 Sep 10 12:14 tectonic-dev/smoke

Ideally the Bazel output would have appropriate permissions by
default, but it currently provides no way to set write permission on
its output files [1].  With this commit, you can run run.sh multiple
times in succession without blowing away tectonic-dev between runs.

[1]: bazelbuild/bazel#5588
@tmccombs
Copy link

why do artifacts have a permission of 555, even if they aren't executable? why not use 444 unless it is a directory or marked as an executable?

@jin jin added untriaged team-Bazel General Bazel product/strategy issues labels Feb 19, 2019
@aiuto aiuto removed the untriaged label Feb 21, 2019
@aiuto
Copy link
Contributor

aiuto commented Feb 21, 2019

That's a good question, but changing it is going to be a breaking change for someone, so we are not going to change it without careful reflection.
Is there any compelling reason why 555 modes would be harmful?

@kastiglione
Copy link
Contributor

@aiuto Breaking in theory or breaking in practice? Are there known tools/systems that expect the execution bit on non-executable files?

@aiuto
Copy link
Contributor

aiuto commented Jul 18, 2019

We follow Hyrum's Law - that someone will end up depending on every observable behavior of your code, documented or not. So we assume that theory is equivalent to practice. I'm sure there is someone who generates a bash script with one rule, then passes it as data to another genrule and then expects it to run. So changing it to 444 would break them. This is not so far fetched.

What I meant was that if we are going to make any behavior change, let's figure out the real needs first. Is executable/non-executable sufficient? Do we need files which are non-readable by other users? Do we want to be able to set arbitrary modes for output, so that if we repackaged that output with pkg_deb it would have the "right" file modes for the package?

@dslomov dslomov added team-Local-Exec Issues and PRs for the Execution (Local) team and removed team-Bazel General Bazel product/strategy issues labels Jul 23, 2019
@alanfalloon
Copy link
Contributor

I just found this, and I have a real need. I was setting the modes explicitly to what I needed them to be and they are reverted to 555, which is breaking my rules. Why are the modes adjusted at all? Can we have an opt-out option? Maybe another magic flag in the execution_requirements dict on a ctx.actions.run() that prevents the automatic chmod?

@jmmv
Copy link
Contributor

jmmv commented May 14, 2020

#4059 has more background on this: specifically, artifacts are always executable for historical reasons. Quoting @ulfjack: "The reason is that Google's remote execution system marks all files as executable in order to avoid having to have multiple copies of the same file available locally (multiple hard-links to the same file have the same mod bits)."

Fixing this has nothing to do with local execution and is a broader change to how Bazel actually treats artifacts. Changing teams.

@jmmv jmmv changed the title feature request: support other output modes than 0555 Support other output modes than 0555 May 14, 2020
@jmmv jmmv added team-Core Skyframe, bazel query, BEP, options parsing, bazelrc untriaged and removed P4 This is either out of scope or we don't have bandwidth to review a PR. (No assignee) team-Local-Exec Issues and PRs for the Execution (Local) team labels May 14, 2020
@janakdr janakdr added P3 We're not considering working on this, but happy to review a PR. (No assignee) and removed untriaged labels Aug 24, 2020
@janakdr
Copy link
Contributor

janakdr commented Aug 24, 2020

I haven't heard a compelling use case for this (I'd be curious to hear what @alanfalloon experienced with broken rules). Given the complexity of the change, keeping at a low priority.

@alanfalloon
Copy link
Contributor

Here are some of the ways that this behaviour has broken my rules:

  • Rules that build archives by first producing the directory tree suddenly have entirely wrong permissions in the archives. Some tools, like GNU tar provide flags to work-around this. Other tools, like zip, do not.
  • Rules that use hard-linking instead of copies (when possible) will have the modes changed on sources mysteriously. This is especially problematic when using configuration transitions because of the combinatorial explosion of output dirs means you really need some way of keeping disk usage under control for rules that are essentially copies. Symlinks are not an option when you need to preserve symlinks inside the copy.
  • We have internal tools that use the executable bits to tell if a file is intended to be a plugin/hook vs. configuration file when scanning directories. Of course they completely broke when everything was made executable.
  • We have tests for tools that need to ensure that permissions are handled correctly, but all of the fixture data gets its modes reset to 555, meaning that the tests all need to be modified to generate their own fixture data in temporary locations.

Besides those concrete examples, there is also the case that the current behaviour is both wrong and surprising. Modes are just as much a part of the file as the content -- if not the entire POSIX mode, then certainly the executable bits. Chmoding my outputs after an action is just as wrong as normalizing newlines on every output. As a rule author, it breaks basic assumptions about how actions are executed, and requires me to jump through hoops to work around this issue.

It is somewhat understandable that something like the remote cache is limited to a subset of POSIX behaviour (not preserving xattrs for example) so cached artifacts could lose some permission information. But even in those situations, basic permissions should be preserved: for example, even git preserves executable information in its tree representations. That said, local actions should preserve anything the local filesystems supports so you can always no-remote an action if you need more detailed permissions for its outputs.

I also don't particularly find the Hyrums law argument very convincing: if people were depending on outputs magically becoming executable, then their rules are wrong -- this is just hiding it. We should gate the fix behind an incompatible-flag for a couple of releases to give them a chance to fix their rules, but its not a reason to avoid fixing this bug.

@janakdr
Copy link
Contributor

janakdr commented Nov 28, 2020

cc @alexjski

p0deje added a commit to SeleniumHQ/selenium that referenced this issue May 5, 2021
There is a mode difference in the result files. Gem sources are 644 as
they should be while outputs of dependencies are 555 (e.g. LICENSE,
NOTICE). In fact, there should be no executable in the gem so it seems
fair to simply force-set mode to 644 on everything.

bazelbuild/bazel#5588
bazel-io pushed a commit that referenced this issue Sep 17, 2021
After action execution, permission of output files is changed to [`0555`](#5588). This PR updates remote module in following ways to make the behavior consistent:

  1. Ignores `isExecutable` field of downloaded outputs from remote cache since the permission will be set to `0555` after action execution.
  2. Always set `isExecutable` to `true` instead of reading the real permission bits from file system when uploading local outputs.
  3. Do `chmod 0555` instead of `chmod 0755` when fetching inputs files for local actions which are outputs of previous remote actions. This should improve cache hit rate for builds that use dynamic execution and build without bytes.

Caveat: actions that depend on permission bits of input files (e.g. zip actions) shouldn't be executed dynamically since we have no control of input file permissions when running remotely. They should be always executed either locally or remotely.

b/198297058

Closes #13980.

PiperOrigin-RevId: 397257861
@georgegiovanni
Copy link

@janakdr, perhaps the required change to address this issue is complex, but maybe the priority in this case shouldn't be determined solely based on it's complexity. I understand decisions were made way back to simplify Google's remote execution system and avoid making copies of the same file locally with hard links, but isn't it a safer security practice to not make files executable if you don't have to? Some of the generated files could be part of a public-facing deliverable. It's not only the contents of a file that make up a deliverable but its accompanying metadata. This behaviour is specially incorrect if it's overriding the user's desired execution bits.

Could there at least be an option to force a desired mode for the generated file?

@janakdr
Copy link
Contributor

janakdr commented Oct 5, 2021

I'm not opposed to this change being made. However, my subteam at Google does not have the bandwidth to make it. I would be open to an external contribution. @philwo for broader Bazel visibility if this is a high-enough priority that someone inside Google should work on it.

@philwo
Copy link
Member

philwo commented Oct 19, 2021

Thank you Janak.

@bazelbuild/remote-execution WDYT?

@werkt
Copy link
Contributor

werkt commented Oct 19, 2021

Strongly in favor of avoiding implicit executable-bit setting by the clients, echoing many of the non-hyrum sentiments in this issue. The executable bit adds a major impact to remote systems when there's a client side filter that just ends up making a majority of the input files (as prior outputs) for remote ex have the bit permutation, for non-fuse systems that use hard links (like buildfarm) creating upfront cost, expiration time sink, and cas thrash.

@github-actions
Copy link

Thank you for contributing to the Bazel repository! This issue has been marked as stale since it has not had any activity in the last 1+ years. It will be closed in the next 14 days unless any other activity occurs or one of the following labels is added: "not stale", "awaiting-bazeler". Please reach out to the triage team (@bazelbuild/triage) if you think this issue is still relevant or you are interested in getting the issue resolved.

@github-actions github-actions bot added the stale Issues or PRs that are stale (no activity for 30 days) label May 24, 2023
@aiuto
Copy link
Contributor

aiuto commented May 24, 2023

FWIW, rules_pkg has this capability. The ancient (and deprecated) pkg_tar from @bazel_tools does not.

@github-actions github-actions bot removed the stale Issues or PRs that are stale (no activity for 30 days) label May 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
P3 We're not considering working on this, but happy to review a PR. (No assignee) team-Core Skyframe, bazel query, BEP, options parsing, bazelrc type: feature request
Projects
None yet
Development

No branches or pull requests