Free the key-info buffer and owned crypto context on pre-KDF errors,
preserving borrowed contexts and avoiding uninitialized drain resources.
Inject every setup allocation and event failure to verify cleanup.
Record cloning, formatting and allocation failures without allocating, then
complete and drain the request before reporting an error. This prevents
worker loss and avoids treating incomplete cipher or KDF output as valid.
Test ordinary exceptions, capture failures and subsequent pool recovery.
Retain accepted callers and KDF workers until completion, and run later
requests synchronously. Clear joined threads and unwind partial startup
so serialized restarts do not retain stale workers.
Cover shutdown boundaries and startup failures with gated tests.
Serialize updates to the shared exception pointer and retain the first
reported error. Test concurrent failures through all three handlers,
exception cleanup and subsequent successful work.
Close admission and retain references for accepted requests, KDF workers
and submitters until they stop using pool resources. Run new work
synchronously while stopping, then join workers and release handles.
Test queued work, delayed requester wakeup, fallback and restart.
Join created workers and release allocated handles when startup fails before
the pool is published. Close worker handles on normal shutdown as well.
Test each startup allocation failure and subsequent restart.
Hold a requester reference until header parsing can no longer enqueue KDFs.
This prevents stale completion signals from allowing cleanup while workers
still use request-owned state.
Add bounded tests of the production pool and caller completion protocol.
EMV keyfile cleanup did not cover APDU response storage, temporary
copies, or transport buffers on exceptions. Wipe responses on clear,
replacement, destruction and growth, avoid redundant response and PAN
copies, and install transport cleanup guards before use.
Add standalone checks for erasure before release, aliasing, allocation
failures, exception unwinding and const TLV input.
The test compiles the requester helper code into a small harness and runs
it as root on an ordinary file owned by an unprivileged user. It checks
that the helper runs in a freshly executed process with a reduced
environment, descriptors 0-2 on /dev/null and no other inherited
descriptor, with and without close_range, including when a library is
found only through LD_LIBRARY_PATH, as in the AppImage. It also checks
that a failed or incomplete start is reported as a startup failure and
never falls back to read-only access, and that invalid requests and a
request socket whose peer is not root are refused.
As an unprivileged user, the test mounts a passthrough FUSE fixture
without allow_other, so that root is denied as with a GVfs share. It then
runs VeraCrypt as root with the sudo attribution of that user. It covers
writable and read-only mounting, the read-only fallbacks, missing or
invalid attribution, wrong passwords, special files, hidden volume
protection, slow servers, timestamp restoration and the mount warning.
Unmounting released the loop device and device-mapper devices recorded
at mount time, by name. After a dismount that failed partway, for
example on a busy auxiliary FUSE mount, these names could be reused by
unrelated objects, which the listing then showed as the volume's and a
retry, emergency cleanup, filesystem check or auto-dismount released.
Without kernel cryptography, the loop device, which carries the
decrypted volume, was also released while the filesystem was mounted
elsewhere or the device was held open. A failed mount could remove a
pre-existing device-mapper device of the same name, and a failed
cascade mount could leave its layers and loop device behind.
Each destructive step now acts only on a device verified to belong to
the volume. A loop device must be bound to the container or volume
image (LOOP_GET_STATUS64). Device-mapper devices get the UUID
VERACRYPT-<serial>-<name> and are removed by UUID; those of earlier
versions, which have none, are verified through their sysfs slaves,
and the dismount fails, saying why, if that is not possible. Emergency
cleanup is not offered then, as it would hide the volume but leave its
devices. While the filesystem is mounted elsewhere, the dismount fails
and keeps the volume's devices. With kernel cryptography, the loop
device is marked for autoclear as soon as it is attached and verified,
so the kernel detaches it once device-mapper releases it; a process
holding it open sees only ciphertext and does not fail the dismount.
Without kernel cryptography, the dismount also fails while the loop
device is held open. Dismount, emergency cleanup, filesystem check and
the listing re-read the volume's devices from its auxiliary mount, and
the English emergency warning mentions these causes.
Add Tests/test_linux_loop_identity.py, covering these cases with and
without kernel cryptography, and with --legacy-binary, volumes mounted
by an earlier version. All 89 checks pass, as do the 11 added by
--legacy-binary 1.26.29; 1.26.29 itself fails 21 of the 89.
The Linux workflow checks the content of the Tests/*.hc volumes by
mounting them, which needs root, FUSE and the installed package, and so
only runs on x86_64. Add a test that recovers the same data through the
volume layer instead, so it also runs on other architectures, e.g. on the
big-endian cross build under qemu-user.
Tests/volume_read_test.cpp opens a volume read-only and reads its data
area with Volume::ReadSectors: in one call, as multi-sector ranges at
nonzero offsets with odd sector counts, again with the encryption thread
pool running, and one sector at a time; every read must match the first.
CPU features are detected as in the application, and the character set
is taken from the environment (LC_CTYPE) so that paths with non-ASCII
characters work; if that locale is unavailable, the test continues in the
C locale and says so.
Tests/test_volume_read.py builds it against Volume.a and Platform.a of a
finished standard Linux build (CXX and NM can be set for a cross build)
and checks the plaintext of every Tests/test.*.hc volume: the FAT boot
sector, DUMMY.TXT with the content "Dummy" at the cluster given by the
root directory, and a known SHA-256 digest of the whole data area. A
volume without a digest, or a digest without a volume, is an error.
It runs in the Linux workflow after the .deb build and in the build job
of the big-endian workflow (test.sha512.hc only in the automatic check,
all volumes in the full run), and requires the thread pool there.
Signed-off-by: Ville Takio <ville+git@takio.fi>
Look up NixOS helpers only when trusted system metadata identifies NixOS
and each path component passes ownership and permission checks. Keep the
existing helper search on other distributions.
Detect NoNewPrivs before prompting for administrator credentials, with a
clear error for restricted launchers. Add regression coverage to Linux CI
and append the English fallback message to all language files.
Refs #1911
* CI: build and test on big-endian (s390x) and across byte orders
The Linux workflow only builds and tests on x86_64, so code that assumes
a little-endian host (see #1899) is not caught. Add a workflow that
cross-builds the console version for s390x and runs it under qemu-user:
- the algorithm self-tests (--test),
- the Tests/test.*.hc volumes, created on little-endian, must open and
accept a password change,
- volumes created on s390x open on a native amd64 build and the other
way round, for every encryption algorithm and cascade, with every PRF
(new Tests/test_byte_order_interop.py, also usable on its own).
The wxWidgets console build is cached per architecture, like in the
existing Linux workflow.
Signed-off-by: Ville Takio <ville+git@takio.fi>
* CI: quick big-endian check on pull requests, full suite on request
Address review:
- Pull requests and pushes run only the s390x build, the algorithm
self-tests and the Tests/*.hc volumes. The full suite (amd64 build,
volumes on both builds, interoperability in both directions) runs
when started manually, with the volume and interoperability tests in
separate jobs that run concurrently.
- Pass the KDF with --hash; one interoperability case per direction
still uses autodetection.
- Use separate current and new PIM values: the Tests/*.hc volumes are
opened with PIM 0, but the new headers use PIM 1, so only the first
key derivation is expensive.
- Open each Tests/*.hc volume again with the new password before
removing it.
- Run VeraCrypt with LANG and LC_ALL set to C and an empty
XDG_CONFIG_HOME, so the "Incorrect password" check does not depend on
the user's language settings.
- Fail instead of reporting success when nothing would be tested:
--skip-official without a second binary, or no (or a missing
requested) Tests/*.hc volume. Add --fixture to select volumes.
- Print how long each check takes.
* CI: keep the automatic big-endian check short
- Open only Tests/test.sha512.hc in the automatic check (all five
volumes took 154 s of the 327 s s390x job); the full suite still
opens all of them.
- Cover KDF autodetection in the automatic check too: the first volume
is opened with the new password (PIM 1) without --hash. The
interoperability case without --hash now uses sha256, since sha512
is tried first anyway.
- Include the event name in the concurrency group, so a push does not
cancel a manual full run.
- Print the elapsed time for failed checks too.
(The previous commit message should say that XDG_CONFIG_HOME points to
an empty temporary directory.)
* CI: use actions/cache@v5 in the big-endian workflow
Match build-linux.yml, which moved to the Node 24 runtime in 9d9fda20.
---------
Signed-off-by: Ville Takio <ville+git@takio.fi>
Add English fallbacks for 12 missing keys in 41 language files.
Report all missing keys and XML errors before failing validation.
Run four regression tests in CI. All tests and 43 XML files pass.
Volumes encrypted in user space are mounted through a loop device on the
FUSE volume image, and their writes end in buffered pwrite() calls to the
backing file or device. The FUSE service had no fsync callback, so libfuse
answered the fsync requests that the loop device issues for block-layer
flushes with ENOSYS, which Linux FUSE reports as success. Synced data
could therefore remain dirty in the host cache, and writeback errors were
not reported.
Register an fsync callback that syncs the backing storage for the volume
image and returns its errors through the existing mapping. Never return
ENOSYS, which would make Linux FUSE stop forwarding fsync for the whole
mount: report a backing ENOSYS as EIO, as the loop driver does, and
return success for the other files. Other Unix platforms are outside this
change.
Add regression coverage on device- and file-backed volumes: fsync must
flush the backing device, a backing failure must be reported as EIO, and
synced data must survive a simulated power cut. Without this change, the
synced data is lost. Validated with FUSE2 and FUSE3 builds.
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.
Limit backup retry recovery to credential errors. Restore header selection
and rethrow other failures, including cancellation, in CLI and GUI.
Add regression coverage for fallback and credential recovery.
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.
* Linux/MacOSX: during build, fallback to /tmp if wxWidgets sources not found in parent directory
* Linux: Add Github workflow to build .deb files and test generated binaries
* Linux: fix wrong wxWidgets extract path in yaml
* fix: fix wrong wxWidgets extract path in yaml
* Linux: harmonize content of test volumes and update Github workflow for this
* Fix corrupted test container
* Linux: optimize Github workflow by caching wxBuildConsole and wxBuildGUI folders
We also modify build script to detect the presence of wxBuildConsole and wxBuildGUI folders and reuse them
* Remove files mistakenly added
* Linux: Fix wrong test for Github workflow
* Linux: use static build of wxWidgets for GUI in Github workflow
* Linux: upload also .deb SHA256SUM file if it is generated in Github workflow
* Linux: fix detection logic of parent folder in build scripts
* Github workflow: add build_cmake_deb.sh as trigger to build-linux.yml
* Github workflow: add wxWidgets source code to the cache of workflow