Skip to content

Commit

Permalink
Kernel - Lock Fcb during setFileInfo notify report change
Browse files Browse the repository at this point in the history
  • Loading branch information
Liryna committed Jan 28, 2022
1 parent eda8609 commit f03d51a
Showing 1 changed file with 63 additions and 45 deletions.
108 changes: 63 additions & 45 deletions sys/fileinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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,
Expand All @@ -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;
Expand All @@ -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)
Expand Down Expand Up @@ -927,4 +942,7 @@ VOID DokanCompleteSetInformation(__in PREQUEST_CONTEXT RequestContext,
FILE_ACTION_MODIFIED);
break;
}
if (fcbLocked) {
DokanFCBUnlock(fcb);
}
}

0 comments on commit f03d51a

Please sign in to comment.