Open the8472 opened 8 months ago
During the ACP a survey of platform support was requested to make sure that fallbacks won't be needed on Tier-1 platforms.
For restricted conversion between *DIR
and a file descriptor we need fdopendir
+ dirfd
. For free conversion we need an alternative to readdir
that operates on file descriptors.
Presence of *at
functions was surveyed by looking at the libc
crate, so this may be incomplete.
NtCreateFile
GetFileInformationByHandleEx
+ FILE_FULL_DIR_INFO
.SetFileInformationByHandle
+ FILE_RENAME_INFORMATION
SetFileInformationByHandle
+ FILE_DISPOSITION_INFO_EX
NtCreateFile
DeviceIoControl
+ FSCTL_SET_REPARSE_POINT
NtQueryInformationByName
(if available) or GetFileInformationByHandle
and GetFileInformationByHandleEx
+ FILE_ATTRIBUTE_TAG_INFOgetdents
getattrlistbulk
getdents
ReadDirents
getattrlistbulk
libc
only lists renameat, unlinkat, symlinkat, fstatat
The redox syscall crate lists no *at calls at all?
Listed as no_std in the platform support documentation. Somehow has some pieces in std anyway. No libc
support either.
Regarding redox, relibc is the right place to look for support. We should be able to support the same list of functions as Linux and the BSDs.
The ACP mentions “it may be possible to add the Dir methods directly to ReadDir instead”. This is problematic because ReadDir: !From<OwnedFd>
(#56777). Being able to open a file with File::open
, then check its file type using Metadata::file_type
and convert it to a Dir
object if it is a directory would be very useful IMO, for instance to hash a tree of files. That said it may be better to just address #56777 than to have the design of #120426 hinge on this.
From a Miri perspective I'd love to see this, it would let us implement support for emulation of openat
and similar functions in a cross-platform way. :)
portable, insecure openat emulation based on Paths
I am somewhat surprised to see this TODO item. In other areas Rust chose to not provide lower-quality fallback implementations, e.g. famously Rust atomics are always hardware atomics and never lock emulated. I can't find discussion of this point in the ACP either. What is the reasoning here for preferring an insecure emulation over a security guarantee stated in the API?
Operating on a directory is a fairly basic operation, like opening a File
. If we returned an error that basically says "we could do that, just the way you're opening it is unsupported on this system" then it would become less portable and likely only interesting for tools like sudo
which won't support such platforms anyway.
Dir
isn't just about security. It provides a handle to a directory that should keep working even if the directory gets renamed (granted, fallbacks don't provide this). It helps with performance. It allows replacing global process state (the current working directory) with local state. It can prevent non-malicious races.
So applications that aren't security-sensitive would still want to use Dir
in their filesystem code.
Additionally, the platforms where openat
isn't available are more likely to be single-user systems without privilege separation, on those fallbacks wouldn't be an issue anyway. Afaik UEFI has none of that.
That said, maybe we can add a fail_closed
flag, impl Dir { const IS_RACEFREE: bool }
or something like that for applications that need some extra assurances.
Also, this wouldn't be a runtime fallback but a platform-based fallback. All tier-1 platforms will use real handles and fail if they're not available. E.g. if something blocks openat
via seccomp on linux I do not intend to try open
.
Also, this wouldn't be a runtime fallback but a platform-based fallback.
Can this be completed with a compiler warning for these platforms? Since this will be something included in the target type, I would imagine so.
@rustbot ping fuchsia
Since it appears that functions being available in the libc crate is not a reliable indicatior that they actually work, is there a better overview of the available posix APIs? I'm interested in the file descriptor APIs listed in https://github.com/rust-lang/rust/issues/120426#issuecomment-1913167876
Hey friends of Fuchsia! This issue could use some guidance on how this should be resolved/implemented on Fuchsia. Could one of you weigh in?
cc @djkoloski @erickt @P1n3appl3 @tmandry
@the8472 how odd, we do support it at the Fuchsia layer, maybe we're not exposing it through fdio. We'll do some investigation and report back.
@the8472 got confirmation from our team that we do support dirfd
on fuchsia, so this is just a bug we'll get fixed.
Feature gate:
#![feature(dirfd)]
This is a tracking issue for directory handles. Such handles provide a stable reference to an underlying filesystem object (typically directories) that are less vulnerable to TOCTOU attacks and similar races. These security properties will be platform-dependent. Platforms that don't provide the necessary primitives will fall back to operations on absolute paths.
Additionally they may also provide performance benefits by avoiding repeated path lookups when performing many operations on a directory.
Sandboxing is a non-goal. If a platform supports upwards path traversal via
..
or symlinks then directory handles will not prevent that. ProvidingO_BENEATH
-style traversal is left to 3rd-party crates or future extensions.Public API
Steps / History
openat
emulation based onPath
sgetdents
to get free conversion between dirfds andReadDir
*at
callsUnresolved Questions