Skip to content
Snippets Groups Projects
  • Jonathan Wakely's avatar
    c8bd4dc8
    libstdc++: Avoid symlink race in filesystem::remove_all [PR104161] · c8bd4dc8
    Jonathan Wakely authored
    This adds a new internal flag to the filesystem::directory_iterator
    constructor that makes it fail if the path is a symlink that resolves to
    a directory. This prevents filesystem::remove_all from following a
    symlink to a directory, rather than deleting the symlink itself.
    
    We can also use that new flag in recursive_directory_iterator to ensure
    that we don't follow symlinks if the follow_directory_symlink option is
    not set.
    
    This also moves an error check in filesystem::remove_all after the while
    loop, so that errors from the directory_iterator constructor are
    reproted, instead of continuing to the filesystem::remove call below.
    
    libstdc++-v3/ChangeLog:
    
    	PR libstdc++/104161
    	* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for
    	fdopendir.
    	* config.h.in: Regenerate.
    	* configure: Regenerate.
    	* src/c++17/fs_dir.cc (_Dir): Add nofollow flag to constructor
    	and pass it to base class constructor.
    	(directory_iterator): Pass nofollow flag to _Dir constructor.
    	(fs::recursive_directory_iterator::increment): Likewise.
    	* src/c++17/fs_ops.cc (do_remove_all): Use nofollow option for
    	directory_iterator constructor. Move error check outside loop.
    	* src/filesystem/dir-common.h (_Dir_base): Add nofollow flag to
    	constructor and when it's set use ::open with O_NOFOLLOW and
    	O_DIRECTORY.
    	* src/filesystem/dir.cc (_Dir): Add nofollow flag to constructor
    	and pass it to base class constructor.
    	(directory_iterator): Pass nofollow flag to _Dir constructor.
    	(fs::recursive_directory_iterator::increment): Likewise.
    	* src/filesystem/ops.cc (remove_all): Use nofollow option for
    	directory_iterator constructor. Move error check outside loop.
    c8bd4dc8
    History
    libstdc++: Avoid symlink race in filesystem::remove_all [PR104161]
    Jonathan Wakely authored
    This adds a new internal flag to the filesystem::directory_iterator
    constructor that makes it fail if the path is a symlink that resolves to
    a directory. This prevents filesystem::remove_all from following a
    symlink to a directory, rather than deleting the symlink itself.
    
    We can also use that new flag in recursive_directory_iterator to ensure
    that we don't follow symlinks if the follow_directory_symlink option is
    not set.
    
    This also moves an error check in filesystem::remove_all after the while
    loop, so that errors from the directory_iterator constructor are
    reproted, instead of continuing to the filesystem::remove call below.
    
    libstdc++-v3/ChangeLog:
    
    	PR libstdc++/104161
    	* acinclude.m4 (GLIBCXX_CHECK_FILESYSTEM_DEPS): Check for
    	fdopendir.
    	* config.h.in: Regenerate.
    	* configure: Regenerate.
    	* src/c++17/fs_dir.cc (_Dir): Add nofollow flag to constructor
    	and pass it to base class constructor.
    	(directory_iterator): Pass nofollow flag to _Dir constructor.
    	(fs::recursive_directory_iterator::increment): Likewise.
    	* src/c++17/fs_ops.cc (do_remove_all): Use nofollow option for
    	directory_iterator constructor. Move error check outside loop.
    	* src/filesystem/dir-common.h (_Dir_base): Add nofollow flag to
    	constructor and when it's set use ::open with O_NOFOLLOW and
    	O_DIRECTORY.
    	* src/filesystem/dir.cc (_Dir): Add nofollow flag to constructor
    	and pass it to base class constructor.
    	(directory_iterator): Pass nofollow flag to _Dir constructor.
    	(fs::recursive_directory_iterator::increment): Likewise.
    	* src/filesystem/ops.cc (remove_all): Use nofollow option for
    	directory_iterator constructor. Move error check outside loop.