Message414871
```python
#!/usr/bin/env python3
import os
import tempfile
def createUnremovableDir(workdir):
print(workdir)
os.mkdir(f'{workdir}/mydir')
os.symlink('/bin/bash', f'{workdir}/mydir/mylink') # Symlink to a root owned file
os.chmod(f'{workdir}/mydir', 0o555)
with tempfile.TemporaryDirectory() as workdir:
createUnremovableDir(workdir)
```
Fails because `tempfile.TemporaryDirectory._rmtree` tries to execute os.chmod(path, 0o700) on the symlink, which by default tries to change the root owned file symlink target instead of the symlink itself:
```
/tmp/tmp1_dy42ef
Traceback (most recent call last):
File "/usr/lib/python3.9/shutil.py", line 682, in _rmtree_safe_fd
os.unlink(entry.name, dir_fd=topfd)
PermissionError: [Errno 13] Permission denied: 'mylink'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "~/tempfile_demo_bug.py", line 13, in <module>
createUnremovableDir(workdir)
File "/usr/lib/python3.9/tempfile.py", line 969, in __exit__
self.cleanup()
File "/usr/lib/python3.9/tempfile.py", line 973, in cleanup
self._rmtree(self.name)
File "/usr/lib/python3.9/tempfile.py", line 955, in _rmtree
_rmtree(name, onerror=onerror)
File "/usr/lib/python3.9/shutil.py", line 727, in rmtree
_rmtree_safe_fd(fd, path, onerror)
File "/usr/lib/python3.9/shutil.py", line 664, in _rmtree_safe_fd
_rmtree_safe_fd(dirfd, fullname, onerror)
File "/usr/lib/python3.9/shutil.py", line 684, in _rmtree_safe_fd
onerror(os.unlink, fullname, sys.exc_info())
File "/usr/lib/python3.9/tempfile.py", line 941, in onerror
resetperms(path)
File "/usr/lib/python3.9/tempfile.py", line 936, in resetperms
_os.chmod(path, 0o700)
PermissionError: [Errno 1] Operation not permitted: '/tmp/tmp1_dy42ef/mydir/mylink'
```
and leaves:
```
(.venv python 3.9.9) $ find /tmp/tmp1_dy42ef -ls
148228 4 drwx------ 3 myuser myuser 4096 Mar 10 16:54 /tmp/tmp1_dy42ef
148229 4 drwx------ 2 myuser myuser 4096 Mar 10 16:54 /tmp/tmp1_dy42ef/mydir
148230 0 lrwxrwxrwx 1 myuser myuser 9 Mar 10 16:54 /tmp/tmp1_dy42ef/mydir/mylink -> /bin/bash
```
This fixes it:
``` python
#!/usr/bin/env python3
import os
import tempfile
def createUnremovableDir(workdir):
print(workdir)
os.mkdir(f'{workdir}/mydir')
os.symlink('/bin/bash', f'{workdir}/mydir/mylink') # Symlink to a root owned file
os.chmod(f'{workdir}/mydir', 0o555)
def _rmtree(cls, name, ignore_errors=False):
def onerror(func, path, exc_info):
if issubclass(exc_info[0], PermissionError):
def resetperms(path):
try:
if os.chflags in os.supports_follow_symlinks: # This is the patch
os.chflags(path, 0, follow_symlinks=False) # This is the patch
elif not os.path.islink(path): # This is the patch
os.chflags(path, 0)
except AttributeError:
pass
if os.chmod in os.supports_follow_symlinks: # This is the patch
os.chmod(path, 0o700, follow_symlinks=False) # This is the patch
elif not os.path.islink(path): # This is the patch
os.chmod(path, 0o700)
try:
if path != name:
resetperms(os.path.dirname(path))
resetperms(path)
try:
os.unlink(path)
# PermissionError is raised on FreeBSD for directories
except (IsADirectoryError, PermissionError):
cls._rmtree(path, ignore_errors=ignore_errors)
except FileNotFoundError:
pass
elif issubclass(exc_info[0], FileNotFoundError):
pass
else:
if not ignore_errors:
raise
shutil.rmtree(name, onerror=onerror)
# Monkey patch the class method tempfile.TemporaryDirectory._rmtree
from types import MethodType
import shutil
tempfile.TemporaryDirectory._rmtree = MethodType(_rmtree, tempfile.TemporaryDirectory)
with tempfile.TemporaryDirectory() as workdir:
createUnremovableDir(workdir) |
|
Date |
User |
Action |
Args |
2022-03-10 17:22:08 | afeblot | set | recipients:
+ afeblot |
2022-03-10 17:22:08 | afeblot | set | messageid: <1646932928.52.0.00833614207853.issue46977@roundup.psfhosted.org> |
2022-03-10 17:22:08 | afeblot | link | issue46977 messages |
2022-03-10 17:22:08 | afeblot | create | |
|