4
4
//! filesystem. All methods in this module represent cross-platform filesystem
5
5
//! operations. Extra platform-specific functionality can be found in the
6
6
//! 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
+ //! Be aware that metadata operations (like [`metadata`] or [`symlink_metadata`]) may be affected by
19
+ //! changes made by other processes.
20
+ //!
21
+ //! To avoid TOCTOU issues:
22
+ //! - Use atomic operations when possible (like [`File::create_new`] instead of checking existence then creating)
23
+ //! - Keep file handles open for the duration of operations
24
+ //! - Use file locking when appropriate
25
+ //!
26
+ //! Individual functions in this module document their specific TOCTOU considerations.
7
27
8
28
#![ stable( feature = "rust1" , since = "1.0.0" ) ]
9
29
#![ deny( unsafe_op_in_unsafe_fn) ]
@@ -549,13 +569,14 @@ impl File {
549
569
/// non-exhaustive list of likely errors.
550
570
///
551
571
/// 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
572
+ /// exists and creating a new one, the file may have been created by another process (a [ TOCTOU]
553
573
/// race condition / attack).
554
574
///
555
575
/// This can also be written using
556
576
/// `File::options().read(true).write(true).create_new(true).open(...)`.
557
577
///
558
578
/// [`AlreadyExists`]: crate::io::ErrorKind::AlreadyExists
579
+ /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
559
580
///
560
581
/// # Examples
561
582
///
@@ -1580,7 +1601,7 @@ impl OpenOptions {
1580
1601
///
1581
1602
/// This option is useful because it is atomic. Otherwise between checking
1582
1603
/// whether a file exists and creating a new one, the file may have been
1583
- /// created by another process (a TOCTOU race condition / attack).
1604
+ /// created by another process (a [ TOCTOU] race condition / attack).
1584
1605
///
1585
1606
/// If `.create_new(true)` is set, [`.create()`] and [`.truncate()`] are
1586
1607
/// ignored.
@@ -1591,6 +1612,7 @@ impl OpenOptions {
1591
1612
/// [`.create()`]: OpenOptions::create
1592
1613
/// [`.truncate()`]: OpenOptions::truncate
1593
1614
/// [`AlreadyExists`]: io::ErrorKind::AlreadyExists
1615
+ /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
1594
1616
///
1595
1617
/// # Examples
1596
1618
///
@@ -2923,7 +2945,7 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
2923
2945
/// - "Windows": This function currently corresponds to `CreateFileW`,
2924
2946
/// `GetFileInformationByHandleEx`, `SetFileInformationByHandle`, and `NtCreateFile`.
2925
2947
///
2926
- /// ## Time-of-check to time-of-use (TOCTOU) race conditions
2948
+ /// ## Time-of-check to time-of-use ([ TOCTOU] ) race conditions
2927
2949
/// On a few platforms there is no way to remove a directory's contents without following symlinks
2928
2950
/// unless you perform a check and then operate on paths based on that directory.
2929
2951
/// This allows concurrently-running code to replace the directory with a symlink after the check,
@@ -2935,6 +2957,7 @@ pub fn remove_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
2935
2957
/// - Redox OS: This function does not protect against TOCTOU races, as Redox does not implement
2936
2958
/// the required platform support to do so.
2937
2959
///
2960
+ /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
2938
2961
/// [changes]: io#platform-specific-behavior
2939
2962
///
2940
2963
/// # Errors
@@ -3208,7 +3231,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
3208
3231
/// permission is denied on one of the parent directories.
3209
3232
///
3210
3233
/// 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
3212
3235
/// where those bugs are not an issue.
3213
3236
///
3214
3237
/// # Examples
@@ -3221,6 +3244,7 @@ impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
3221
3244
/// ```
3222
3245
///
3223
3246
/// [`Path::exists`]: crate::path::Path::exists
3247
+ /// [TOCTOU]: self#time-of-check-to-time-of-use-toctou
3224
3248
#[ stable( feature = "fs_try_exists" , since = "1.81.0" ) ]
3225
3249
#[ inline]
3226
3250
pub fn exists < P : AsRef < Path > > ( path : P ) -> io:: Result < bool > {
0 commit comments