Skip to content

Commit 714aa3c

Browse files
committed
fix
1 parent 3a4fcc2 commit 714aa3c

File tree

1 file changed

+24
-19
lines changed

1 file changed

+24
-19
lines changed

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

+24-19
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,13 @@ 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+
}
194201
}
195202

196203
impl AsFd for LazyReadDir<'_> {
@@ -307,31 +314,29 @@ mod remove_dir_all_xat {
307314
let parent_readdir = match readdir_cache.pop_back() {
308315
Some(readdir) => readdir,
309316
None => {
310-
// cache is empty - reopen parent and grandparent fd
311-
317+
// cache is empty - reopen parent
312318
let parent_readdir = current_readdir.get_parent()?;
313319
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-
331320
parent_readdir
332321
}
333322
};
334323

324+
// If `parent_readdir` was now or previously opened via `get_parent()`
325+
// we need to verify the grandparent (dev, inode) pair as well to protect
326+
// against the situation that the child directory was moved somewhere
327+
// else and that the parent just happens to have the same reused
328+
// (dev, inode) pair, that we found descending.
329+
if !parent_readdir.is_open() && readdir_cache.is_empty() {
330+
let grandparent_readdir = parent_readdir.get_parent()?;
331+
if let Some(grandparent_component) = path_components.last() {
332+
grandparent_component.verify_dev_ino(grandparent_readdir.as_fd())?;
333+
readdir_cache.push_back(grandparent_readdir);
334+
} else {
335+
// verify parent of the deletion root directory
336+
root_parent_component.verify_dev_ino(grandparent_readdir.as_fd())?;
337+
}
338+
}
339+
335340
// remove now empty directory
336341
cvt(unsafe {
337342
unlinkat(

0 commit comments

Comments
 (0)