Skip to content

Commit

Permalink
Store and compare with stat.st_dev as well when going back up via ..
Browse files Browse the repository at this point in the history
  • Loading branch information
hkratz committed Jan 30, 2022
1 parent 424189d commit 65b740c
Showing 1 changed file with 11 additions and 4 deletions.
15 changes: 11 additions & 4 deletions library/std/src/sys/unix/fs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1487,6 +1487,7 @@ mod remove_dir_impl {
use crate::sync::Arc;
use crate::sys::{cvt, cvt_r};
use alloc::collections::VecDeque;
use libc::dev_t;

#[cfg(not(all(target_os = "macos", target_arch = "x86_64"),))]
use libc::{fdopendir, openat, unlinkat};
Expand Down Expand Up @@ -1640,27 +1641,33 @@ mod remove_dir_impl {

struct DirComponent {
name: CString,
dev: dev_t,
ino: u64,
}

fn readdir_open_path(path: &CStr) -> io::Result<(DirComponent, CachedReadDir)> {
let dir_fd = openat_nofollow_dironly(None, path)?;

// use fstat() to get the inode of the directory
// use fstat() to get dev, inode of the directory
let mut stat = unsafe { mem::zeroed() };
cvt(unsafe { fstat64(dir_fd.as_raw_fd(), &mut stat) })?;
let cached_readdir = fdreaddir(dir_fd)?;
Ok((DirComponent { name: CString::new("")?, ino: stat.st_ino }, cached_readdir))
Ok((
DirComponent { name: CString::new("")?, dev: stat.st_dev, ino: stat.st_ino },
cached_readdir,
))
}

fn readdir_open_child(
readdir: &CachedReadDir,
child: &DirEntry,
) -> io::Result<(DirComponent, CachedReadDir)> {
let dir_fd = openat_nofollow_dironly(Some(readdir.as_fd()), child.name_cstr())?;
let mut stat = unsafe { mem::zeroed() };
cvt(unsafe { fstat64(dir_fd.as_raw_fd(), &mut stat) })?;
let cached_readdir = fdreaddir(dir_fd)?;
Ok((
DirComponent { name: child.name_cstr().into(), ino: child.entry.d_ino },
DirComponent { name: child.name_cstr().into(), dev: stat.st_dev, ino: stat.st_ino },
cached_readdir,
))
}
Expand All @@ -1676,7 +1683,7 @@ mod remove_dir_impl {
cvt(unsafe { fstat64(parent_dir_fd.as_raw_fd(), &mut stat) })?;
// Make sure that the reopened parent directory has the same inode as when we visited it descending
// the directory tree. More detailed risk analysis TBD.
if expected_parent_dir.ino != stat.st_ino {
if expected_parent_dir.dev != stat.st_dev || expected_parent_dir.ino != stat.st_ino {
return Err(io::Error::new(
io::ErrorKind::Uncategorized,
"parent directory inode does not match",
Expand Down

0 comments on commit 65b740c

Please sign in to comment.