Skip to content

Tracking Issue for directory handles #120426

Description

@the8472

View all comments

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. Providing O_BENEATH-style traversal is left to 3rd-party crates or future extensions.

Public API

impl Dir {
    pub fn open<P: AsRef<Path>>(path: P) -> Result<Self>;
    /// This could be put on OpenOptions instead
    pub fn open_with<P: AsRef<Path>>(path: P, opts: &OpenOptions) -> io::Result<Self>;
    pub fn open_for_traversal<P: AsRef<Path>>(path: P) -> io::Result<Self>;

    pub fn try_clone(&self) -> io::Result<Self>;
    pub fn self_metadata(&self) -> Result<Metadata>;

    pub fn open_file<P: AsRef<Path>>(&self, path: P) -> io::Result<File>;
    /// This could be put on OpenOptions instead
    pub fn open_file_with<P: AsRef<Path>>(&self, path: P, opts: &OpenOptions) -> io::Result<File>;
    pub fn open_dir<P: AsRef<Path>>(&self, path: P) -> io::Result<Self>;
    /// This could be put on OpenOptions instead
    pub fn open_dir_with<P: AsRef<Path>>(&self, path: P, opts: &OpenOptions) -> io::Result<Self>
    pub fn create_dir<P: AsRef<Path>>(&self, path: P) -> Result<()>;
    pub fn rename<P: AsRef<Path>, Q: AsRef<Path>>(&self, from: P, to_dir: &Self, to: Q) -> Result<()>;
    pub fn remove_file<P: AsRef<Path>>(&self, path: P) -> Result<()>;
    pub fn remove_dir<P: AsRef<Path>>(&self, path: P) -> Result<()>;
    pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(&self, original: P, link: Q) -> Result<()>;
    pub fn metadata(&self, path: impl AsRef<Path>) -> Result<Metadata>;
    pub fn symlink_metadata(&self, path: impl AsRef<Path>) -> Result<Metadata>;
}

// Various trait impls: AsFd, From<OwnedFd>, ...

impl DirEntry {
    pub fn open(&self) -> Result<File>
    /// This could be put on OpenOptions instead
    pub fn open_with(&self, options: &OpenOptions) -> Result<File>
    pub fn remove_file(&self) -> Result<()>
    pub fn remove_dir(&self) -> Result<()>
}

Steps / History

Unresolved Questions

  • AdRawFd can only be implemented on platforms that use actual directory handles, not all fd platforms. Is this fine?
  • Should the Dir operations that take paths accept absolute paths (where self is effectively irrelevant)?
  • This has been added in piecemeal with a number of fallbacks involved. Prior to stabilization, there should be an implementation review verifying that we're actually using the TOCTOU-resistant operations when available, and that we refuse to fallback to racy versions on tier 1 platforms (Linux, macOS, Windows).
  • What should the Dir method for getting the metadata of the directory itself be called (if we have such an operation at all)? Dir::metadata already corresponds to fs::metadata. For now, it is called self_metadata.
  • Dir::open_file_with (and likely more Dir methods) on Windows does not support / #163032

Footnotes

  1. https://std-dev-guide.rust-lang.org/feature-lifecycle/stabilization.html ↩

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-ioArea: `std::io`, `std::fs`, `std::net` and `std::path`C-tracking-issueCategory: An issue tracking the progress of sth. like the implementation of an RFCO-fuchsiaOperating system: FuchsiaT-libsRelevant to the library team, which will review and decide on the PR/issue.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions