Skip to content

Unix: check mount points that do not exist yet through their parents - #1974

Closed
flatstik wants to merge 2 commits into
veracrypt:masterfrom
flatstik:fix-1973-mount-point
Closed

flatstik wants to merge 2 commits into
veracrypt:masterfrom
flatstik:fix-1973-mount-point

Conversation

@flatstik

Copy link
Copy Markdown
Contributor

Fixes #1973.

The protected mount point check (CVE-2025-23021) compared the unresolved path when realpath() failed, that is, when the mount point did not exist yet, so a new mount point reaching a protected directory through .. or a symbolic link passed. Every path starting with the default prefix was then created with mkdir(), chowned and later removed by pathname, following the same .. or link.

  • IsProtectedSystemDirectory and IsDirectoryOnUserPath resolve the longest existing part of the mount point and append the rest. A mount point whose missing part contains . or .. is refused, since it cannot be checked.
  • Only exact default mount points (<prefix>N, IsDefaultMountPoint) are created, chowned and removed, and used to derive the slot, instead of every path starting with the prefix.
  • A default mount point is created with mkdirat() in a parent directory that only root can change (checked with fstat() on its descriptor), opened without following links and given to the user with fchown(), as the FUSE-T auxiliary directories are handled, so the path is not resolved again between the checks, mkdir() and chown(). A prefix whose parent other users can change (through VERACRYPT_MOUNT_PREFIX) is refused instead of creating mount points there.

The macOS path is unchanged: it does not create mount points itself.

Tested with Tests/test_linux_mount_point_protection.py (new, run in the Linux workflow), both reproductions from the issue plus an existing directory inside a mounted volume as mount point and a default mount point:

Not tested on FreeBSD or OpenBSD, which share the mount point creation.

@flatstik
flatstik force-pushed the fix-1973-mount-point branch 2 times, most recently from 116ddd1 to fee6387 Compare October 28, 2026 23:16
The protected mount point check (CVE-2025-23021) compared the unresolved
path when realpath() failed, that is, when the mount point did not exist
yet. Such a path passed when it reached a protected directory through
".." or a symbolic link, for example a link to /etc inside a volume
mounted at /media/veracrypt1, or a favorite mount point with "..".
Paths starting with the default prefix were then created with mkdir(),
which followed them, chowned to the user and mounted on, and the
directory remained after dismount.

Resolve the longest existing part of a mount point and append the rest,
and refuse a mount point whose missing part contains "." or "..", or
that cannot be resolved for another reason than a missing directory. The
check for directories on the user's PATH resolves paths the same way.

Create, chown and remove only exact default mount points (<prefix>N),
rather than every path starting with the prefix. A default mount point
is created with mkdirat() in a parent directory that only root can
change, and given to the user with fchown() through a descriptor opened
without following links.

Fixes veracrypt#1973
Tests/test_linux_mount_point_protection.py checks that a volume cannot
be mounted on a new directory under /etc through a symbolic link in a
mounted volume or a favorite mount point with "..", that an existing
directory in a mounted volume can still be used, and that a default
mount point is created for the user and removed after dismount.
@flatstik
flatstik force-pushed the fix-1973-mount-point branch from fee6387 to d1d9730 Compare October 28, 2026 23:16
@idrassi

idrassi commented Oct 29, 2026

Copy link
Copy Markdown
Member

Thanks for working on this. I assigned the issue to myself when it was opened to let people know I was working on it, though that was probably easy to miss. So, I had already started on my fix before you opened this PR, and I have now pushed it as d18cb6f.

Your test complements mine by exercising real mounts as root, so I have cherry picked it as 9d599af, preserving your authorship. I ran it against my fix and all checks passed. Thanks for adding that coverage.

@idrassi idrassi closed this Oct 29, 2026
@flatstik

Copy link
Copy Markdown
Contributor Author

Thanks for taking the test, and sorry for missing that the issue was assigned to you. I will check assignees before starting on an issue.

@flatstik
flatstik deleted the fix-1973-mount-point branch October 29, 2026 10:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Linux: protected mount point check can be bypassed for not-yet-existing paths ('..' or symlink under /media/veracryptN)

2 participants