MountVolumeNative attaches a loop device only for a volume in a file,
but it recorded the volume path as the loop device in every case. For
a volume on a block device mounted with kernel cryptography, that is
the host device itself, so DismountVolume and EmergencyDismountVolume
ran losetup -d on it. A loop device that the user had attached, for
example to open a volume inside a disk image, was detached, or marked
for autoclear when emergency cleanup ran while the filesystem was
busy. On other devices, such as partitions, losetup failed and was
retried for about 1.2 seconds before the error was ignored. This code
comes from TrueCrypt 7.1a.
Record the loop device only when MountVolumeNative attached one, as
its error path already does. A volume mounted by an earlier version
keeps its FUSE service after an upgrade, and that service still
reports the host device, so the unmount functions also skip a loop
device that is the volume's own path. A loop device that VeraCrypt
attached is never the volume path.
Validated with console builds as root, for volumes on a loop device,
on a partition of a loop device attached with --partscan, and with
--emergency-unmount while the filesystem was busy: losetup no longer
runs, the loop device stays attached, and the partition case unmounts
in 0.18 s instead of 1.43 s. The same holds when these volumes are
mounted by 1.26.29 and unmounted by this build. Volumes in files and
nokernelcrypto mounts still detach the loop device that VeraCrypt
attached, also when mounting fails.
The FAT formatter stored multi-byte boot sector and FSInfo fields by
casting positions in the sector buffer to integer pointers, and
GetMaxHiddenVolumeSize read the outer volume's boot sector the same
way. Several FAT fields start at odd offsets (bytes per sector at 11,
root directory entry count at 17, total sectors at 19, and the volume
ID at 39 or 67), so these accesses were misaligned. That is undefined
behavior whatever the byte order, and it can fault on targets that
require aligned accesses. An alignment-sanitized build reported the
stores in PutBoot and, for FAT12 and FAT16 outer volumes, the read of
the root directory entry count.
Copy each field between the buffer and a local integer with memcpy,
keeping the Endian::Little conversions, and copy the volume ID as its
four random bytes. Fields at even offsets use the same helpers: they
were aligned only because the sector buffer comes from malloc. The FAT
scan for the last used cluster is unchanged; it reads 32-bit words at
multiples of four in a malloc'd buffer and only tests them for zero.
Validated with x86_64 builds using -fsanitize=alignment and big-endian
s390x builds under qemu. With fixed volume ID bytes, the formatter
output for 18 FAT12, FAT16 and FAT32 layouts, including the FAT32
backup boot sector, is byte-identical before and after. The hidden
volume size of 16 volumes created and populated through the CLI is
unchanged and matches a separate implementation; the s390x checks used
the big-endian crypto fixes from #1899 to open the volumes. The
sanitizer and trap builds no longer report these accesses.
Without dmsetup, MountVolumeNative fails with "dmsetup not found in
system directories" instead of using the FUSE path, so on systems that
do not ship device-mapper tools (for example OpenWrt) every mount and
the filesystem formatting step of --create need an explicit
--mount-options=nokernelcrypto. Treat a missing dmsetup like the other
cases where kernel crypto cannot be used.
Signed-off-by: Ville Takio <ville+git@takio.fi>
Create a fresh private parent for each FUSE-T auxiliary mount. Elevated
parents stay root-owned and grant only the original user read/search
access, restricting access through the auxiliary mount path and preventing
caller-controlled path replacement during elevated setup.
Clear inherited ACLs and reject temporary filesystems that ignore
ownership. Remove per-mount parents on setup failure and service teardown,
while preserving legacy temporary directories and discovery behavior.
Add regression coverage for permissions, unique parent creation, rollback,
and cleanup. FUSE-T transport authentication is outside this change.
Run display discovery asynchronously and bound batched disk-image inventory
queries. Filter auxiliary mounts by basename, filesystem and owner, and
keep unresolved candidates separate from verified volumes. Allow targeted
dismounts despite incomplete discovery while requiring complete results
for slot allocation and empty-inventory decisions.
Use nonthrowing GUI snapshots with monotonic freshness, completion events
and safe window lifetimes. Suspend inactivity decisions while the snapshot
is stale, without restarting idle timers: activity counters are cumulative
per volume instance. Refresh logout targets and retry only failed ones.
Show a progress dialog for interactive unmounts, but keep automatic ones
synchronous, so a quit or logout request that arrives meanwhile is handled
afterwards rather than refused. Guard core operations against reentry and
route wait-dialog requests only from worker threads, so a main-thread
message cannot wait for itself.
Bind teardown to captured mount and service identities, including process
start time. Report a service exit that cannot be confirmed after auxiliary
mount removal as a distinct error that keeps the original details. Such
volumes are not retried, and a multi-volume unmount reports all of them
together with any other failure or a declined prompt. Warn about it after
automatic unmounts and at quit, and keep the background application until
the warning is acknowledged. Keep rollback responsive, and let services
remove their auxiliary directories without probing mounted paths. Preserve
released /control compatibility and perform best-effort cleanup for older
services.
Reap bounded subprocesses as soon as their output ends. A child that
survives SIGKILL is reaped by a later call, which starts no new child until
then. Keep subjects and subprocess command, status and error output when
formatting exceptions for wrapping and logs. Clarify discovery and rollback
diagnostics. Fix the localization-dependent busy-volume regression
assertion and extend discovery, snapshot, process identity, cleanup, GUI
lifecycle, inactivity and teardown coverage.
Keep FUSE serving until the auxiliary SMB filesystem is unmounted, then
join the shutdown worker before destroying the FUSE handle. Authenticate
socket peers and bind each request to the service and filesystem instance;
carry the force flag through to unmount and reply before teardown.
Resolve the current disk image before detach instead of trusting cached
BSD device numbers. Clear device and mount metadata when the image is gone,
and abort on inventory errors. Refresh ownership during enumeration and
before filesystem checks. Give each auxiliary mount a random path so an old
backend cannot target a subsequent VeraCrypt mount during cleanup.
Canonicalize the auxiliary path before service startup and hdiutil attach.
Resolve older clients' image paths through TMPDIR aliases without accessing
unrelated images. Treat candidate resolution failures as errors rather than
evidence that an attached image is gone.
Keep a new service provisional over a private inherited socketpair until
control-file readiness and public shutdown endpoint checks succeed. On
startup failure or caller exit, unmount while FUSE still serves and wait for
volume closure and service exit. Report incomplete cleanup explicitly and
keep retrying cleanup in the service if unmounting is temporarily blocked.
Restore dismounts of released services without /shutdown through a
validated legacy flow. Preserve incoming file-protocol notifications and
watch for external unmounts independently of those notifications. Legacy
unmount cannot guarantee termination of an already-running old service.
Use one fixed versioned socket frame and publish the random endpoint in
/shutdown-socket, preserving the three-field /shutdown identity. Remove
compatibility with unpublished socket protocols. Recover from transient
accept and mount-enumeration failures, bound partial-request lifetimes,
and report connection refusal as an availability error. Handle join failure
without unwinding the destructor or freeing a live worker's context.
Map auxiliary EBUSY to MountedVolumeInUse for the GUI force prompt. Return
failure for a single busy non-interactive dismount and log automatic-dismount
failures. Mark inherited descriptors close-on-exec before FUSE setup and
make File::SetCloseOnExec const.
Extend disposable-container tests for released clients and services,
reused device numbers, partial requests, identity validation, forced write
integrity, TMPDIR aliases, and injected startup and rollback failures.
Validated without sudo with a clean arm64 build, unchanged warnings,
algorithm self-tests, the compatibility matrix, descriptor audits, worker
fault-recovery checks, and 24 conditional compilation checks.
Generate the session serial before forking and reuse it in the service
and fallback mount metadata.
This keeps PR #1866's shutdown identity check consistent when control
metadata cannot be read.
Add an authenticated shutdown endpoint to the auxiliary FUSE filesystem and wait for the matching service process to terminate before removing the mount point.
Reuse the prepared password to avoid rereading outer keyfiles after
mounting. This prevents post-mount read failures and ensures the cache
contains the credential that unlocked the volume.
Apply protection keyfiles once in the application, including cached-password
mounts. This keeps PC/SC out of the core service before FUSE forks.
Preserve protection errors and cache retries, and ignore protection
credentials when protection is disabled.
Clone command-line auto-mount options before device and favorite batches, and clone the batch options again for each favorite before applying favorite-specific fields.
This prevents interactive credentials, PIM, KDF choices, and per-favorite filesystem settings from carrying over to later favorites.
Propagate EMVSupportEnabled through MountOptions serialization and mount setup so elevated core service requests use the same EMV setting as the caller.
Expose FFS as the native OpenBSD filesystem option for volume creation and accept FFS/UFS on the command line, mapping mounts to the OpenBSD ffs filesystem type.
Run newfs through the elevated core service on vnd raw devices, then temporarily mount the new filesystem to transfer root directory ownership back to the invoking user.
Keep the non-interactive creation default as FAT on OpenBSD so existing unattended scripts do not start requiring elevation.
Reuse the OpenBSD doas PTY prompt flow on FreeBSD so opendoas receives the password through its controlling terminal.
Apply the same foreground process group validation on FreeBSD as on OpenBSD when attaching the private doas authentication PTY.
Detect the incompatible FreeBSD security/doas package by pkg origin and fail with explicit guidance.
Move child pipe descriptors away from stdio slots before remapping them, avoiding collisions when 0/1/2 are closed.
On OpenBSD, wait for authentication-terminal output before writing the doas password, avoiding prompt text matching while keeping the startup timeout as the upper bound.
Keep OpenBSD doas stderr on the private authentication PTY because doas requires stderr to be a terminal while prompting.
Capture authentication-terminal diagnostics, strip prompts from user-facing errors, and fail promptly on explicit authentication denial.
Wait for actual prompt bytes before sending the password so OpenBSD PTY POLLIN|POLLHUP before slave open cannot race with readpassphrase terminal flushing.
Set close-on-exec on elevated-service startup pipes before fork and centralize duplication onto standard descriptors.
Clear FD_CLOEXEC on descriptors intentionally kept across exec, including dup2(fd, fd) no-op cases.
OpenBSD defines O_CLOEXEC, but rejects it in posix_openpt() with EINVAL. Retry with the POSIX pseudoterminal flags and then set FD_CLOEXEC explicitly so doas authentication can create its private PTY.
Prefer sudo when available and fall back to doas on Unix. Run doas authentication through a PTY while keeping service communication on stdin/stdout pipes, and use a no-fork service mode for the doas path.
Keep doas authentication terminal descriptors close-on-exec and close the slave descriptor after attaching it as the controlling terminal. Preserve startup diagnostics through stderr until service synchronization completes, then redirect no-fork service stderr away from the closed parent pipe.
Use noninteractive privilege-helper auth checks for both sudo and doas so cached, nopass, or persisted sessions do not need an unnecessary VeraCrypt password prompt. Keep the PTY password path for doas when authentication is required.
Use a shared Unix DOAS_USER helper for FUSE and mount ownership, backed by getpwnam_r and guarded so non-OpenBSD platforms only trust it for VeraCrypt's internal doas no-fork service path. Detach asynchronous child-reaper threads to avoid leaking joinable pthread handles.
Keep the historical auto-mount behavior as the first attempt when the user did not request a filesystem type. If that mount fails on Linux, detect the filesystem with blkid and retry only for FAT-family types that minimal mount implementations may not auto-probe.
Leave explicit filesystem types and NTFS kernel-driver resolution unchanged.
CoreMacOSX::CheckFilesystem() ignored both its mountedVolume and repair
arguments and always just launched Disk Utility.app, so the "Check
Filesystem" and "Repair Filesystem" menu items behaved identically and
neither acted on the mounted volume. On Linux/BSD the same operation runs
fsck and honors the flag (passing -n only when repair is false).
Run diskutil on the VeraCrypt virtual device, choosing verifyVolume or
repairVolume per the flag (diskutil unmounts the inner filesystem itself
as needed). The Core layer has no GUI, so the result is shown in a
Terminal window via a temporary .command script; it falls back to
launching Disk Utility.app when no virtual device is available.
Run the macOS check in the unprivileged application process. VeraCrypt does
not need to create or launch the helper script from the elevated core
service: diskutil operates on the mounted virtual device and macOS handles
any device authorization requirements. Once a device-hosted mount has
started the elevated core service, every later service request is routed to
that root process. There it would create the helper script as root (0700)
and open a Terminal in the GUI session that the user could neither read nor
execute. CoreServiceProxy::CheckFilesystem now invokes the core
implementation directly on macOS instead of sending a service request, so
the script is always owned by the GUI user.
The device path is strictly validated as /dev/[r]diskN[sM] before being
single-quoted into the command. The helper script is created securely in
the per-user temp directory via mkstemps() (atomic O_EXCL/0600, fchmod
0700 by descriptor, close() checked for deferred write errors, unlinked on
any failure) rather than at a predictable, enumerable path in the
world-writable /tmp, guarding against a symlink/race on the executed
script. A trap removes the script on exit even if the window is closed
early, and it is also unlinked if launching Terminal fails. The script
captures $? so diskutil's result, including failures, is shown before the
script exits.
Replace the macOS pre-check message (which still told the user Disk
Utility would open and to pick Verify/Repair manually) with check- and
repair-specific text describing the new automatic diskutil flow.
Seed the two new strings into all translation files with the English
text so the XML key-completeness check passes; localization can follow.
Co-authored-by: Damian Rickard <damian@rickard.us>
Separate sudo authentication success from elevated request execution state by acknowledging when the elevated core service starts successfully.
Once that channel is available, propagate later failures instead of showing repeated administrator password dialogs. Initialize the sudo dummy-password flag consistently on macOS, avoiding an uninitialized read of UseDummySudoPassword.
Register admin-password cleanup before elevation attempts so plaintext sudo credentials are erased on early-return and post-sudo failure paths.
References #1788.
The hdiutil `-plist` output used for mount/dismount device discovery
(MountAuxVolumeImage and UpdateMountedVolumeInfo) was parsed with a
hand-rolled string scanner that assumed the value always follows the
requested key and that <key>/<string> pairs appear in a fixed order.
Replace it with the CoreFoundation property-list API
(CFPropertyListCreateWithData + dictionary/array navigation), which is
correct by construction and robust to hdiutil output ordering/variation.
An RAII helper (CFHolder) ensures CFRelease on every path.
Behavior is preserved: prefer the system-entity that carries a
mount-point, otherwise fall back to the first dev-entry, and match disk
images by normalized image-path. CoreFoundation is already linked on
macOS (via Cocoa), so no build changes are needed.
Verified end-to-end on Apple Silicon: mounting parses `hdiutil attach`
output and dismount parses `hdiutil info` output correctly.
Co-authored-by: Damian Rickard <damian@rickard.us>
The privileged CoreService handler for SetFileOwnerRequest passed the
client-supplied path straight to chown() as root with no validation --
unlike the adjacent APFS formatter handler, which strictly validates its
device argument. Every legitimate macOS caller of the elevated
SetFileOwner targets a real disk device node (/dev/[r]diskN[sM]), so a
crafted IPC request, or a symlink planted at the target, could otherwise
make the root process change ownership of an arbitrary path.
Validate the target service-side: require the strict device-path form
already used by the formatter, and lstat() it to confirm a block or
character device (rejecting symlinks rather than following them) before
the chown.
Co-authored-by: Damian Rickard <damian@rickard.us>
On Unix and macOS, the hidden volume wizard estimates the available space for non-FAT outer filesystems using statvfs(). The previous calculation used f_bsize with f_bavail, which can overstate available bytes on macOS exFAT because f_bsize may be the preferred I/O size instead of the fragment size associated with the block counts.
Use f_frsize when it is reported, fall back to f_bsize, and clamp the non-FAT estimate to the actual outer VeraCrypt data size before applying the existing 80% safety heuristic.
Also harden hidden volume creation in both the cross-platform VolumeCreator path and the Windows/common formatting path by rejecting sizes that would exceed the hidden host data area and overlap volume header space.
Fixes#1037
CentOS 6 builds VeraCrypt with GCC 4.4.7 and -std=c++0x. That compiler does not support range-based for loops, and its libstdc++ does not provide std::string::back() or std::string::pop_back().
Avoid those constructs in the affected Unix/Linux code paths: use VeraCrypt's existing foreach helper when iterating PKCS#11 object handles, and use indexing plus erase() when trimming trailing slashes from PATH entries.
This keeps the code valid for newer Linux toolchains while restoring compatibility with the CentOS 6 build environment.
VeraCrypt derives the real (non-root) user from SUDO_UID/SUDO_GID
to set default mount-point ownership and the FUSE service access
filter. On OpenBSD, privileged commands are normally run through doas,
which exposes the invoking login name via DOAS_USER and does not set
the sudo variables. As a result, VeraCrypt launched through doas
attributes both to root instead of the invoking user.
When the sudo identity variables are absent, resolve DOAS_USER through
the password database and use that uid/gid for default mount-point
ownership and the VeraCrypt FUSE service access filter. sudo behavior
is unchanged.
This is a correctness fix for the doas launch path. It is not confirmed
to resolve the non-root ext2fs EACCES reported in the linked issues:
that failure occurs at the ext2fs layer reached through vnd, whose
backing-image I/O runs as root and is therefore already permitted by
the access filter.
Refs #1589.
Refs #1593.
OpenBSD device length detection was returning the raw disk sector count from DIOCGPDINFO directly. That value is not bytes and it describes the physical/default disk label, which caused VeraCrypt to expose an incorrectly sized FUSE backing image through vnd for device-hosted volumes.
Use the current disklabel from DIOCGDINFO, derive the opened partition from the device minor number, and return the selected partition size in bytes. Keep the raw c partition on the whole-disk path by using DL_GETDSIZE there.
Also reject sector-misaligned device-hosted sizes during volume creation so new malformed OpenBSD device-hosted volumes are not created. Do not reject existing malformed headers at mount time, so users can still mount old OpenBSD-created volumes for recovery.
Refs #1589.
Refs #1593.
Allow normal file-hosted containers to use quick format in the Unix volume creation path by sizing the host file with ftruncate before backup headers are written.
Enable the GUI checkbox for normal file containers and honor --quick in text mode. Update the Unix HTML documentation for the weaker deniability properties of sparse or unwritten host regions.
Argon2id includes the requested output length in its computation, so deriving 192 bytes and using a prefix is not equivalent to deriving only the selected cipher's key material length. This differs from PBKDF2, where the prefix property made this detail invisible.
VeraCrypt derives the maximum header key material currently needed by the supported cipher/cascade set, which is 192 bytes, and then uses the required prefix for the selected encryption algorithm. For AES-XTS this means the first 64 bytes of the 192-byte Argon2id output are used.
Make this design rule explicit in code and documentation by introducing ARGON2_HEADER_KEYDATA_SIZE instead of relying implicitly on GetMaxPkcs5OutSize. If a future cipher or cascade requires more than 192 bytes, that must be handled as an explicit format/design change.
Document the 192-byte Argon2id header KDF output requirement so third-party implementations derive the same header key material.
References: https://github.com/veracrypt/VeraCrypt/issues/1614
Keep the NTFS kernel-driver option as a generic in-kernel NTFS path rather than an ntfs3-specific path. Add --filesystem=kernel-ntfs and -m kernelntfs routes that select a registered or loadable kernel NTFS driver and mount with -i so mount.ntfs/ntfs-3g helpers are not invoked.
Preserve --filesystem=ntfs3 as a literal pin to the ntfs3 driver. Treat both ntfs3 and kernel-ntfs as mount-only selectors; volume creation continues to use filesystem type NTFS.
The preference and -m kernelntfs path only select an in-kernel NTFS driver when no explicit filesystem type was supplied and blkid detects NTFS.
Treat ntfs as the preferred in-kernel driver on Linux 7.1 and later, where the upstream read/write driver is expected. On earlier kernels, select ntfs only when module metadata identifies the standalone read/write driver and /sys/module confirms it loaded, avoiding ntfs3 read-only ntfs compatibility registrations. Fall back to ntfs3 otherwise, and report a generic kernel-driver error if neither supported driver is available or loadable.
Rename the internal preference/config field to MountNtfsWithKernelDriver, migrate the old MountNtfsWithNtfs3 preference key, and update UI strings, CLI help, documentation, release notes, and translation placeholders accordingly.
Reference: https://github.com/veracrypt/VeraCrypt/issues/1735
Prefer hdiutil plist entities that carry a mount-point when recording the virtual device. This fixes APFS images where the first dev-entry is not the mounted volume.
Add a macOS mounted-volume refresh hook that recovers VirtualDevice and MountPoint from hdiutil info when FUSE-T SMB auxiliary metadata is missing or stale.
APFS volume creation can still fail with Permission denied after preparing the raw and block device aliases because newfs_apfs performs privileged APFS container and volume operations beyond opening the device nodes.
Route APFS formatting through the elevated CoreService path for non-root macOS runs. Keep the elevated interface narrow by sending only the target device and invoking user UID/GID, validate the device path on the privileged side, rebuild the formatter arguments there, and execute /sbin/newfs_apfs by absolute path to avoid PATH shadowing.
Pass -U/-G so the created filesystem preserves the invoking user ownership. Apply the same path to GUI and text-mode creation.
Report explicit progress stages while writing volume data, writing backup headers, and flushing data to disk so the wizard does not appear stuck at 100%.
Keep the wizard in progress during Unix post-creation formatting and show status for temporary mount/device setup, mkfs invocation, and dismount.
When normal filesystem unmount fails, the Linux path could stop before cleaning VeraCrypt mapper, loop and FUSE objects. Add an explicit emergency dismount request that is only reached after interactive confirmation.
The recovery path lazy-detaches mounted filesystems, uses deferred dmsetup removal for VeraCrypt mapper devices, detaches loop devices, and keeps normal force/ignoreOpenFiles behavior unchanged.
The read loop that captures stderr from the sudo child process used
`vector<char> buffer(4096); buffer.clear();` followed by
`read(fd, &buffer[0], buffer.capacity())`. This has two instances of
undefined behavior:
1. `operator[](0)` on a vector with `size() == 0` violates the C++
standard precondition `n < size()`. libstdc++ built with
`-D_GLIBCXX_ASSERTIONS` aborts the process with:
stl_vector.h:1128: Assertion '__n < this->size()' failed.
2. `buffer.begin() + bytesRead` on the same empty vector constructs
an iterator past `end()`, also UB.
`-D_GLIBCXX_ASSERTIONS` is in the default build flags of Arch Linux,
Fedora, and several other distributions. On those systems, the
unprivileged helper process aborts as soon as sudo writes anything
to stderr (a password prompt, a 'user is not in the sudoers file'
error, etc.). The main process then sees EOF on the service output
pipe, and throws `InsufficientData`, which renders to the user as
'Not enough data available'. A second mount attempt fails at
`File::Write` because the helper is dead and the pipe is broken,
producing the bare message 'VeraCrypt::File::Write:395'.
Fix by replacing `buffer` with a plain `char[4096]` and using
`reserve(4096)` on `errOutput` to preserve the original
pre-allocation intent. No behavioral change on systems where the UB
happened to work; aborts are eliminated on systems where the
assertions fire.
Reported-by: multiple users, see veracrypt/VeraCrypt#1550,
veracrypt/VeraCrypt#1446, veracrypt/VeraCrypt#844
Co-authored-by: rabbit <rabbit@github>
Make /aux-device-info readable for SMB, verify that FUSE records hdiutil device info after mount and recover missing virtual devices from hdiutil before dismounting auxiliary mounts.
Add statfs metadata for the auxiliary FUSE mount, keep /control read-only by sending hdiutil device data through /aux-device-info and tolerate delayed SMB rediscovery during mount completion. Log final control-file retry failures for diagnostics.
The cascade order has been updated so that SM4 is applied after the other cipher(s) (e.g., Serpent). This change reflects standard cryptanalytic guidance, which shows that the overall strength of a cascade is limited by the first encryption stage. Given that SM4 uses a 128-bit key, its post-quantum brute-force resistance is lower than ciphers with a 256-bit key (such as Serpent). By placing SM4 last, we ensure that any potential weakness in SM4 cannot reduce the security margin provided by the stronger cipher.
When VeraCrypt is run as an AppImage, the veracrypt binary resides in a SquashFS mount under /tmp which is inaccessible to root. Using this path with sudo results in a "command not found" error.
This patch detects the AppImage environment by checking both APPIMAGE and APPDIR variables, ensuring the executable path starts with APPDIR and that APPDIR starts with the expected "/tmp/.mount_Veracr" prefix. In this scenario, the AppImage file itself (APPIMAGE) is used as the executable for sudo, resolving the elevation issue.