[FASTFAT] Ensure that deferred write IRP contexts are not touched. CORE-17328

Cc may decide to process deferred writes any time, so the context might
already be freed by the time we return from CcDeferWrite.
Also mark the IRP as pending, since we're going to return STATUS_PENDING.
This commit is contained in:
Thomas Faber 2020-10-11 15:02:26 +02:00
parent 6b3f309a08
commit 320abafdc3
No known key found for this signature in database
GPG key ID: 076E7C3D44720826
3 changed files with 34 additions and 28 deletions

View file

@ -130,7 +130,7 @@ VfatDispatchRequest(
break;
case IRP_MJ_WRITE:
Status = VfatWrite(IrpContext);
Status = VfatWrite(&IrpContext);
break;
case IRP_MJ_FILE_SYSTEM_CONTROL:
@ -182,30 +182,33 @@ VfatDispatchRequest(
Status = STATUS_DRIVER_INTERNAL_ERROR;
}
QueueIrp = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_QUEUE);
CompleteIrp = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_COMPLETE);
ASSERT((!CompleteIrp && !QueueIrp) ||
(CompleteIrp && !QueueIrp) ||
(!CompleteIrp && QueueIrp));
if (CompleteIrp)
if (IrpContext != NULL)
{
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest(IrpContext->Irp, IrpContext->PriorityBoost);
}
QueueIrp = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_QUEUE);
CompleteIrp = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_COMPLETE);
if (QueueIrp)
{
/* Reset our status flags before queueing the IRP */
IrpContext->Flags |= IRPCONTEXT_COMPLETE;
IrpContext->Flags &= ~IRPCONTEXT_QUEUE;
Status = VfatQueueRequest(IrpContext);
}
else
{
/* Unless the IRP was queued, always free the IRP context */
VfatFreeIrpContext(IrpContext);
ASSERT((!CompleteIrp && !QueueIrp) ||
(CompleteIrp && !QueueIrp) ||
(!CompleteIrp && QueueIrp));
if (CompleteIrp)
{
IrpContext->Irp->IoStatus.Status = Status;
IoCompleteRequest(IrpContext->Irp, IrpContext->PriorityBoost);
}
if (QueueIrp)
{
/* Reset our status flags before queueing the IRP */
IrpContext->Flags |= IRPCONTEXT_COMPLETE;
IrpContext->Flags &= ~IRPCONTEXT_QUEUE;
Status = VfatQueueRequest(IrpContext);
}
else
{
/* Unless the IRP was queued, always free the IRP context */
VfatFreeIrpContext(IrpContext);
}
}
FsRtlExitFileSystem();

View file

@ -873,8 +873,9 @@ ByeBye:
NTSTATUS
VfatWrite(
PVFAT_IRP_CONTEXT IrpContext)
PVFAT_IRP_CONTEXT *pIrpContext)
{
PVFAT_IRP_CONTEXT IrpContext = *pIrpContext;
PVFATFCB Fcb;
PERESOURCE Resource = NULL;
LARGE_INTEGER ByteOffset;
@ -999,13 +1000,15 @@ VfatWrite(
Retrying = BooleanFlagOn(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
SetFlag(IrpContext->Flags, IRPCONTEXT_DEFERRED_WRITE);
IoMarkIrpPending(IrpContext->Irp);
Status = STATUS_PENDING;
DPRINT1("Deferring write for Irp %p, context %p!\n", IrpContext->Irp, IrpContext);
CcDeferWrite(IrpContext->FileObject, VfatHandleDeferredWrite,
IrpContext, NULL, Length, Retrying);
*pIrpContext = NULL;
DPRINT1("Dererring write!\n");
goto ByeBye;
return Status;
}
if (IsVolume)

View file

@ -1189,7 +1189,7 @@ VfatRead(
NTSTATUS
VfatWrite(
PVFAT_IRP_CONTEXT IrpContext);
PVFAT_IRP_CONTEXT *pIrpContext);
NTSTATUS
NextCluster(