Repository navigation
Conversation
…lume MountVolume released the outer volume password once the volume was open, but kept the protection password referenced by the mount request. The forked FUSE service inherited it, so the hidden volume password stayed in plaintext in both service processes until dismount. Release it at the same points as the outer volume password. Fixes veracrypt#1961
--create-keyfile and --backup-headers opened the destination with O_CREAT|O_TRUNC without checking whether it existed. Recreating an existing keyfile replaced it with new random data, so every volume that used it could no longer be mounted, and an existing file chosen for a header backup was truncated. Ask before replacing an existing file, as the graphical interface does, and as text mode already does for new containers (4edad72). With --non-interactive the operation fails instead, and --force overwrites without asking. The keyfile prompt is shown before the random pool is enriched, so a refusal does not waste that input. Fixes veracrypt#1962
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
…open An emergency dismount lazily detaches the file systems. The FUSE service keeps running with the volume open until the last file on the detached file system is closed, but the volume is no longer in the mount table, so it could be mounted again and two services wrote to it. Once the volume is open, take an exclusive flock for it. The FUSE service inherits the descriptor and holds the lock until it exits; a second mount fails with "already mounted" meanwhile. Because a normally dismounted service may still be exiting, a busy lock is retried for up to 10 seconds. The lock is named after the device number, or the file system and inode numbers, that fstat reports for the opened volume, so it applies to the file actually served, whatever path leads to it. It is not taken on the volume file itself, whose locking is disabled to avoid remote file system issues. The lock files are created with openat in the root owned /var/run/veracrypt, which is opened without following symbolic links and checked through its descriptor. /var/run also exists on systems without /run. Without root or a usable lock directory, mounting works as before. Fixes veracrypt#1959
SecureBuffer only erased its memory when freed. The FUSE service that holds the master keys had no locked memory and could be core dumped, and a core file of it contained both halves of the master key. Give each SecureBuffer whole pages of its own, lock them with mlock and exclude them from core dumps (MADV_DONTDUMP, or MADV_NOCORE on FreeBSD). Separate pages let a freed buffer be unlocked without affecting another one. Memory locks are not inherited by fork, so the FUSE service locks the live buffers again once FUSE has started it in the background. If RLIMIT_MEMLOCK does not allow locking, the buffers are used unlocked as before. Key material can also be copied outside SecureBuffer, so the core service and the FUSE service additionally disable core dumps: they set RLIMIT_CORE to 0 and, on Linux, clear the dumpable flag, which a core_pattern pipe does not ignore. Volume::WriteSectors encrypts each write in a buffer that is encrypted in place right after the copy. Allocating it as a SecureBuffer would lock and unlock its pages on every write and cut write throughput by about 20 to 60 percent depending on the write size, so it becomes a Buffer that is still erased when freed. Fixes veracrypt#1958
flatstik
force-pushed
the
unix-security-fixes
branch
from
October 27, 2026 03:55
4ca66b3 to
7872271
Compare
Contributor
Author
|
Updated after rereading the review of #1931, which asked that a directory checked by pathname not be used by pathname afterwards:
The other commits are unchanged. Retested on the OpenWrt router with the same results as in the description. |
Run against the installed package as root in the Linux workflow: locked memory and no core file for the FUSE service (veracrypt#1958), no second mount while an emergency-detached service keeps the volume open (veracrypt#1959), parallel mounts and an existing /tmp/.veracrypt_aux_mnt1 (veracrypt#1960), the hidden volume protection password in the service memory (veracrypt#1961), and the overwrite checks of --create-keyfile and --backup-headers (veracrypt#1962).
Contributor
Author
|
Added the regression tests as a sixth commit: |
|
You better split the PR into each issue otherwise @idrassi will have a hard time to under which changes belong to which code |
This was referenced Oct 27, 2026
Contributor
Author
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes for the five issues reported by curious-rabbit, one commit each. Each commit describes its change in detail.
Hidden volume protection password stays in memory while the outer volume is mounted #1961 The protection password is released together with the outer volume password once the volume is open, so the forked FUSE service no longer inherits it.
Options --create-keyfile and --backup-headers overwrite existing files without asking #1962
--create-keyfileand--backup-headersask before replacing an existing file in text mode, as the GUI does and as text mode already does for new containers (4edad72).--non-interactivefails instead;--forceoverwrites. The header backup prompt uses the wxWidgets string of the GUI file dialog, so no new translation key is needed.Two volumes mounted at the same time can fail or end up at the wrong mount point #1960 Outside FUSE-T builds, the auxiliary mount point is created with
mkdtemp(as FUSE-T builds already do) instead of reusing/tmp/.veracrypt_aux_mntN. The name keeps the.veracrypt_aux_mntprefix that identifies auxiliary mounts. Its mode is not changed by pathname afterwards (0700 frommkdtempinstead of 0500), since the temporary directory can belong to the user with pam_tmpdir.After emergency unmount the same volume can be mounted twice and gets corrupted #1959 Linux: once the volume is open, an exclusive
flockis taken for it and inherited by the FUSE service, which holds it until it exits, so a volume whose service was detached by an emergency dismount cannot be mounted again meanwhile. The lock is named after the device number, or the file system and inode numbers, thatfstatreports for the opened volume, so it applies to the file actually served whatever path leads to it. It is not taken on the volume file itself, whose locking is disabled for remote file systems. The lock files are created withopenatin the root owned/var/run/veracrypt(also present where/runis not), which is opened without following symbolic links and checked through its descriptor. A busy lock is retried for 10 s because a normally dismounted service may still be exiting. Without root or a usable lock directory, mounting works as before. The lock files are not removed, to avoid the usual unlink race; they are small and on tmpfs.key memory is not locked and the volume service can be core dumped #1958
SecureBufferallocations get whole pages of their own, locked withmlockand excluded from core dumps (MADV_DONTDUMP,MADV_NOCOREon FreeBSD). Memory locks are not inherited byfork, so the FUSE service locks the live buffers again once FUSE has put it in the background. The core service and the FUSE service also setRLIMIT_COREto 0 and, on Linux, clear the dumpable flag, because key material can be copied outsideSecureBufferand acore_patternpipe ignoresRLIMIT_CORE.Volume::WriteSectorskeeps a plainBuffer, still erased when freed: its data is encrypted in place right after the copy, and locking and unlocking its pages on every write reduced write throughput by 19 to 60 % in a benchmark (x86_64, AES-NI, 1 MiB to 4 KiB writes).Tests
Tests/test_unix_security_regressions.pychecks each of the five issues against the installed package, as root, in the GUI package step of the Linux workflow (about 30 s).Tested on Linux x86_64 (build without warnings,
--test) and on OpenWrt 25.12.6 mipsel (ASUS RT-AX53U, FUSE3, as root), with the reporters' scenarios, comparing 1.26.30 with these commits applied on top of it:ParameterIncorrect at MountVolume:1463,fuse: mount failed), once a volume mounted at the other volume's mount point/tmp/.veracrypt_aux_mnt1does not block mounting--create-keyfileon an existing keyfileKEYFILE_ALREADY_EXISTS;--forcereplaces itNot built or tested: macOS and FreeBSD (the shared code was only reviewed for them). Not tested: the non-root user plus core service setup of #1961 (the reproduction above runs as root, without a core service).