faccess adds file accessbility checks for file paths to Rust:
For the simple case:
use PathBuf; use PathExt; let path = from; if path.readable
More complex needs, such as reporting precisely why the file isn’t deemed
accessible in the desired manner, the underlying
access method can be used:
use PathBuf; use ; let path = from; match path.access ;
On Unix platforms, this is basically trivial – just exposing a safe
faccessat(2) via the
On Windows, there’s
AccessCheck, which… is both more fiddly and has more special-cases to worry about.
For example, you can’t just ask if the current process can read or write a file
or directory, beacuse that would be silly – instead, you want to check if you
can access a given
SECURITY_DESCRIPTOR that idenfities the resource you wish
to check, and check it against an “impersonation token” with
I’m still not entirely happy with what I’ve got – not least because it simply falls back to just trying to open a file in the common case.
This is particularly awkward for me as it interacts badly with Windows Overlay Filter compressed files (as created by Compactor), because checking if such a file is writable will–in opening the file for writing–also uncompress it.
Security Considerations: TOCTOU
This style of file accessibility check is the poster child of so-called “time-of-check to time-of-use” bugs. Here’s Wikipedia’s main example:
if fd = ; ;
In this C program,
file is checked using
access in a setuid program to
determine if the real user (as opposed to the effective user–setuid programs
run as the owner of the executable rather than the actual user running it) is
permitted to write to it–basically attempting to replicate the standard file
permissions in userspace.
In a multitasking environment this races against other processes on the system,
which may manipulate
file in between the original
access check and the
write call, causing the program to misuse its elevated permissions
to overwrite a file it shouldn’t have had access to.
Happily we can now reproduce such security concerns in Rust, so they can at least be memory-safe. You’re welcome.