sys: FspFileNodeRename: acquire resource of descendant file nodes when renaming them

This commit is contained in:
Bill Zissimopoulos 2016-10-14 22:47:10 -07:00
parent 5a5a1008de
commit 5773c6eab7
3 changed files with 51 additions and 4 deletions

View File

@ -348,7 +348,8 @@ typedef struct
UINT64 UserContext2; UINT64 UserContext2;
} QueryStreamInformation; } QueryStreamInformation;
} Req; } Req;
FSP_FSCTL_TRANSACT_BUF FileName; /* {Create,Cleanup,SetInformation/{...},QueryDirectory} */ FSP_FSCTL_TRANSACT_BUF FileName;
/* Create,Cleanup,SetInformation{Disposition,Rename},FileSystemControl{ReparsePoint} */
FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[]; FSP_FSCTL_DECLSPEC_ALIGN UINT8 Buffer[];
} FSP_FSCTL_TRANSACT_REQ; } FSP_FSCTL_TRANSACT_REQ;
typedef struct typedef struct

View File

@ -514,13 +514,13 @@ NTSTATUS FspNotifyFullReportChange(
#define FspNotifyCleanupAll(NS, NL)\ #define FspNotifyCleanupAll(NS, NL)\
FsRtlNotifyCleanupAll(NS, NL) FsRtlNotifyCleanupAll(NS, NL)
#define FspNotifyChangeDirectory(NS, NL, FC, FN, WT, CF, I)\ #define FspNotifyChangeDirectory(NS, NL, FC, FN, WT, CF, I)\
FspNotifyFullChangeDirectory(NS, NL, FC, (PSTRING)FN, WT, FALSE, CF, I, 0, 0) FspNotifyFullChangeDirectory(NS, NL, FC, (PSTRING)(FN), WT, FALSE, CF, I, 0, 0)
#define FspNotifyCleanup(NS, NL, FC)\ #define FspNotifyCleanup(NS, NL, FC)\
FsRtlNotifyCleanup(NS, NL, FC) FsRtlNotifyCleanup(NS, NL, FC)
#define FspNotifyDeletePending(NS, NL, FC)\ #define FspNotifyDeletePending(NS, NL, FC)\
FspNotifyFullChangeDirectory(NS, NL, FC, 0, 0, FALSE, 0, 0, 0, 0) FspNotifyFullChangeDirectory(NS, NL, FC, 0, 0, FALSE, 0, 0, 0, 0)
#define FspNotifyReportChange(NS, NL, FN, FO, SN, F, A)\ #define FspNotifyReportChange(NS, NL, FN, FO, NP, F, A)\
FspNotifyFullReportChange(NS, NL, (PSTRING)FN, FO, (PSTRING)SN, 0, F, A, 0) FspNotifyFullReportChange(NS, NL, (PSTRING)(FN), FO, 0, (PSTRING)(NP), F, A, 0)
/* utility: synchronous work queue */ /* utility: synchronous work queue */
typedef struct typedef struct
@ -1026,6 +1026,27 @@ VOID FspFileNodeConvertExclusiveToSharedF(FSP_FILE_NODE *FileNode, ULONG Flags);
VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner); VOID FspFileNodeSetOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags); VOID FspFileNodeReleaseF(FSP_FILE_NODE *FileNode, ULONG Flags);
VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner); VOID FspFileNodeReleaseOwnerF(FSP_FILE_NODE *FileNode, ULONG Flags, PVOID Owner);
static inline
VOID FspFileNodeAcquireSharedForeign(FSP_FILE_NODE *FileNode)
{
if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode;
ExAcquireResourceSharedLite(FileNode->Header.Resource, TRUE);
}
static inline
VOID FspFileNodeAcquireExclusiveForeign(FSP_FILE_NODE *FileNode)
{
if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode;
ExAcquireResourceExclusiveLite(FileNode->Header.Resource, TRUE);
}
static inline
VOID FspFileNodeReleaseForeign(FSP_FILE_NODE *FileNode)
{
if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode;
ExReleaseResourceLite(FileNode->Header.Resource);
}
FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, FSP_FILE_NODE *FspFileNodeOpen(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,
UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult); UINT32 GrantedAccess, UINT32 ShareAccess, NTSTATUS *PResult);
VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject, VOID FspFileNodeCleanup(FSP_FILE_NODE *FileNode, PFILE_OBJECT FileObject,

View File

@ -803,6 +803,25 @@ NTSTATUS FspFileNodeFlushAndPurgeCache(FSP_FILE_NODE *FileNode,
VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName) VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName)
{ {
/*
* FspFileNodeRename may block, because it attempts to acquire the Main
* resource of descendant file nodes. FspFileNodeRename is called at the
* completion path of IRP_MJ_SET_INFORMATION[Rename] and an IRP completion
* path should not block, with the notable exception of Rename.
*
* The original reason that Rename completion is allowed to block was that
* it was observed that IoCompleteRequest of a Rename could sometimes
* trigger a recursive call into the FSD (likely due to a filter). WinFsp
* was modified to accommodate this by allowing this recursive call to
* proceed on a different thread.
*
* Since WinFsp can already accommodate blocking on Rename completions,
* it is safe to acquire the Main resource of descendant file nodes.
*
* Note also that there can only be one rename at a time because of the
* device's FileRenameResource.
*/
PAGED_CODE(); PAGED_CODE();
PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject; PDEVICE_OBJECT FsvolDeviceObject = FileNode->FsvolDeviceObject;
@ -862,6 +881,9 @@ VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName)
DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex]; DescendantFileNode = DescendantFileNodes[DescendantFileNodeIndex];
ASSERT(DescendantFileNode->FileName.Length >= FileNameLength); ASSERT(DescendantFileNode->FileName.Length >= FileNameLength);
if (0 != DescendantFileNodeIndex)
FspFileNodeAcquireExclusiveForeign(DescendantFileNode);
FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &DescendantFileNode->FileName, &Deleted); FspFsvolDeviceDeleteContextByName(FsvolDeviceObject, &DescendantFileNode->FileName, &Deleted);
ASSERT(Deleted); ASSERT(Deleted);
@ -888,6 +910,9 @@ VOID FspFileNodeRename(FSP_FILE_NODE *FileNode, PUNICODE_STRING NewFileName)
FspFsvolDeviceInsertContextByName(FsvolDeviceObject, &DescendantFileNode->FileName, DescendantFileNode, FspFsvolDeviceInsertContextByName(FsvolDeviceObject, &DescendantFileNode->FileName, DescendantFileNode,
&DescendantFileNode->ContextByNameElementStorage, &Inserted); &DescendantFileNode->ContextByNameElementStorage, &Inserted);
ASSERT(Inserted); ASSERT(Inserted);
if (0 != DescendantFileNodeIndex)
FspFileNodeReleaseForeign(DescendantFileNode);
} }
FspFsvolDeviceUnlockContextTable(FsvolDeviceObject); FspFsvolDeviceUnlockContextTable(FsvolDeviceObject);