From 610feb4c284d7ccbe8bf5505e052cb80c298c93a Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Fri, 29 May 2026 18:32:32 +0900 Subject: [PATCH] macOS: block partitioned disk alias bypass On macOS, the same whole disk can be addressed as both /dev/diskN and /dev/rdiskN. The GUI creation wizard only compared the selected path against the enumerated raw device path, so manually entering the block-device alias could bypass the existing DEVICE_PARTITIONS_ERR guard and allow formatting a disk that still had partitions. Add a shared macOS device-path comparison helper that normalizes paths to their raw-device form before comparison. Use it in the GUI wizard so /dev/diskN and /dev/rdiskN are treated as the same whole-disk target while partition paths remain distinct. Apply the same partitioned whole-device guard in the text/CLI creation path as well, including the macOS alias normalization, so command-line creation cannot format a partitioned top-level disk through an alternate device alias. Fixes #728 --- src/Main/Forms/VolumeCreationWizard.cpp | 7 ++++++- src/Main/MacOSXFormatterDevice.h | 5 +++++ src/Main/TextUserInterface.cpp | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/Main/Forms/VolumeCreationWizard.cpp b/src/Main/Forms/VolumeCreationWizard.cpp index 6f1001e6..3f74c092 100644 --- a/src/Main/Forms/VolumeCreationWizard.cpp +++ b/src/Main/Forms/VolumeCreationWizard.cpp @@ -1044,7 +1044,12 @@ namespace VeraCrypt foreach_ref (const HostDevice &drive, Core->GetHostDevices()) { - if (drive.Path == SelectedVolumePath && !drive.Partitions.empty()) + bool selectedWholeDevice = drive.Path == SelectedVolumePath; +#ifdef TC_MACOSX + selectedWholeDevice = selectedWholeDevice + || IsSameMacOSXDevicePath (string (drive.Path), string (SelectedVolumePath)); +#endif + if (selectedWholeDevice && !drive.Partitions.empty()) { foreach_ref (const HostDevice &partition, drive.Partitions) { diff --git a/src/Main/MacOSXFormatterDevice.h b/src/Main/MacOSXFormatterDevice.h index a62898f6..d841ae2c 100644 --- a/src/Main/MacOSXFormatterDevice.h +++ b/src/Main/MacOSXFormatterDevice.h @@ -61,6 +61,11 @@ namespace VeraCrypt return deviceIdentifier; } + inline bool IsSameMacOSXDevicePath (const string &firstDeviceIdentifier, const string &secondDeviceIdentifier) + { + return GetMacOSXRawDevicePath (firstDeviceIdentifier) == GetMacOSXRawDevicePath (secondDeviceIdentifier); + } + inline string GetMacOSXFormatterName (const string &fsFormatter) { size_t namePos = fsFormatter.find_last_of ('/'); diff --git a/src/Main/TextUserInterface.cpp b/src/Main/TextUserInterface.cpp index 2d8871f8..b343155f 100644 --- a/src/Main/TextUserInterface.cpp +++ b/src/Main/TextUserInterface.cpp @@ -684,6 +684,28 @@ namespace VeraCrypt } while (options->Path.IsEmpty()); } + if (options->Path.IsDevice()) + { + foreach_ref (const HostDevice &drive, Core->GetHostDevices()) + { + bool selectedWholeDevice = drive.Path == options->Path; +#ifdef TC_MACOSX + selectedWholeDevice = selectedWholeDevice + || IsSameMacOSXDevicePath (string (drive.Path), string (options->Path)); +#endif + if (selectedWholeDevice && !drive.Partitions.empty()) + { + foreach_ref (const HostDevice &partition, drive.Partitions) + { + if (partition.MountPoint == "/") + throw_err (LangString["LINUX_ERROR_TRY_ENCRYPT_SYSTEM_DRIVE"]); + } + + throw_err (LangString["DEVICE_PARTITIONS_ERR"]); + } + } + } + // Sector size if (options->Path.IsDevice()) options->SectorSize = Core->GetDeviceSectorSize (options->Path);