From f03d51a76bdbfaab0b78cd72e6fe8378d66b266e Mon Sep 17 00:00:00 2001 From: Liryna Date: Mon, 24 Jan 2022 09:20:16 -0500 Subject: [PATCH] Kernel - Lock Fcb during setFileInfo notify report change --- sys/fileinfo.c | 108 ++++++++++++++++++++++++++++--------------------- 1 file changed, 63 insertions(+), 45 deletions(-) diff --git a/sys/fileinfo.c b/sys/fileinfo.c index ae14b7e5..ec0bacd6 100644 --- a/sys/fileinfo.c +++ b/sys/fileinfo.c @@ -797,6 +797,8 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext, __in PEVENT_INFORMATION EventInfo) { PDokanCCB ccb; PDokanFCB fcb = NULL; + BOOLEAN fcbLocked = TRUE; + UNICODE_STRING oldFileName; FILE_INFORMATION_CLASS infoClass; RequestContext->Irp->IoStatus.Information = EventInfo->BufferLength; @@ -805,6 +807,9 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext, ccb = RequestContext->IrpSp->FileObject->FsContext2; ASSERT(ccb != NULL); + fcb = ccb->Fcb; + ASSERT(fcb != NULL); + infoClass = RequestContext->IrpSp->Parameters.SetFile.FileInformationClass; DOKAN_LOG_FINE_IRP(RequestContext, "FileObject=%p infoClass=%s", RequestContext->IrpSp->FileObject, @@ -816,30 +821,17 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext, return; } - fcb = ccb->Fcb; - ASSERT(fcb != NULL); - - switch (RequestContext->IrpSp->Parameters.SetFile.FileInformationClass) { - case FileAllocationInformation: - DokanNotifyReportChange(RequestContext, fcb, FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED); - break; - case FileBasicInformation: - DokanNotifyReportChange( - RequestContext, fcb, - FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE | - FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION, - FILE_ACTION_MODIFIED); - break; + // Process changes + switch (infoClass) { case FileDispositionInformation: case FileDispositionInformationEx: { + // Note that we do not acquire the resource for paging file + // operations in order to avoid deadlock with Mm + fcbLocked = !(RequestContext->Irp->Flags & IRP_PAGING_IO); + if (fcbLocked) { + DokanFCBLockRW(fcb); + } if (EventInfo->Operation.Delete.DeleteOnClose) { - // Note that we do not acquire the resource for paging file - // operations in order to avoid deadlock with Mm - BOOLEAN fcbLocked = !(RequestContext->Irp->Flags & IRP_PAGING_IO); - if (fcbLocked) { - DokanFCBLockRW(fcb); - } if (!MmFlushImageSection(&fcb->SectionObjectPointers, MmFlushForDelete)) { DOKAN_LOG_FINE_IRP(RequestContext, "Cannot delete user mapped image"); RequestContext->Irp->IoStatus.Status = STATUS_CANNOT_DELETE; @@ -849,53 +841,76 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext, DOKAN_LOG_FINE_IRP(RequestContext, "FileObject->DeletePending = TRUE"); RequestContext->IrpSp->FileObject->DeletePending = TRUE; } - if (fcbLocked) { - DokanFCBUnlock(fcb); - } + } else { DokanCCBFlagsClearBit(ccb, DOKAN_DELETE_ON_CLOSE); DokanFCBFlagsClearBit(fcb, DOKAN_DELETE_ON_CLOSE); DOKAN_LOG_FINE_IRP(RequestContext, "FileObject->DeletePending = FALSE"); RequestContext->IrpSp->FileObject->DeletePending = FALSE; } - if (RequestContext->IrpSp->FileObject->DeletePending) { - if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) { - DokanNotifyReportChange(RequestContext, fcb, - FILE_NOTIFY_CHANGE_DIR_NAME, - FILE_ACTION_REMOVED); - } else { - DokanNotifyReportChange(RequestContext, fcb, - FILE_NOTIFY_CHANGE_FILE_NAME, - FILE_ACTION_REMOVED); - } - } - } break; - case FileEndOfFileInformation: - DokanNotifyReportChange(RequestContext, fcb, FILE_NOTIFY_CHANGE_SIZE, - FILE_ACTION_MODIFIED); break; - case FileRenameInformationEx: - case FileRenameInformation: { + } + case FileRenameInformation: + case FileRenameInformationEx: { + DokanVCBLockRW(RequestContext->Vcb); DokanFCBLockRW(fcb); // Process rename - UNICODE_STRING oldFileName = + oldFileName = DokanWrapUnicodeString(fcb->FileName.Buffer, fcb->FileName.Length); // Copy new file name PVOID buffer = DokanAllocZero(EventInfo->BufferLength + sizeof(WCHAR)); if (buffer == NULL) { RequestContext->Irp->IoStatus.Status = STATUS_INSUFFICIENT_RESOURCES; DokanFCBUnlock(fcb); + DokanVCBUnlock(RequestContext->Vcb); return; } RtlCopyMemory(buffer, EventInfo->Buffer, EventInfo->BufferLength); - DokanVCBLockRW(RequestContext->Vcb); DokanRenameFcb(RequestContext, fcb, buffer, (USHORT)EventInfo->BufferLength); DokanVCBUnlock(RequestContext->Vcb); DOKAN_LOG_FINE_IRP(RequestContext, "Fcb=%p renamed \"%wZ\"", fcb, &fcb->FileName); - DokanFCBUnlock(fcb); - // Notify rename + break; + } + default: + DokanFCBLockRO(fcb); + break; + } + + // Notify changes + switch (infoClass) { + case FileAllocationInformation: + DokanNotifyReportChange(RequestContext, fcb, FILE_NOTIFY_CHANGE_SIZE, + FILE_ACTION_MODIFIED); + break; + case FileBasicInformation: + DokanNotifyReportChange( + RequestContext, fcb, + FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_LAST_WRITE | + FILE_NOTIFY_CHANGE_LAST_ACCESS | FILE_NOTIFY_CHANGE_CREATION, + FILE_ACTION_MODIFIED); + break; + case FileDispositionInformation: + case FileDispositionInformationEx: + if (RequestContext->IrpSp->FileObject->DeletePending) { + if (DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY)) { + DokanNotifyReportChange(RequestContext, fcb, + FILE_NOTIFY_CHANGE_DIR_NAME, + FILE_ACTION_REMOVED); + } else { + DokanNotifyReportChange(RequestContext, fcb, + FILE_NOTIFY_CHANGE_FILE_NAME, + FILE_ACTION_REMOVED); + } + } + break; + case FileEndOfFileInformation: + DokanNotifyReportChange(RequestContext, fcb, FILE_NOTIFY_CHANGE_SIZE, + FILE_ACTION_MODIFIED); + break; + case FileRenameInformation: + case FileRenameInformationEx: { if (IsInSameDirectory(&oldFileName, &fcb->FileName)) { DokanNotifyReportChange0(RequestContext, fcb, &oldFileName, DokanFCBFlagsIsSet(fcb, DOKAN_FILE_DIRECTORY) @@ -927,4 +942,7 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext, FILE_ACTION_MODIFIED); break; } + if (fcbLocked) { + DokanFCBUnlock(fcb); + } }