Harden encryption fragment completion against queue slot reuse

Capture the parent before releasing a fragment slot on Windows and Unix.
This removes the completion code's dependency on the first-fragment slot
holding up the ring until the requester observes completion.
This commit is contained in:
Mounir IDRASSI
2026-10-16 18:05:24 +09:00
parent 762b374db0
commit 0cb9fad329
2 changed files with 11 additions and 6 deletions
+6 -3
View File
@@ -192,6 +192,7 @@ static void SetWorkItemState (EncryptionThreadPoolWorkItem *workItem, WorkItemSt
static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
{
EncryptionThreadPoolWorkItem *workItem;
EncryptionThreadPoolWorkItem *firstFragment;
if (threadArg)
{
#ifdef DEVICE_DRIVER
@@ -333,14 +334,16 @@ static TC_THREAD_PROC EncryptionThreadProc (void *threadArg)
TC_THROW_FATAL_EXCEPTION;
}
if (workItem != workItem->FirstFragment)
// Keep the parent reference before releasing this queue slot.
firstFragment = workItem->FirstFragment;
if (workItem != firstFragment)
{
SetWorkItemState (workItem, WorkItemFree);
TC_SET_EVENT (WorkItemCompletedEvent);
}
if (InterlockedDecrement (&workItem->FirstFragment->OutstandingFragmentCount) == 0)
TC_SET_EVENT (workItem->FirstFragment->ItemCompletedEvent);
if (InterlockedDecrement (&firstFragment->OutstandingFragmentCount) == 0)
TC_SET_EVENT (firstFragment->ItemCompletedEvent);
}
#ifdef DEVICE_DRIVER
+5 -3
View File
@@ -375,14 +375,16 @@ namespace VeraCrypt
continue;
}
if (workItem != workItem->FirstFragment)
// Keep the parent reference before releasing this queue slot.
WorkItem *firstFragment = workItem->FirstFragment;
if (workItem != firstFragment)
{
workItem->State.Set (WorkItem::State::Free);
WorkItemCompletedEvent.Signal();
}
if (workItem->FirstFragment->OutstandingFragmentCount.Decrement() == 0)
workItem->FirstFragment->ItemCompletedEvent.Signal();
if (firstFragment->OutstandingFragmentCount.Decrement() == 0)
firstFragment->ItemCompletedEvent.Signal();
}
}
catch (exception &e)