[issue46478] DirEntry.stat() of os.scandir() has no dir_fd parameter
STINNER Victor
report at bugs.python.org
Sat Jan 22 22:38:48 EST 2022
New submission from STINNER Victor <vstinner at python.org>:
I read the Rust CVE-2022-21658 vulnerability of std::fs::remove_dir_all:
https://blog.rust-lang.org/2022/01/20/cve-2022-21658.html
It's a race condition if an attacker replaces a directory with a symlink while Rust is removing the parent directory, Rust follows the symlink rather than just removing the symlink.
shutil._rmtree_safe_fd() uses os.scandir(). If entry.is_dir(follow_symlinks=False) is true, it calls entry.stat(follow_symlinks=False). It opens the directory as a file to remove the directory. It checks os.path.samestat(orig_st, os.fstat(dirfd)): if it's false, it raises an exception:
try:
# This can only happen if someone replaces
# a directory with a symlink after the call to
# os.scandir or stat.S_ISDIR above.
raise OSError("Cannot call rmtree on a symbolic "
"link")
except OSError:
onerror(os.path.islink, fullname, sys.exc_info())
I understand that this check is in place to detect the Rust CVE-2022-21658 vulnerability.
I noticed that the first entry.is_dir(follow_symlinks=False) call does a stat() syscall, but it doesn't pass the directory file descriptor. It would be even safer to pass it, just in case if the parent directory has been modified in the meanwhile as well.
----------
components: Library (Lib)
messages: 411338
nosy: serhiy.storchaka, vstinner
priority: normal
severity: normal
status: open
title: DirEntry.stat() of os.scandir() has no dir_fd parameter
versions: Python 3.11
_______________________________________
Python tracker <report at bugs.python.org>
<https://bugs.python.org/issue46478>
_______________________________________
More information about the Python-bugs-list
mailing list