summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Coghlan <ncoghlan@gmail.com>2012-06-24 06:43:06 (GMT)
committerNick Coghlan <ncoghlan@gmail.com>2012-06-24 06:43:06 (GMT)
commit5b0eca116ad1b9509ebe4620f1685d86ce4433bf (patch)
tree06028b901fd8bd82fb14cf108c399b8626dce196
parent8e5c0a774fd8c51fdf5654a6d6688a09e62d6c5e (diff)
downloadcpython-5b0eca116ad1b9509ebe4620f1685d86ce4433bf.zip
cpython-5b0eca116ad1b9509ebe4620f1685d86ce4433bf.tar.gz
cpython-5b0eca116ad1b9509ebe4620f1685d86ce4433bf.tar.bz2
Issue #4489: Rename the feature marker for the symlink resistant rmtree and store it as a function attribute
-rw-r--r--Doc/library/shutil.rst29
-rw-r--r--Doc/whatsnew/3.3.rst5
-rw-r--r--Lib/shutil.py8
-rw-r--r--Lib/test/test_shutil.py4
4 files changed, 28 insertions, 18 deletions
diff --git a/Doc/library/shutil.rst b/Doc/library/shutil.rst
index 5521841..7526e5e 100644
--- a/Doc/library/shutil.rst
+++ b/Doc/library/shutil.rst
@@ -190,14 +190,15 @@ Directory and files operations
handled by calling a handler specified by *onerror* or, if that is omitted,
they raise an exception.
- .. warning::
+ .. note::
- The default :func:`rmtree` function is susceptible to a symlink attack:
- given proper timing and circumstances, attackers can use it to delete
- files they wouldn't be able to access otherwise. Thus -- on platforms
- that support the necessary fd-based functions -- a safe version of
- :func:`rmtree` is used, which isn't vulnerable. In this case
- :data:`rmtree_is_safe` is set to True.
+ On platforms that support the necessary fd-based functions a symlink
+ attack resistant version of :func:`rmtree` is used by default. On other
+ platforms, the :func:`rmtree` implementation is susceptible to a
+ symlink attack: given proper timing and circumstances, attackers can
+ manipulate symlinks on the filesystem to delete files they wouldn't
+ be able to access otherwise. Applications can use the :data:`rmtree.avoids_symlink_attacks` function attribute to
+ determine which case applies.
If *onerror* is provided, it must be a callable that accepts three
parameters: *function*, *path*, and *excinfo*.
@@ -209,16 +210,16 @@ Directory and files operations
:func:`sys.exc_info`. Exceptions raised by *onerror* will not be caught.
.. versionchanged:: 3.3
- Added a safe version that is used automatically if platform supports
- fd-based functions.
+ Added a symlink attack resistant version that is used automatically
+ if platform supports fd-based functions.
-.. data:: rmtree_is_safe
+ .. data:: rmtree.avoids_symlink_attacks
- Indicates whether the current platform and implementation has a symlink
- attack-proof version of :func:`rmtree`. Currently this is only true for
- platforms supporting fd-based directory access functions.
+ Indicates whether the current platform and implementation provides a
+ symlink attack resistant version of :func:`rmtree`. Currently this is
+ only true for platforms supporting fd-based directory access functions.
- .. versionadded:: 3.3
+ .. versionadded:: 3.3
.. function:: move(src, dst)
diff --git a/Doc/whatsnew/3.3.rst b/Doc/whatsnew/3.3.rst
index 25a0ece..e97ac86 100644
--- a/Doc/whatsnew/3.3.rst
+++ b/Doc/whatsnew/3.3.rst
@@ -1296,6 +1296,11 @@ shutil
acts on the symlink itself (or creates one, if relevant).
(Contributed by Hynek Schlawack in :issue:`12715`.)
+* :func:`~shutil.rmtree` is now resistant to symlink attacks on platforms
+ which support the new ``dir_fd`` parameter in :func:`os.open` and
+ :func:`os.unlinkat`. (Contributed by Martin von Löwis and Hynek Schlawack
+ in :issue:`4489`.)
+
signal
diff --git a/Lib/shutil.py b/Lib/shutil.py
index f743d05..2c00f4a 100644
--- a/Lib/shutil.py
+++ b/Lib/shutil.py
@@ -405,8 +405,9 @@ def _rmtree_safe_fd(topfd, path, onerror):
except os.error:
onerror(os.rmdir, path, sys.exc_info())
-rmtree_is_safe = _use_fd_functions = (os.unlink in os.supports_dir_fd and
- os.open in os.supports_dir_fd)
+_use_fd_functions = (os.unlink in os.supports_dir_fd and
+ os.open in os.supports_dir_fd)
+
def rmtree(path, ignore_errors=False, onerror=None):
"""Recursively delete a directory tree.
@@ -449,6 +450,9 @@ def rmtree(path, ignore_errors=False, onerror=None):
else:
return _rmtree_unsafe(path, onerror)
+# Allow introspection of whether or not the hardening against symlink
+# attacks is supported on the current platform
+rmtree.avoids_symlink_attacks = _use_fd_functions
def _basename(path):
# A basename() variant which first strips the trailing slash, if present.
diff --git a/Lib/test/test_shutil.py b/Lib/test/test_shutil.py
index b2ac0cf..067889e 100644
--- a/Lib/test/test_shutil.py
+++ b/Lib/test/test_shutil.py
@@ -487,7 +487,7 @@ class TestShutil(unittest.TestCase):
def test_rmtree_uses_safe_fd_version_if_available(self):
if os.unlink in os.supports_dir_fd and os.open in os.supports_dir_fd:
self.assertTrue(shutil._use_fd_functions)
- self.assertTrue(shutil.rmtree_is_safe)
+ self.assertTrue(shutil.rmtree.avoids_symlink_attacks)
tmp_dir = self.mkdtemp()
d = os.path.join(tmp_dir, 'a')
os.mkdir(d)
@@ -502,7 +502,7 @@ class TestShutil(unittest.TestCase):
shutil._rmtree_safe_fd = real_rmtree
else:
self.assertFalse(shutil._use_fd_functions)
- self.assertFalse(shutil.rmtree_is_safe)
+ self.assertFalse(shutil.rmtree.avoids_symlink_attacks)
def test_rmtree_dont_delete_file(self):
# When called on a file instead of a directory, don't delete it.