@@ -1487,6 +1487,7 @@ mod remove_dir_impl {
14871487 use crate :: sync:: Arc ;
14881488 use crate :: sys:: { cvt, cvt_r} ;
14891489 use alloc:: collections:: VecDeque ;
1490+ use libc:: dev_t;
14901491
14911492 #[ cfg( not( all( target_os = "macos" , target_arch = "x86_64" ) , ) ) ]
14921493 use libc:: { fdopendir, openat, unlinkat} ;
@@ -1640,27 +1641,33 @@ mod remove_dir_impl {
16401641
16411642 struct DirComponent {
16421643 name : CString ,
1644+ dev : dev_t ,
16431645 ino : u64 ,
16441646 }
16451647
16461648 fn readdir_open_path ( path : & CStr ) -> io:: Result < ( DirComponent , CachedReadDir ) > {
16471649 let dir_fd = openat_nofollow_dironly ( None , path) ?;
16481650
1649- // use fstat() to get the inode of the directory
1651+ // use fstat() to get dev, inode of the directory
16501652 let mut stat = unsafe { mem:: zeroed ( ) } ;
16511653 cvt ( unsafe { fstat64 ( dir_fd. as_raw_fd ( ) , & mut stat) } ) ?;
16521654 let cached_readdir = fdreaddir ( dir_fd) ?;
1653- Ok ( ( DirComponent { name : CString :: new ( "" ) ?, ino : stat. st_ino } , cached_readdir) )
1655+ Ok ( (
1656+ DirComponent { name : CString :: new ( "" ) ?, dev : stat. st_dev , ino : stat. st_ino } ,
1657+ cached_readdir,
1658+ ) )
16541659 }
16551660
16561661 fn readdir_open_child (
16571662 readdir : & CachedReadDir ,
16581663 child : & DirEntry ,
16591664 ) -> io:: Result < ( DirComponent , CachedReadDir ) > {
16601665 let dir_fd = openat_nofollow_dironly ( Some ( readdir. as_fd ( ) ) , child. name_cstr ( ) ) ?;
1666+ let mut stat = unsafe { mem:: zeroed ( ) } ;
1667+ cvt ( unsafe { fstat64 ( dir_fd. as_raw_fd ( ) , & mut stat) } ) ?;
16611668 let cached_readdir = fdreaddir ( dir_fd) ?;
16621669 Ok ( (
1663- DirComponent { name : child. name_cstr ( ) . into ( ) , ino : child . entry . d_ino } ,
1670+ DirComponent { name : child. name_cstr ( ) . into ( ) , dev : stat . st_dev , ino : stat . st_ino } ,
16641671 cached_readdir,
16651672 ) )
16661673 }
@@ -1676,7 +1683,7 @@ mod remove_dir_impl {
16761683 cvt ( unsafe { fstat64 ( parent_dir_fd. as_raw_fd ( ) , & mut stat) } ) ?;
16771684 // Make sure that the reopened parent directory has the same inode as when we visited it descending
16781685 // the directory tree. More detailed risk analysis TBD.
1679- if expected_parent_dir. ino != stat. st_ino {
1686+ if expected_parent_dir. dev != stat . st_dev || expected_parent_dir . ino != stat. st_ino {
16801687 return Err ( io:: Error :: new (
16811688 io:: ErrorKind :: Uncategorized ,
16821689 "parent directory inode does not match" ,
0 commit comments