44//! filesystem. All methods in this module represent cross-platform filesystem 
55//! operations. Extra platform-specific functionality can be found in the 
66//! extension traits of `std::os::$platform`. 
7+ //! 
8+ //! # Time of Check to Time of Use (TOCTOU) 
9+ //! 
10+ //! Many filesystem operations are subject to a race condition known as "Time of Check to Time of Use" 
11+ //! (TOCTOU). This occurs when a program checks a condition (like file existence or permissions) 
12+ //! and then uses the result of that check to make a decision, but the condition may have changed 
13+ //! between the check and the use. 
14+ //! 
15+ //! For example, checking if a file exists and then creating it if it doesn't is vulnerable to 
16+ //! TOCTOU - another process could create the file between your check and creation attempt. 
17+ //! 
18+ //! Another example is with symbolic links: when removing a directory, if another process replaces 
19+ //! the directory with a symbolic link between the check and the removal operation, the removal 
20+ //! might affect the wrong location. This is why operations like [`remove_dir_all`] need to use 
21+ //! atomic operations to prevent such race conditions. 
22+ //! 
23+ //! To avoid TOCTOU issues: 
24+ //! - Be aware that metadata operations (like [`metadata`] or [`symlink_metadata`]) may be affected by 
25+ //! changes made by other processes. 
26+ //! - Use atomic operations when possible (like [`File::create_new`] instead of checking existence then creating). 
27+ //! - Keep file open for the duration of operations. 
728
829#![ stable( feature = "rust1" ,  since = "1.0.0" ) ]  
930#![ deny( unsafe_op_in_unsafe_fn) ]  
@@ -549,13 +570,14 @@ impl File {
549570     /// non-exhaustive list of likely errors. 
550571     /// 
551572     /// This option is useful because it is atomic. Otherwise between checking whether a file 
552-      /// exists and creating a new one, the file may have been created by another process (a TOCTOU 
573+      /// exists and creating a new one, the file may have been created by another process (a [ TOCTOU]  
553574     /// race condition / attack). 
554575     /// 
555576     /// This can also be written using 
556577     /// `File::options().read(true).write(true).create_new(true).open(...)`. 
557578     /// 
558579     /// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists 
580+      /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou 
559581     /// 
560582     /// # Examples 
561583     /// 
@@ -1580,7 +1602,7 @@ impl OpenOptions {
15801602     /// 
15811603     /// This option is useful because it is atomic. Otherwise between checking 
15821604     /// whether a file exists and creating a new one, the file may have been 
1583-      /// created by another process (a TOCTOU race condition / attack). 
1605+      /// created by another process (a [ TOCTOU]  race condition / attack). 
15841606     /// 
15851607     /// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are 
15861608     /// ignored. 
@@ -1591,6 +1613,7 @@ impl OpenOptions {
15911613     /// [`.create()`]: OpenOptions::create 
15921614     /// [`.truncate()`]: OpenOptions::truncate 
15931615     /// [`AlreadyExists`]: io::ErrorKind::AlreadyExists 
1616+      /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou 
15941617     /// 
15951618     /// # Examples 
15961619     /// 
@@ -2924,17 +2947,17 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
29242947/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`. 
29252948/// 
29262949/// ## Time-of-check to time-of-use (TOCTOU) race conditions 
2927- /// On a few platforms there is no way to remove a directory's contents without following symlinks 
2928- /// unless you perform a check and then operate on paths based on that directory. 
2929- /// This allows concurrently-running code to replace the directory with a symlink after the check, 
2930- /// causing a removal to instead operate on a path based on the symlink. This is a TOCTOU race. 
2931- /// By default, `fs::remove_dir_all` protects against a symlink TOCTOU race on all platforms 
2932- /// except the following. It should not be used in security-sensitive contexts on these platforms: 
2933- /// - Miri: Even when emulating targets where the underlying implementation will protect against 
2934- /// TOCTOU races, Miri will not do so. 
2935- /// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement 
2936- /// the required platform support to do so. 
2950+ /// See the [module-level TOCTOU explanation](self#time-of-check-to-time-of-use-toctou). 
2951+ /// 
2952+ /// On most platforms, `fs::remove_dir_all` protects against symlink TOCTOU races by default. 
2953+ /// However, on the following platforms, this protection is not provided and the function should 
2954+ /// not be used in security-sensitive contexts: 
2955+ /// - **Miri**: Even when emulating targets where the underlying implementation will protect against 
2956+ ///   TOCTOU races, Miri will not do so. 
2957+ /// - **Redox OS**: This function does not protect against TOCTOU races, as Redox does not implement 
2958+ ///   the required platform support to do so. 
29372959/// 
2960+ /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou 
29382961/// [changes]: io#platform-specific-behavior 
29392962/// 
29402963/// # Errors 
@@ -3208,7 +3231,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
32083231/// permission is denied on one of the parent directories. 
32093232/// 
32103233/// Note that while this avoids some pitfalls of the `exists()` method, it still can not 
3211- /// prevent time-of-check to time-of-use (TOCTOU) bugs. You should only use it in scenarios 
3234+ /// prevent time-of-check to time-of-use ([ TOCTOU] ) bugs. You should only use it in scenarios 
32123235/// where those bugs are not an issue. 
32133236/// 
32143237/// # Examples 
@@ -3221,6 +3244,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
32213244/// ``` 
32223245/// 
32233246/// [`Path::exists`]: crate::path::Path::exists 
3247+ /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou 
32243248#[ stable( feature = "fs_try_exists" ,  since = "1.81.0" ) ]  
32253249#[ inline]  
32263250pub  fn  exists < P :  AsRef < Path > > ( path :  P )  -> io:: Result < bool >  { 
0 commit comments