Skip to content

Commit 3a4fcc2

Browse files
committed
move grandparent check before the deletion
1 parent 83fb4c4 commit 3a4fcc2

File tree

1 file changed

+19
-27
lines changed

1 file changed

+19
-27
lines changed

library/std/src/sys/unix/fs/dir_fd.rs

+19-27
Original file line numberDiff line numberDiff line change
@@ -191,13 +191,6 @@ mod remove_dir_all_xat {
191191
}
192192
Ok(())
193193
}
194-
195-
fn is_open(&self) -> bool {
196-
match self {
197-
LazyReadDir::OpenReadDir(_, _) => true,
198-
_ => false,
199-
}
200-
}
201194
}
202195

203196
impl AsFd for LazyReadDir<'_> {
@@ -314,9 +307,27 @@ mod remove_dir_all_xat {
314307
let parent_readdir = match readdir_cache.pop_back() {
315308
Some(readdir) => readdir,
316309
None => {
317-
// cache is empty - reopen parent
310+
// cache is empty - reopen parent and grandparent fd
311+
318312
let parent_readdir = current_readdir.get_parent()?;
319313
parent_component.verify_dev_ino(parent_readdir.as_fd())?;
314+
315+
// We are about to delete the now empty "child directory".
316+
// To make sure the that the child directory was not moved somewhere
317+
// else and that the parent just happens to have the same reused
318+
// (dev, inode) pair, that we found descending, we verify the
319+
// grandparent directory (dev, inode) as well.
320+
let grandparent_readdir = parent_readdir.get_parent()?;
321+
if let Some(grandparent_component) = path_components.last() {
322+
grandparent_component
323+
.verify_dev_ino(grandparent_readdir.as_fd())?;
324+
readdir_cache.push_back(grandparent_readdir);
325+
} else {
326+
// verify parent of the deletion root directory
327+
root_parent_component
328+
.verify_dev_ino(grandparent_readdir.as_fd())?;
329+
}
330+
320331
parent_readdir
321332
}
322333
};
@@ -332,25 +343,6 @@ mod remove_dir_all_xat {
332343

333344
current_path_component = parent_component;
334345
current_readdir = parent_readdir;
335-
336-
// Let "child directory" be the directory that was just deleted and "parent directory"
337-
// the parent of "child directory" which is now referred to in current_*.
338-
// If we don't have readdir open for the parent directory that means we got the file
339-
// descriptor via openat(dirfd, ".."). To make sure the that the child directory
340-
// was not moved somewhere else and the parent just happens to have the same reused
341-
// (dev, inode) pair, that we found descending, we check the parent directory
342-
// (dev, inode) as well.
343-
if !current_readdir.is_open() && readdir_cache.is_empty() {
344-
if let Some(parent_component) = path_components.last() {
345-
let parent_readdir = current_readdir.get_parent()?;
346-
parent_component.verify_dev_ino(parent_readdir.as_fd())?;
347-
readdir_cache.push_back(parent_readdir);
348-
} else {
349-
// verify parent of the deletion root directory
350-
let parent_readdir = current_readdir.get_parent()?;
351-
root_parent_component.verify_dev_ino(parent_readdir.as_fd())?;
352-
}
353-
}
354346
}
355347
None => break,
356348
}

0 commit comments

Comments
 (0)