From a1dfce108dfdeec78198724320035f3b88c845b2 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Sun, 4 Oct 2026 10:21:12 +0900 Subject: [PATCH] Linux: don't detach the host device of a device-hosted volume 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. --- src/Core/Unix/CoreUnix.cpp | 6 ++++-- src/Core/Unix/Linux/CoreLinux.cpp | 6 +++++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Core/Unix/CoreUnix.cpp b/src/Core/Unix/CoreUnix.cpp index 1344f9e0..5525ab9c 100644 --- a/src/Core/Unix/CoreUnix.cpp +++ b/src/Core/Unix/CoreUnix.cpp @@ -306,7 +306,8 @@ namespace VeraCrypt #endif catch (NotApplicable &) { } - if (!mountedVolume->LoopDevice.IsEmpty()) + // Earlier versions recorded the host device of a device-hosted volume mounted with Linux kernel cryptography as its loop device + if (!mountedVolume->LoopDevice.IsEmpty() && wstring (mountedVolume->LoopDevice) != wstring (mountedVolume->Path)) { try { @@ -410,7 +411,8 @@ namespace VeraCrypt firstException.reset (e.CloneNew()); } - if (!mountedVolume->LoopDevice.IsEmpty()) + // Earlier versions recorded the host device of a device-hosted volume mounted with kernel cryptography as its loop device + if (!mountedVolume->LoopDevice.IsEmpty() && wstring (mountedVolume->LoopDevice) != wstring (mountedVolume->Path)) { try { diff --git a/src/Core/Unix/Linux/CoreLinux.cpp b/src/Core/Unix/Linux/CoreLinux.cpp index 3c7f6692..922c65a4 100644 --- a/src/Core/Unix/Linux/CoreLinux.cpp +++ b/src/Core/Unix/Linux/CoreLinux.cpp @@ -651,7 +651,11 @@ namespace VeraCrypt filesystemMounted = true; } - FuseService::SendAuxDeviceInfo (auxMountPoint, nativeDevPath, volumePath); + // Dismounting detaches the recorded loop device, so record only one attached above + if (loopDevAttached) + FuseService::SendAuxDeviceInfo (auxMountPoint, nativeDevPath, volumePath); + else + FuseService::SendAuxDeviceInfo (auxMountPoint, nativeDevPath); } catch (...) {