#467 Consider requiring all files in /usr to be world-readable
Closed: Fixed None Opened 4 years ago by amluto.

Various tools expect most or all of /usr to be world-readable. For example:

  • A containerized copy of a Fedora system can be run using systemd-nspawn or other tools. /usr can be bind-mounted into the container. The container should not require global root in order to read /usr. (LXC and systemd-nspawn are easy examples.)

  • Some virtualization usecases (e.g. virtme) expect /usr to be readable by unprivileged users. Anything that isn't world-readable can't be tested using virtme.

  • systemd --test works much better if systemd can read the relevant parts of /usr.

With the stateless systems and Atomic, this seems even more relevant to me. A stateless system should be fully functional in an unprivileged container or virtfs-based VM.

With this in mind, I would like the FPC to consider a packaging guideline stating that packages must not, without a specific exception, install non-world-readable files under /usr.

I'm less convinced about directories. There may be legitimate use cases for non-readable directories in which admins are expected to put configuration files, although these really belong under /etc instead.

Current violations include audit, sudo, ssh-keysign and ssh-agent, and audit. See https://bugzilla.redhat.com/show_bug.cgi?id=959483 for a bug related to this issue.


Yes, yes, yes! Down with security by obscurity!

supermin can also use this to build better appliances as non-root.

Current list of violations from the packages that libguestfs uses in its supermin appliance:

{{{
supermin: ext2: creating empty ext2 filesystem '/var/tmp/.guestfs-1000/appliance.d.yorqph1o/root'
supermin: ext2: populating from base image
supermin: ext2: copying files from host filesystem
supermin: open: /lib64/dbus-1/dbus-daemon-launch-helper: Permission denied
supermin: open: /usr/bin/chfn: Permission denied
supermin: open: /usr/bin/chsh: Permission denied
supermin: open: /usr/bin/ssh-agent: Permission denied
supermin: open: /usr/libexec/openssh/ssh-keysign: Permission denied
supermin: open: /usr/libexec/utempter/utempter: Permission denied
supermin: open: /usr/sbin/build-locale-archive: Permission denied
supermin: open: /usr/sbin/glibc_post_upgrade.x86_64: Permission denied
supermin: open: /usr/sbin/groupadd: Permission denied
supermin: open: /usr/sbin/groupdel: Permission denied
supermin: open: /usr/sbin/groupmems: Permission denied
supermin: open: /usr/sbin/groupmod: Permission denied
supermin: open: /usr/sbin/unix_update: Permission denied
supermin: open: /usr/sbin/useradd: Permission denied
supermin: open: /usr/sbin/userdel: Permission denied
supermin: open: /usr/sbin/usermod: Permission denied
supermin: ext2: copying kernel modules
}}}

It might pay to change "in the majority of situations" to "unless a specific exception is granted" or something like that. I think that world-readability is sufficiently valuable that packagers should need to justify any deviation. (And rpmlint should check, too, IMO.)

The guidelines are in general always able to be violated with good reason; it's pretty much up to the package reviewer to make the decision. There are only a very few things which are considered so terrible as to require FPC intervention (bundling and such). I personally don't think this rises to the level of something that FPC has to specifically approve but can see the value in simply removing "in the majority of situations" completely.

I would agree about rpmlint, but FPC doesn't control rpmlint. I would suggest contributing a test to rpmlint for this. The Fedora maintainer has generally been receptive to such things, especially if they back up existing guidelines.

With this in mind, I would like the FPC to consider a packaging guideline stating that
packages must not, without a specific exception, install non-world-readable files under
/usr.

What would the criteria for such a "specific exception" be? I don't see '''any''' valid reason for any part of /usr to not be world-readable, it should contain '''only''' stuff installed by a Fedora package, which is public content by definition. So I would say "no exceptions" instead. (Otherwise, people '''will''' argue about exceptions for stupid reasons, such as compliance with some broken regulation, as in that audit bug. The rejection of those reasons is what this policy is all about.)

I'm less convinced about directories. There may be legitimate use cases for non-readable
directories in which admins are expected to put configuration files, although these
really belong under /etc instead.

The policy should just apply without exception, also for directories. If the directory contains host-specific information that could be sensitive, the directory needs to be symlinked to somewhere in /etc. We approved features to allow a read-only /usr (didn't we?), thus anything that '''requires''' the local admin to write to /usr is broken.

I'd really go for a stricter policy on this, and whitelist rather than blacklist the types of file system objects we allow in /usr.

See my comment on the ML:

https://lists.fedoraproject.org/pipermail/devel/2014-November/203907.html

I disagree with the proposal. The FHS definition of /usr, shareable read-only data, does not imply anything about world-readability.

Consider

  • Third-party set[ug]id executables and D-Bus servers and other executables used with high privileges. Those may not be available in a public repository and thus not known to the attacker, and not making the full binary available to the attacker for analysis is a pretty good protection against exploits. It is IMHO a very valid setup to have such executables on /usr, so any software that assumes ''all'' of /usr will be world-readable will be broken in such a setup even if all of Fedora-shipped RPMs were world-readable.

  • Drop-in configuration additions to important security configuration, e.g. polkit rules or in the future SELinux modules. Again, there is a real security benefit to not telling the attacker the (mistakes in the) policy that is enforced, and with the current push to make /etc empty and to push all of these drop-in files to /usr we naturally end up with /usr-packaged non-world-readable files.

And as for the use cases cited:
Not everything available on a host system should is useful to run in a container
(systemd --test) definitely doesn’t need ''all'' of /usr to be world-readable.

There may be useful subsets of /usr where standardizing on permissions makes sense, but I don’t see why “all files” should be that subset.

Replying to [comment:7 mitr]:

I disagree with the proposal. The FHS definition of /usr, shareable read-only data, does not imply anything about world-readability.

Consider

  • Third-party set[ug]id executables and D-Bus servers and other executables used with high privileges. Those may not be available in a public repository and thus not known to the attacker, and not making the full binary available to the attacker for analysis is a pretty good protection against exploits. It is IMHO a very valid setup to have such executables on /usr, so any software that assumes ''all'' of /usr will be world-readable will be broken in such a setup even if all of Fedora-shipped RPMs were world-readable.

These aren't subject to Fedora's packaging guidelines, though.

  • Drop-in configuration additions to important security configuration, e.g. polkit rules or in the future SELinux modules. Again, there is a real security benefit to not telling the attacker the (mistakes in the) policy that is enforced, and with the current push to make /etc empty and to push all of these drop-in files to /usr we naturally end up with /usr-packaged non-world-readable files.

I'm not sure that anything in Fedora's repositories actually give this benefit. For example, if you put something sensitive in auditd.service, then apparently anyone can read it using the systemd dbus api.

And as for the use cases cited:
Not everything available on a host system should is useful to run in a container
(systemd --test) definitely doesn’t need ''all'' of /usr to be world-readable.

There may be useful subsets of /usr where standardizing on permissions makes sense, but I don’t see why “all files” should be that subset.

I can only authoritatively speak to virtme's usecase. Virtme is (currently) a testing tool, and it touches very little except for what the user tries to touch with it. If you want to test audit code using virtme, then you really want the audit files to be readable.

See, for example, https://bugzilla.redhat.com/show_bug.cgi?id=1062930

Note that I first encountered this issue specifically because I was trying to debug the audit code. It's basically impossible to do that in a namespace-based container barring major kernel changes. When I discovered that virtme couldn't read any of the audit-related tools, I chmodded them, but that was rather annoying.

Replying to [comment:7 mitr]:

I disagree with the proposal. The FHS definition of /usr, shareable read-only data, does not imply anything about world-readability.

I've already made my opinion known here, but I have a couple of comments on the arguments you make.

First off, I don't see the relevance of FHS here. We are certainly free to impose additional restrictions not given by FHS. In fact, that's pretty much the entirety of our guidelines.

Second (and I'm just not going to quote them due to brevity) but did you really just make two separate security-by-obscurity arguments?

Replying to [comment:9 amluto]:

Replying to [comment:7 mitr]:

  • Third-party…

These aren't subject to Fedora's packaging guidelines, though.

No, but anything relying on ''all' of /usr being world-readable would be broken by them. So, even Fedora-packaged software should not rely on ''all' of /usr being world-readable.

  • Drop-in configuration additions to important security configuration, e.g. polkit rules or in the future SELinux modules.

I'm not sure that anything in Fedora's repositories actually give this benefit.

I have specifically cited polkit rules; currently all of /usr/share/polkit-1/rules.d is not world-accessible, and there is no API to retrieve the contents of those files. (Again, this matters only for third-party RPMs.)

Replying to [comment:10 tibbs]:

Replying to [comment:7 mitr]:

I disagree with the proposal. The FHS definition of /usr, shareable read-only data, does not imply anything about world-readability.

First off, I don't see the relevance of FHS here. We are certainly free to impose additional restrictions not given by FHS.

Still, these restrictions should IMHO be compatible with the FHS. This rule may end up creating a class of files that have no location that is both FHS- and Fedora packaging guidelines- compliant.

Second (and I'm just not going to quote them due to brevity) but did you really just make two separate security-by-obscurity arguments?

Unless your adversary is a nation state with unlimited resources, making information more difficult to discover ''does'' make systems more difficult to attack and ''is'' valuable. Similarly, layered security is valuable even though only one layer should in theory be enough to enforce the desired policy; these are layers of “reverse-engineer the design“ instead of “find and execute an exploit”, but the net effect is the same: raising costs for the attacker.

Obscurity should never be the ''only'' security mechanism you have, but with a malicious user on the system you want the attacker to run against as many barriers they haven’t anticipated, and for as long a time, and to raise as many alarms in the process, as possible, to give you a better chance to notice and more time to respond.

Replying to [comment:11 mitr]:

I have specifically cited polkit rules; currently all of /usr/share/polkit-1/rules.d is not world-accessible, and there is no API to retrieve the contents of those files. (Again, this matters only for third-party RPMs.)

I intentionally left the idea that non-world-readable /directories/ might be okay. This is an example arguing for that. I don't personally find it a very compelling example (custom packages could install into /usr/local/share or /etc, too), but it's certainly valid.

Replying to [comment:10 tibbs]:

Obscurity should never be the ''only'' security mechanism you have, but with a malicious user on the system you want the attacker to run against as many barriers they haven’t anticipated, and for as long a time, and to raise as many alarms in the process, as possible, to give you a better chance to notice and more time to respond.

If you want to propose that Fedora should actually do this, then do so, and there could be an interesting debate on the merits of this proposal.

But Fedora doesn't do this. Almost every setuid binary is already world-readable. The audit stuff isn't even setuid, so this argument makes essentially no sense in that context.

Replying to [comment:12 amluto]:

Replying to [comment:11 mitr]:

I have specifically cited polkit rules; currently all of /usr/share/polkit-1/rules.d is not world-accessible, and there is no API to retrieve the contents of those files. (Again, this matters only for third-party RPMs.)

I intentionally left the idea that non-world-readable /directories/ might be okay.

I don’t understand; surely non-world-readable directories imply non-world-accessible files. Why are any individually unreadable files a a problem but readable files in unreadable directories fine?

Replying to [comment:10 tibbs]:

Obscurity should never be the ''only'' security mechanism you have, but with a malicious user on the system you want the attacker to run against as many barriers they haven’t anticipated, and for as long a time, and to raise as many alarms in the process, as possible, to give you a better chance to notice and more time to respond.

If you want to propose that Fedora should actually do this, then do so, and there could be an interesting debate on the merits of this proposal.

As others have argued, Fedora RPMs are public so there is little obscurity possible. Third-party and private RPMs are where the obscurity does add value.

But Fedora doesn't do this. Almost every setuid binary is already world-readable. The audit stuff isn't even setuid, so this argument makes essentially no sense in that context.

Sure, there may be useful subsets of /usr where standardizing on permissions makes sense, but I don’t see why “all files” should be that subset.

Replying to [comment:13 mitr]:

Replying to [comment:12 amluto]:

Replying to [comment:11 mitr]:

I have specifically cited polkit rules; currently all of /usr/share/polkit-1/rules.d is not world-accessible, and there is no API to retrieve the contents of those files. (Again, this matters only for third-party RPMs.)

I intentionally left the idea that non-world-readable /directories/ might be okay.

I don’t understand; surely non-world-readable directories imply non-world-accessible files. Why are any individually unreadable files a a problem but readable files in unreadable directories fine?

I should have said that more clearly. I think that world-unreadable directories are still a problem, but that there could be a justification for them (i.e. this one). I tend to think that the problem outweighs the justification.

I don't see a matching justification for regular files.

Sure, there may be useful subsets of /usr where standardizing on permissions makes sense, but I don’t see why “all files” should be that subset.

Actually, the polkit rules are very much in the set of files that I think really should be world-readable. Once the stateless project gets far enough along, I think that virtme, userspace file serving, and unprivileged nspawn-like tools (or a future nspawn that doesn't need to be root) should be able to boot an entire Fedora desktop environment. If the polkit rules directory is unreadable, this won't work.

We discussed this in todays meeting (​​http://meetbot.fedoraproject.org/fedora-meeting-1/2014-11-13/fpc.2014-11-13-17.01.txt) and voted to change the policy to be clearer:

...where a copy of the last policy (http://fpaste.org/150562/41590171/) is:

Permissions on files must be set properly.
Inside of /usr, files should be owned by root:root unless a more specific user or group is needed for security .  They must be universally readable (and executable if appropriate).
Outside of /usr, non-config and non-state files should be owned by root:root, universally readable (and executable if appropriate) unless circumstances require otherwise.

Default file mode is 0644 or 0755. Directories should be mode 0755. Most well behaved build scripts and rpm will use these defaults.
If the directory needs to be group writable, it should also have the setgid bit set so that files written there are owned by that group. These directories should have mode 2775.

Deviations from the default ownership or mode must be justified and documented in the specfile.

Announcement text:

Guidelines on file permissions (https://fedoraproject.org/wiki/Packaging:Guidelines#File_Permissions) have been clarified.

For historical record, in case this were ever to be revisited (which I am not proposing at this point): even when contents of a setuid file are known to the attacker, giving the attacker read privileges to the actual inode storing the setuid file was useful for an exploit:

http://googleprojectzero.blogspot.cz/2015/03/exploiting-dram-rowhammer-bug-to-gain.html

We load /bin/ping (using open() and mmap()+MAP_POPULATE) and query which physical pages it was loaded into using /proc/self/pagemap.

Login to comment on this ticket.

Metadata