VeraCrypt
aboutsummaryrefslogtreecommitdiff
path: root/src/Core/Unix/CoreUnix.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Core/Unix/CoreUnix.cpp')
-rw-r--r--src/Core/Unix/CoreUnix.cpp49
1 files changed, 37 insertions, 12 deletions
diff --git a/src/Core/Unix/CoreUnix.cpp b/src/Core/Unix/CoreUnix.cpp
index 0b248fb9..1868eb6d 100644
--- a/src/Core/Unix/CoreUnix.cpp
+++ b/src/Core/Unix/CoreUnix.cpp
@@ -1,57 +1,54 @@
/*
Derived from source code of TrueCrypt 7.1a, which is
Copyright (c) 2008-2012 TrueCrypt Developers Association and which is governed
by the TrueCrypt License 3.0.
Modifications and additions to the original source code (contained in this file)
and all other portions of this file are Copyright (c) 2013-2017 IDRIX
and are governed by the Apache License 2.0 the full text of which is
contained in the file License.txt included in VeraCrypt binary and source
code distribution packages.
*/
#include "CoreUnix.h"
#include <errno.h>
#include <iostream>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <stdio.h>
#include <unistd.h>
#include "Platform/FileStream.h"
#include "Driver/Fuse/FuseService.h"
#include "Volume/VolumePasswordCache.h"
-template<typename T>
-inline void ignore_result(const T & /* unused result */) {}
-
namespace VeraCrypt
{
#ifdef TC_LINUX
static string GetTmpUser ();
static bool SamePath (const string& path1, const string& path2);
#endif
CoreUnix::CoreUnix ()
{
signal (SIGPIPE, SIG_IGN);
char *loc = setlocale (LC_ALL, "");
if (!loc || string (loc) == "C")
setlocale (LC_ALL, "en_US.UTF-8");
}
CoreUnix::~CoreUnix ()
{
}
void CoreUnix::CheckFilesystem (shared_ptr <VolumeInfo> mountedVolume, bool repair) const
{
if (!mountedVolume->MountPoint.IsEmpty())
DismountFilesystem (mountedVolume->MountPoint, false);
list <string> args;
args.push_back ("-T");
args.push_back ("fsck");
@@ -217,61 +214,61 @@ namespace VeraCrypt
|| fs.Type == "fatfs"
|| fs.Type == "msdos"
|| fs.Type == "msdosfs"
|| fs.Type == "umsdos"
|| fs.Type == "dos"
|| fs.Type == "dosfs"
|| fs.Type == "pcfs"
)
{
return false;
}
return true;
}
}
catch (...) { }
}
return true; // Prevent errors if the filesystem cannot be identified
}
bool CoreUnix::FilesystemSupportsUnixPermissions (const DevicePath &devicePath) const
{
File device;
device.Open (devicePath);
Buffer bootSector (device.GetDeviceSectorSize());
device.SeekAt (0);
device.ReadCompleteBuffer (bootSector);
- byte *b = bootSector.Ptr();
+ uint8 *b = bootSector.Ptr();
return memcmp (b + 3, "NTFS", 4) != 0
&& memcmp (b + 54, "FAT", 3) != 0
&& memcmp (b + 82, "FAT32", 5) != 0
&& memcmp (b + 3, "EXFAT", 5) != 0;
}
string CoreUnix::GetDefaultMountPointPrefix () const
{
const char *envPrefix = getenv ("VERACRYPT_MOUNT_PREFIX");
if (envPrefix && !string (envPrefix).empty())
return envPrefix;
if (FilesystemPath ("/media").IsDirectory())
return "/media/veracrypt";
if (FilesystemPath ("/mnt").IsDirectory())
return "/mnt/veracrypt";
return GetTempDirectory() + "/veracrypt_mnt";
}
uint32 CoreUnix::GetDeviceSectorSize (const DevicePath &devicePath) const
{
File dev;
dev.Open (devicePath);
return dev.GetDeviceSectorSize();
}
uint64 CoreUnix::GetDeviceSize (const DevicePath &devicePath) const
@@ -279,71 +276,99 @@ namespace VeraCrypt
File dev;
dev.Open (devicePath);
return dev.Length();
}
DirectoryPath CoreUnix::GetDeviceMountPoint (const DevicePath &devicePath) const
{
DevicePath devPath = devicePath;
#ifdef TC_MACOSX
if (string (devPath).find ("/dev/rdisk") != string::npos)
devPath = string ("/dev/") + string (devicePath).substr (6);
#endif
MountedFilesystemList mountedFilesystems = GetMountedFilesystems (devPath);
if (mountedFilesystems.size() < 1)
return DirectoryPath();
return mountedFilesystems.front()->MountPoint;
}
VolumeInfoList CoreUnix::GetMountedVolumes (const VolumePath &volumePath) const
{
VolumeInfoList volumes;
foreach_ref (const MountedFilesystem &mf, GetMountedFilesystems ())
{
if (string (mf.MountPoint).find (GetFuseMountDirPrefix()) == string::npos)
continue;
shared_ptr <VolumeInfo> mountedVol;
- try
+ // Introduce a retry mechanism with a timeout for control file access
+ // This workaround is limited to FUSE-T mounted volume under macOS for
+ // which md.Device starts with "fuse-t:"
+#ifdef VC_MACOSX_FUSET
+ bool isFuseT = wstring(mf.Device).find(L"fuse-t:") == 0;
+ int controlFileRetries = 10; // 10 retries with 500ms sleep each, total 5 seconds
+ while (!mountedVol && (controlFileRetries-- > 0))
+#endif
{
- shared_ptr <File> controlFile (new File);
- controlFile->Open (string (mf.MountPoint) + FuseService::GetControlPath());
+ try
+ {
+ shared_ptr <File> controlFile (new File);
+ controlFile->Open (string (mf.MountPoint) + FuseService::GetControlPath());
- shared_ptr <Stream> controlFileStream (new FileStream (controlFile));
- mountedVol = Serializable::DeserializeNew <VolumeInfo> (controlFileStream);
+ shared_ptr <Stream> controlFileStream (new FileStream (controlFile));
+ mountedVol = Serializable::DeserializeNew <VolumeInfo> (controlFileStream);
+ }
+ catch (const std::exception& e)
+ {
+#ifdef VC_MACOSX_FUSET
+ // if exception starts with "VeraCrypt::Serializer::ValidateName", then
+ // serialization is not ready yet and we need to wait before retrying
+ // this happens when FUSE-T is used under macOS and if it is the first time
+ // the volume is mounted
+ if (isFuseT && string (e.what()).find ("VeraCrypt::Serializer::ValidateName") != string::npos)
+ {
+ Thread::Sleep(500); // Wait before retrying
+ }
+ else
+ {
+ break; // Control file not found or other error
+ }
+#endif
+ }
}
- catch (...)
+
+ if (!mountedVol)
{
- continue;
+ continue; // Skip to the next mounted filesystem
}
if (!volumePath.IsEmpty() && wstring (mountedVol->Path).compare (volumePath) != 0)
continue;
mountedVol->AuxMountPoint = mf.MountPoint;
if (!mountedVol->VirtualDevice.IsEmpty())
{
MountedFilesystemList mpl = GetMountedFilesystems (mountedVol->VirtualDevice);
if (mpl.size() > 0)
mountedVol->MountPoint = mpl.front()->MountPoint;
}
volumes.push_back (mountedVol);
if (!volumePath.IsEmpty())
break;
}
return volumes;
}
gid_t CoreUnix::GetRealGroupId () const
{
const char *env = getenv ("SUDO_GID");
if (env)
{
try
@@ -667,61 +692,61 @@ namespace VeraCrypt
}
try
{
try
{
MountVolumeNative (volume, options, fuseMountPoint);
}
catch (NotApplicable&)
{
MountAuxVolumeImage (fuseMountPoint, options);
}
}
catch (...)
{
if (mountDirCreated)
remove (mountPoint.c_str());
throw;
}
#ifndef TC_MACOSX
// set again correct ownership of the mount point to avoid any issues
if (!options.NoFilesystem && options.MountPoint)
{
mountPoint = *options.MountPoint;
if (mountPoint.find (GetDefaultMountPointPrefix()) == 0)
{
try
{
- ignore_result(chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()));
+ throw_sys_sub_if (chown (mountPoint.c_str(), GetRealUserId(), GetRealGroupId()) == -1, mountPoint);
} catch (...) { }
}
}
#endif
}
catch (...)
{
try
{
VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path);
if (mountedVolumes.size() > 0)
{
shared_ptr <VolumeInfo> mountedVolume (mountedVolumes.front());
DismountVolume (mountedVolume);
}
}
catch (...) { }
throw;
}
VolumeInfoList mountedVolumes = GetMountedVolumes (*options.Path);
if (mountedVolumes.size() != 1)
throw ParameterIncorrect (SRC_POS);
VolumeEventArgs eventArgs (mountedVolumes.front());
VolumeMountedEvent.Raise (eventArgs);
return mountedVolumes.front();
}