Skip to content

Commit b18c2d3

Browse files
committed
Windows: Implement mutex to serialize initialization across multiple VeraCrypt instances
When multiple VeraCrypt.exe instances were launched simultaneously, race conditions could occur during the WM_INITDIALOG processing phase, potentially causing application crashes or hang. This was because the initialization logic handles critical operations like mounting/unmounting volumes and processing favorite volumes that modify global system state. This commit: - Adds a named local session mutex (MainInitMutex) that serializes the WM_INITDIALOG handler - Implements proper acquisition and release of the mutex during initialization - Ensures proper cleanup of mutex resources on application exit
1 parent e142999 commit b18c2d3

1 file changed

Lines changed: 61 additions & 1 deletion

File tree

src/Mount/Mount.c

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,10 @@ static DWORD LastKnownLogicalDrives;
187187

188188
static volatile LONG FavoriteMountOnGoing = 0;
189189

190+
191+
const wchar_t* MainInitMutexName = L"Local\\VeraCryptMainInit_02B831C5_401D_4A0D_8CC5_98D2C4CEB5F2";
192+
static HANDLE MainInitMutex = NULL; /* Mutex for main dialog WM_INITDIALOG */
193+
static BOOL MainInitMutexAcquired = FALSE; /* TRUE if the main window mutex has been acquired */
190194
static HANDLE TaskBarIconMutex = NULL;
191195
static BOOL MainWindowHidden = FALSE;
192196
static int pwdChangeDlgMode = PCDM_CHANGE_PASSWORD;
@@ -202,6 +206,29 @@ static HMODULE hWtsLib = NULL;
202206
static WTSREGISTERSESSIONNOTIFICATION fnWtsRegisterSessionNotification = NULL;
203207
static WTSUNREGISTERSESSIONNOTIFICATION fnWtsUnRegisterSessionNotification = NULL;
204208

209+
void AcquireMainInitMutex ()
210+
{
211+
if (MainInitMutex && !MainInitMutexAcquired)
212+
{
213+
DWORD dwWaitResult;
214+
dwWaitResult = WaitForSingleObject (MainInitMutex, INFINITE);
215+
if (dwWaitResult == WAIT_OBJECT_0 || dwWaitResult == WAIT_ABANDONED)
216+
{
217+
// Mutex acquired successfully
218+
MainInitMutexAcquired = TRUE;
219+
}
220+
}
221+
}
222+
223+
void ReleaseMainInitMutex ()
224+
{
225+
if (MainInitMutex && MainInitMutexAcquired)
226+
{
227+
ReleaseMutex (MainInitMutex);
228+
MainInitMutexAcquired = FALSE;
229+
}
230+
}
231+
205232
// Used to opt-in to receive notification about power events.
206233
// This is mandatory to support Windows 10 Modern Standby and Windows 8.1 Connected Standby power model.
207234
// https://docs.microsoft.com/en-us/windows-hardware/design/device-experiences/prepare-software-for-modern-standby
@@ -426,6 +453,13 @@ static void localcleanup (void)
426453
}
427454

428455
RandStop (TRUE);
456+
457+
if (MainInitMutex != NULL)
458+
{
459+
ReleaseMainInitMutex ();
460+
CloseHandle (MainInitMutex);
461+
MainInitMutex = NULL;
462+
}
429463
}
430464

431465
#ifndef BS_SPLITBUTTON
@@ -7093,6 +7127,9 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
70937127
bUseSecureDesktop = FALSE;
70947128
bUseLegacyMaxPasswordLength = FALSE;
70957129

7130+
// lock the init mutex
7131+
AcquireMainInitMutex ();
7132+
70967133
ResetWrongPwdRetryCount ();
70977134

70987135
ExtractCommandLine (hwndDlg, (wchar_t *) lParam);
@@ -7149,7 +7186,8 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
71497186
if (ComServerMode)
71507187
{
71517188
InitDialog (hwndDlg);
7152-
7189+
// unlock mutex since we are starting the COM server
7190+
ReleaseMainInitMutex ();
71537191
if (!ComServerMain ())
71547192
{
71557193
handleWin32Error (hwndDlg, SRC_POS);
@@ -7532,6 +7570,8 @@ BOOL CALLBACK MainDialogProc (HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa
75327570
RegisterWtsAndPowerNotification(hwndDlg);
75337571
DoPostInstallTasks (hwndDlg);
75347572
ResetCurrentDirectory ();
7573+
// unlock the init mutex
7574+
ReleaseMainInitMutex ();
75357575
}
75367576
return 0;
75377577

@@ -10201,6 +10241,26 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, wchar_t *lpsz
1020110241
AbortProcess ("NODRIVER");
1020210242
}
1020310243

10244+
/* Initialize Main mutex */
10245+
SECURITY_ATTRIBUTES sa;
10246+
SECURITY_DESCRIPTOR sd;
10247+
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
10248+
sa.lpSecurityDescriptor = &sd;
10249+
sa.bInheritHandle = FALSE;
10250+
10251+
// Initialize a security descriptor with a NULL DACL (everyone full access)
10252+
if (InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION) &&
10253+
SetSecurityDescriptorDacl(&sd, TRUE, NULL, FALSE))
10254+
{
10255+
// Use the security attributes when creating the mutex
10256+
MainInitMutex = CreateMutexW(&sa, FALSE, MainInitMutexName);
10257+
}
10258+
else
10259+
{
10260+
// If security descriptor initialization fails, fall back to default security attributes
10261+
MainInitMutex = CreateMutexW(NULL, FALSE, MainInitMutexName);
10262+
}
10263+
1020410264
/* Create the main dialog box */
1020510265
DialogBoxParamW (hInstance, MAKEINTRESOURCEW (IDD_MOUNT_DLG), NULL, (DLGPROC) MainDialogProc,
1020610266
(LPARAM) lpszCommandLine);

0 commit comments

Comments
 (0)