Skip to content

Unix: create the auxiliary FUSE mount point with mkdtemp - #1966

Open
flatstik wants to merge 4 commits into
veracrypt:masterfrom
flatstik:fix-1960-aux-mount-point
Open

flatstik wants to merge 4 commits into
veracrypt:masterfrom
flatstik:fix-1960-aux-mount-point

Conversation

@flatstik

@flatstik flatstik commented Oct 27, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #1960.

Outside FUSE-T builds, the auxiliary mount point was the first /tmp/.veracrypt_aux_mntN not listed in the mount table, deleted and created again with mkdir, so parallel mounts could pick the same directory and any local user could block mounting by creating the 256 directories. It is now created with mkdtemp, as FUSE-T builds already do. The name keeps the .veracrypt_aux_mnt prefix that identifies auxiliary mounts. Its mode is not changed by pathname afterwards (0700 from mkdtemp instead of 0500), since the temporary directory can belong to the user with pam_tmpdir.

Without --slot, two mounts at the same time could also choose the same free slot, so the second file system was mounted over the first at /media/veracryptN (with kernel crypto, both used the device-mapper name veracryptN). A second commit takes an exclusive flock for the slot in the root owned /var/run/veracrypt before mounting, held by the FUSE service until it exits: an automatically chosen slot that another mount holds is replaced by the next free one (with its default mount point), and a slot given with --slot is retried for up to 10 s and then reported as unavailable. The lock file is opened by OpenMountLockFile, which #1967 uses as well.

Tested:

  • OpenWrt 25.12.6 mipsel (FUSE3, root), 40 rounds of two parallel mounts: 1.26.30 had failures in each run (ParameterIncorrect at MountVolume:1463, fuse: mount failed) and once a volume at the other volume's mount point; with this change 0 failed and 0 swapped, and a foreign /tmp/.veracrypt_aux_mnt1 does not prevent mounting.
  • Tests/test_linux_parallel_mounts.py (new, run in the Linux workflow), which also mounts two volumes in parallel without --slot or a mount point, through FUSE and with kernel crypto: passes on ubuntu-24.04 and ubuntu-26.04 with these commits, https://github.com/flatstik/VeraCrypt/actions/runs/40577013454; without the slot lock the rounds without --slot fail (both volumes in slot 1 at /media/veracrypt1), https://github.com/flatstik/VeraCrypt/actions/runs/40580352709.
  • The change also applies to FreeBSD, OpenBSD and macOS with macFUSE, not built or tested there.

The new test adds lines next to test_mount_helper.py in .github/workflows/build-linux.yml, as do the other PRs split from #1963, so whichever is merged later conflicts there; I will rebase it.

Split from #1963, with #1968 (#1958), #1967 (#1959), #1964 (#1961), #1965 (#1962).

@curious-rabbit

Copy link
Copy Markdown
Contributor

Parallel mounts without --slot still collide. Both get the same slot from GetFirstFreeSlotNumber. The second filesystem is mounted over the first at /media/veracrypt1. With kernel crypto both use the dm name veracrypt1.

@flatstik
flatstik force-pushed the fix-1960-aux-mount-point branch from ceecf75 to 10ca32d Compare October 27, 2026 20:59
@flatstik

Copy link
Copy Markdown
Contributor Author

Right, thanks. Added a commit that reserves the slot with a lock held by the FUSE service: an automatically chosen slot that another mount holds is replaced by the next free one, and --slot waits up to 10 s and then fails. The test now also mounts in parallel without --slot, through FUSE and with kernel crypto; without the lock it reproduces the collision (both volumes in slot 1 at /media/veracrypt1), https://github.com/flatstik/VeraCrypt/actions/runs/40580352709, and passes with it, https://github.com/flatstik/VeraCrypt/actions/runs/40577013454.

@idrassi idrassi left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please address the issues below.

For integration with #1967, the rebase request I left there still applies.

Comment thread src/Core/Unix/CoreUnix.cpp Outdated
Comment thread src/Core/Unix/CoreUnix.cpp Outdated
Comment thread src/Core/Unix/CoreUnix.cpp Outdated
Comment thread Tests/test_linux_parallel_mounts.py
Comment thread Tests/test_linux_parallel_mounts.py Outdated
@flatstik
flatstik force-pushed the fix-1960-aux-mount-point branch from 10ca32d to 19fac98 Compare October 28, 2026 21:36
Outside FUSE-T builds, the auxiliary mount point was the first
/tmp/.veracrypt_aux_mntN not listed in the mount table, deleted and
created again with mkdir. Two volumes mounted at the same time could
pick the same directory, so a mount failed or the file system of one
volume was mounted at the mount point of the other, also across users.
Any local user could block all mounts by creating the 256 directories.

Create a new directory with mkdtemp, as FUSE-T builds already do. The
name keeps the .veracrypt_aux_mnt prefix that identifies auxiliary
mounts. mkdtemp creates it with mode 0700 instead of the previous 0500,
which makes no difference to other users, so its mode is not changed by
pathname afterwards, which could follow a replaced directory when the
temporary directory belongs to the user (pam_tmpdir).

Fixes veracrypt#1960
Without --slot, a mount takes the first slot that no mounted volume
uses. Two mounts at the same time could choose the same slot, so the
second file system was mounted over the first at /media/veracryptN, and
with kernel crypto both used the device-mapper name veracryptN.

Take an exclusive flock for the slot in the root owned
/var/run/veracrypt before mounting. The FUSE service inherits the
descriptor and holds the lock until it exits. If the slot was chosen
automatically and another mount holds it, the next free slot is taken
(with its default mount point). A slot given with --slot is retried for
up to 10 seconds, because a normally dismounted service may still be
exiting, and is then reported as unavailable. Without root or a usable
lock directory, mounting works as before.
Without --slot, a mount with a custom mount directory also takes the
first free slot, but it was handled like a slot given with --slot: when
a parallel mount held that slot, it waited for 10 seconds and failed
while other slots were free. A slot is now chosen automatically whenever
--slot is not given, unless a default mount point names it, and the
directory given by the user is kept when another slot is taken.
--auto-mount=devices leaves the choice to the core in the same way.

The slot was also checked for availability before it was reserved, so a
mount published in between made the request fail. The slot is now
reserved first and then checked; an automatically chosen slot that turns
out to be taken is released and the next free one is tried.

A mount for which the slot cannot be reserved, because the lock
directory cannot be used or flock fails unexpectedly, is now refused,
also when it is read-only: it could still use the same default mount
point and device-mapper name as another mount.

The lock directory must belong to the user running VeraCrypt, root,
and be writable only by it. CoreUnix::GetMountLockDirectory() gives its
location, which the unprivileged mount test overrides, so that it uses
the production locks instead of failing to create /var/run/veracrypt.
Tests/test_linux_parallel_mounts.py checks parallel mounts and an
existing /tmp/.veracrypt_aux_mnt1 against the installed package in
the Linux workflow.
@flatstik
flatstik force-pushed the fix-1960-aux-mount-point branch from 19fac98 to 5ed3f04 Compare October 29, 2026 10:53
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.

Two volumes mounted at the same time can fail or end up at the wrong mount point

3 participants