diff --git a/src/Main/Forms/VolumeCreationWizard.cpp b/src/Main/Forms/VolumeCreationWizard.cpp index d1ab7789..ed72f839 100644 --- a/src/Main/Forms/VolumeCreationWizard.cpp +++ b/src/Main/Forms/VolumeCreationWizard.cpp @@ -22,6 +22,9 @@ #include "Core/VolumeCreator.h" #include "Main/Application.h" #include "Main/GraphicUserInterface.h" +#ifdef TC_MACOSX +#include "Main/MacOSXFormatterDevice.h" +#endif #include "Main/Resources.h" #include "VolumeCreationWizard.h" #include "EncryptionOptionsWizardPage.h" @@ -194,20 +197,6 @@ namespace VeraCrypt return path; } - static string GetMacOSXRawDevicePath (const string &deviceIdentifier) - { - if (deviceIdentifier.find ("/dev/rdisk") == 0) - return deviceIdentifier; - - if (deviceIdentifier.find ("/dev/disk") == 0) - return string ("/dev/r") + deviceIdentifier.substr (5); - - if (deviceIdentifier.find ("disk") == 0) - return string ("/dev/r") + deviceIdentifier; - - return deviceIdentifier; - } - static string GetMacOSXDiskutilInfo (const VolumePath &devicePath) { list args; @@ -844,14 +833,20 @@ namespace VeraCrypt Thread::Sleep (2000); // Try to prevent race conditions caused by OS // Temporarily take ownership of the device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - DevicePath virtualDevice = volume->VirtualDevice; #ifdef TC_MACOSX string virtualDeviceStr = virtualDevice; - if (virtualDeviceStr.find ("/dev/rdisk") != 0) - virtualDevice = "/dev/r" + virtualDeviceStr.substr (5); -#endif + virtualDevice = GetMacOSXRawDevicePath (virtualDeviceStr); + + MacOSXFormatterDeviceOwnerRestoreList changedDeviceOwners; + finally_do_arg (MacOSXFormatterDeviceOwnerRestoreList *, &changedDeviceOwners, + { + RestoreMacOSXFormatterDeviceOwners (*finally_arg); + }); + PrepareMacOSXFormatterDevice (virtualDevice, changedDeviceOwners); +#else + UserId origDeviceOwner ((uid_t) -1); + try { File file; @@ -871,6 +866,7 @@ namespace VeraCrypt if (finally_arg2.SystemId != (uid_t) -1) Core->SetFileOwner (finally_arg, finally_arg2); }); +#endif // Create filesystem list args; diff --git a/src/Main/MacOSXFormatterDevice.h b/src/Main/MacOSXFormatterDevice.h new file mode 100644 index 00000000..4eb7d3e4 --- /dev/null +++ b/src/Main/MacOSXFormatterDevice.h @@ -0,0 +1,131 @@ +/* + VeraCrypt source code + Copyright (c) 2026 AM Crypto + + This file is part of VeraCrypt and is 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. +*/ + +#ifndef VC_HEADER_Main_MacOSXFormatterDevice +#define VC_HEADER_Main_MacOSXFormatterDevice + +#include "Main/Main.h" + +#ifdef TC_MACOSX +#include + +namespace VeraCrypt +{ + inline bool IsMacOSXDiskDevicePath (const string &deviceIdentifier, const string &prefix) + { + return deviceIdentifier.find (prefix) == 0 + && deviceIdentifier.size() > prefix.size() + && deviceIdentifier[prefix.size()] >= '0' + && deviceIdentifier[prefix.size()] <= '9'; + } + + inline string GetMacOSXRawDevicePath (const string &deviceIdentifier) + { + if (IsMacOSXDiskDevicePath (deviceIdentifier, "/dev/rdisk")) + return deviceIdentifier; + + if (IsMacOSXDiskDevicePath (deviceIdentifier, "/dev/disk")) + return string ("/dev/rdisk") + deviceIdentifier.substr (9); + + if (IsMacOSXDiskDevicePath (deviceIdentifier, "rdisk")) + return string ("/dev/") + deviceIdentifier; + + if (IsMacOSXDiskDevicePath (deviceIdentifier, "disk")) + return string ("/dev/r") + deviceIdentifier; + + return deviceIdentifier; + } + + inline string GetMacOSXBlockDevicePath (const string &deviceIdentifier) + { + if (IsMacOSXDiskDevicePath (deviceIdentifier, "/dev/disk")) + return deviceIdentifier; + + if (IsMacOSXDiskDevicePath (deviceIdentifier, "/dev/rdisk")) + return string ("/dev/disk") + deviceIdentifier.substr (10); + + if (IsMacOSXDiskDevicePath (deviceIdentifier, "disk")) + return string ("/dev/") + deviceIdentifier; + + if (IsMacOSXDiskDevicePath (deviceIdentifier, "rdisk")) + return string ("/dev/disk") + deviceIdentifier.substr (5); + + return deviceIdentifier; + } + + struct MacOSXFormatterDeviceOwnerRestore + { + MacOSXFormatterDeviceOwnerRestore (const FilesystemPath &path, const UserId &owner) + : Path (path), Owner (owner) { } + + FilesystemPath Path; + UserId Owner; + }; + + typedef list MacOSXFormatterDeviceOwnerRestoreList; + + inline void AddUniqueMacOSXDevicePath (list &paths, const string &path) + { + if (path.empty()) + return; + + foreach (const FilesystemPath &existingPath, paths) + { + if (string (existingPath) == path) + return; + } + + paths.push_back (FilesystemPath (path)); + } + + inline void PrepareMacOSXFormatterDevice (const DevicePath &devicePath, MacOSXFormatterDeviceOwnerRestoreList &changedDeviceOwners) + { + if (Core->HasAdminPrivileges()) + return; + + const string devicePathStr = devicePath; + list paths; + // APFS formatters may resolve /dev/rdiskN back to /dev/diskN internally. + AddUniqueMacOSXDevicePath (paths, devicePathStr); + AddUniqueMacOSXDevicePath (paths, GetMacOSXRawDevicePath (devicePathStr)); + AddUniqueMacOSXDevicePath (paths, GetMacOSXBlockDevicePath (devicePathStr)); + + foreach (const FilesystemPath &path, paths) + { + try + { + File file; + file.Open (path, File::OpenReadWrite); + } + catch (...) + { + UserId origDeviceOwner = path.GetOwner(); + // Register before chown so service-side success followed by + // an IPC failure can still be restored. + changedDeviceOwners.push_back (MacOSXFormatterDeviceOwnerRestore (path, origDeviceOwner)); + Core->SetFileOwner (path, UserId (getuid())); + } + } + } + + inline void RestoreMacOSXFormatterDeviceOwners (const MacOSXFormatterDeviceOwnerRestoreList &changedDeviceOwners) + { + foreach (const MacOSXFormatterDeviceOwnerRestore &restore, changedDeviceOwners) + { + try + { + Core->SetFileOwner (restore.Path, restore.Owner); + } + catch (...) { } + } + } +} +#endif // TC_MACOSX + +#endif // VC_HEADER_Main_MacOSXFormatterDevice diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index 2ff21a5a..a132c581 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -26,6 +26,9 @@ #include "Common/EMVToken.h" #include "Core/RandomNumberGenerator.h" #include "Application.h" +#ifdef TC_MACOSX +#include "Main/MacOSXFormatterDevice.h" +#endif #include "TextUserInterface.h" namespace VeraCrypt @@ -1065,14 +1068,20 @@ namespace VeraCrypt Thread::Sleep (2000); // Try to prevent race conditions caused by OS // Temporarily take ownership of the device if the user is not an administrator - UserId origDeviceOwner ((uid_t) -1); - DevicePath virtualDevice = volume->VirtualDevice; #ifdef TC_MACOSX string virtualDeviceStr = virtualDevice; - if (virtualDeviceStr.find ("/dev/rdisk") != 0) - virtualDevice = "/dev/r" + virtualDeviceStr.substr (5); -#endif + virtualDevice = GetMacOSXRawDevicePath (virtualDeviceStr); + + MacOSXFormatterDeviceOwnerRestoreList changedDeviceOwners; + finally_do_arg (MacOSXFormatterDeviceOwnerRestoreList *, &changedDeviceOwners, + { + RestoreMacOSXFormatterDeviceOwners (*finally_arg); + }); + PrepareMacOSXFormatterDevice (virtualDevice, changedDeviceOwners); +#else + UserId origDeviceOwner ((uid_t) -1); + try { File file; @@ -1092,6 +1101,7 @@ namespace VeraCrypt if (finally_arg2.SystemId != (uid_t) -1) Core->SetFileOwner (finally_arg, finally_arg2); }); +#endif // Create filesystem list args;