@@ -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