Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/changelog/3013.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix TOCTOU vulnerabilities in app_data and lock directory creation that could be exploited via symlink attacks - reported by :user:`tsigouris007`, fixed by :user:`gaborbernat`.
11 changes: 5 additions & 6 deletions src/virtualenv/app_data/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,11 @@ def make_app_data(folder, **kwargs):
if is_read_only:
return ReadOnlyAppData(folder)

if not os.path.isdir(folder):
try:
os.makedirs(folder)
LOGGER.debug("created app data folder %s", folder)
except OSError as exception:
LOGGER.info("could not create app data folder %s due to %r", folder, exception)
try:
os.makedirs(folder, exist_ok=True)
LOGGER.debug("created app data folder %s", folder)
except OSError as exception:
LOGGER.info("could not create app data folder %s due to %r", folder, exception)

if os.access(folder, os.W_OK):
return AppDataDiskFolder(folder)
Expand Down
7 changes: 3 additions & 4 deletions src/virtualenv/util/lock.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@
class _CountedFileLock(FileLock):
def __init__(self, lock_file) -> None:
parent = os.path.dirname(lock_file)
if not os.path.isdir(parent):
with suppress(OSError):
os.makedirs(parent)
with suppress(OSError):
os.makedirs(parent, exist_ok=True)

super().__init__(lock_file)
self.count = 0
Expand Down Expand Up @@ -117,7 +116,7 @@ def _lock_file(self, lock, no_block=False): # noqa: FBT002
# a lock, but that lock might then become expensive, and it's not clear where that lock should live.
# Instead here we just ignore if we fail to create the directory.
with suppress(OSError):
os.makedirs(str(self.path))
os.makedirs(str(self.path), exist_ok=True)

try:
lock.acquire(0.0001)
Expand Down
Loading