NOTE: With this release, some parts of
github.com/cyphar/filepath-securejoinare now licensed under the Mozilla Public License (version 2). Please see COPYING.md as well as the the license header in each file for more details.
Breaking
-
The new API introduced in the 0.3.0 release has been moved to a new subpackage called
pathrs-lite. This was primarily done to better indicate the split between the new and old APIs, as well as indicate to users the purpose of this subpackage (it is a less complete version of libpathrs).We have added some wrappers to the top-level package to ease the transition, but those are deprecated and will be removed in the next minor release of filepath-securejoin. Users should update their import paths.
This new subpackage has also been relicensed under the Mozilla Public License (version 2), please see COPYING.md for more details.
Added
-
Most of the key bits the safe
procfsAPI have now been exported and are available ingithub.com/cyphar/filepath-securejoin/pathrs-lite/procfs. At the moment this primarily consists of a newprocfs.HandleAPI:-
OpenProcRootreturns a new handle to/proc, endeavouring to make it safe if possible (subset=pidto protect against mistaken write attacks and leaks, as well as usingfsopen(2)to avoid racing mount attacks).OpenUnsafeProcRootreturns a handle without attempting to create one withsubset=pid, which makes it more dangerous to leak. Most users should useOpenProcRoot(even if you need to useProcRootas the base of an operation, as filepath-securejoin will internally open a handle when necessary). -
The
(*procfs.Handle).Open*family of methods lets you get a safeO_PATHhandle to subpaths within/procfor certain subpaths.For
OpenThreadSelf, the returnedProcThreadSelfCloserneeds to be called after you completely finish using the handle (this is necessary because Go is multi-threaded andProcThreadSelfreferences/proc/thread-selfwhich may disappear if we do notruntime.LockOSThread--ProcThreadSelfCloseris currently equivalent toruntime.UnlockOSThread).Note that you cannot open any
procfssymlinks (most notably magic-links) using this API. At the moment, filepath-securejoin does not support this feature (but libpathrs does). -
ProcSelfFdReadlinklets you get the in-kernel path representation of a file descriptor (thinkreadlink("/proc/self/fd/...")), except that we verify that there aren't any tricky overmounts that could fool the process.Please be aware that the returned string is simply a snapshot at that particular moment, and an attacker could move the file being pointed to. In addition, complex namespace configurations could result in non-sensical or confusing paths to be returned. The value received from this function should only be used as secondary verification of some security property, not as proof that a particular handle has a particular path.
The procfs handle used internally by the API is the same as the rest of
filepath-securejoin(for privileged programs this is usually a private in-processprocfsinstance created withfsopen(2)).As before, this is intended as a stop-gap before users migrate to libpathrs, which provides a far more extensive safe
procfsAPI and is generally more robust. -
-
Previously, the hardened procfs implementation (used internally within
ReopenandOpen(at)InRoot) only protected against overmount attacks on systems withopenat2(2)(Linux 5.6) or systems withfsopen(2)oropen_tree(2)(Linux 5.2) and programs with privileges to use them (with some caveats about locked mounts that probably affect very few users). For other users, an attacker with the ability to create malicious mounts (on most systems, a sysadmin) could trick you into operating on files you didn't expect. This attack only really makes sense in the context of container runtime implementations.This was considered a reasonable trade-off, as the long-term intention was to get all users to just switch to libpathrs if they wanted to use the safe
procfsAPI (which had more extensive protections, and is what these new protections infilepath-securejoinare based on). However, as the API is now being exported it seems unwise to advertise the API as "safe" if we do not protect against known attacks.The procfs API is now more protected against attackers on systems lacking the aforementioned protections. However, the most comprehensive of these protections effectively rely on
statx(STATX_MNT_ID)(Linux 5.8). On older kernel versions, there is no effective protection (there is some minimal protection against non-procfsfilesystem components but a sufficiently clever attacker can work around those). In addition,STATX_MNT_IDis vulnerable to mount ID reuse attacks by sufficiently motivated and privileged attackers -- this problem is mitigated withSTATX_MNT_ID_UNIQUE(Linux 6.8) but that raises the minimum kernel version for more protection.The fact that these protections are quite limited despite needing a fair bit of extra code to handle was one of the primary reasons we did not initially implement this in
filepath-securejoin(libpathrs supports all of this, of course).
Fixed
- RHEL 8 kernels have backports of
fsopen(2)but in some testing we've found that it has very bad (and very difficult to debug) performance issues, and so we will explicitly refuse to usefsopen(2)if the running kernel version is pre-5.2 and will instead fallback toopen("/proc").
Thanks to the following contributors who made this release possible:
- Aleksa Sarai cyphar@cyphar.com
- Kir Kolyshkin kolyshkin@gmail.com
- Stephen Kitt skitt@redhat.com
Signed-off-by: Aleksa Sarai cyphar@cyphar.com