sys: QueryDirectory stability:

- FspMetaCacheAddItem now handles exceptions during copy from fs buffer
- FspFsvolQueryDirectoryLengthMax is correct max length for QueryDirectory
This commit is contained in:
Bill Zissimopoulos 2017-10-25 10:44:33 -07:00
parent fa388e57ad
commit 3a8ad9c8d7
3 changed files with 29 additions and 8 deletions

View File

@ -74,6 +74,12 @@ enum
RequestProcess = 3, RequestProcess = 3,
}; };
enum
{
FspFsvolQueryDirectoryLengthMax =
FspFsvolDeviceDirInfoCacheItemSizeMax - FspMetaCacheItemHeaderSize,
};
static NTSTATUS FspFsvolQueryDirectoryCopy( static NTSTATUS FspFsvolQueryDirectoryCopy(
PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive, PUNICODE_STRING DirectoryPattern, BOOLEAN CaseInsensitive,
PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut, PUNICODE_STRING DirectoryMarker, PUNICODE_STRING DirectoryMarkerOut,
@ -544,7 +550,7 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
QueryDirectoryLengthMin = sizeof(FSP_FSCTL_DIR_INFO) + QueryDirectoryLengthMin = sizeof(FSP_FSCTL_DIR_INFO) +
FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR); FsvolDeviceExtension->VolumeParams.MaxComponentLength * sizeof(WCHAR);
QueryDirectoryLengthMin = FSP_FSCTL_ALIGN_UP(QueryDirectoryLengthMin, 8); QueryDirectoryLengthMin = FSP_FSCTL_ALIGN_UP(QueryDirectoryLengthMin, 8);
ASSERT(QueryDirectoryLengthMin < FspFsvolDeviceDirInfoCacheItemSizeMax); ASSERT(QueryDirectoryLengthMin < FspFsvolQueryDirectoryLengthMax);
if (0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout && if (0 != FsvolDeviceExtension->VolumeParams.FileInfoTimeout &&
0 == FileDesc->DirectoryMarker.Buffer) 0 == FileDesc->DirectoryMarker.Buffer)
{ {
@ -557,11 +563,11 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
QueryDirectoryLength = FSP_FSCTL_ALIGN_UP(QueryDirectoryLength, 8); QueryDirectoryLength = FSP_FSCTL_ALIGN_UP(QueryDirectoryLength, 8);
if (QueryDirectoryLength < QueryDirectoryLengthMin) if (QueryDirectoryLength < QueryDirectoryLengthMin)
QueryDirectoryLength = QueryDirectoryLengthMin; QueryDirectoryLength = QueryDirectoryLengthMin;
else if (QueryDirectoryLength > FspFsvolDeviceDirInfoCacheItemSizeMax) else if (QueryDirectoryLength > FspFsvolQueryDirectoryLengthMax)
QueryDirectoryLength = FspFsvolDeviceDirInfoCacheItemSizeMax; QueryDirectoryLength = FspFsvolQueryDirectoryLengthMax;
} }
else else
QueryDirectoryLength = FspFsvolDeviceDirInfoCacheItemSizeMax; QueryDirectoryLength = FspFsvolQueryDirectoryLengthMax;
} }
else else
{ {
@ -575,11 +581,11 @@ static NTSTATUS FspFsvolQueryDirectoryRetry(
QueryDirectoryLength = FSP_FSCTL_ALIGN_UP(QueryDirectoryLength, 8); QueryDirectoryLength = FSP_FSCTL_ALIGN_UP(QueryDirectoryLength, 8);
if (QueryDirectoryLength < QueryDirectoryLengthMin) if (QueryDirectoryLength < QueryDirectoryLengthMin)
QueryDirectoryLength = QueryDirectoryLengthMin; QueryDirectoryLength = QueryDirectoryLengthMin;
else if (QueryDirectoryLength > FspFsvolDeviceDirInfoCacheItemSizeMax) else if (QueryDirectoryLength > FspFsvolQueryDirectoryLengthMax)
QueryDirectoryLength = FspFsvolDeviceDirInfoCacheItemSizeMax; QueryDirectoryLength = FspFsvolQueryDirectoryLengthMax;
} }
else else
QueryDirectoryLength = FspFsvolDeviceDirInfoCacheItemSizeMax; QueryDirectoryLength = FspFsvolQueryDirectoryLengthMax;
} }
Request->Kind = FspFsctlTransactQueryDirectoryKind; Request->Kind = FspFsctlTransactQueryDirectoryKind;

View File

@ -837,6 +837,10 @@ PIRP FspIoqNextCompleteIrp(FSP_IOQ *Ioq, PIRP BoundaryIrp);
ULONG FspIoqRetriedIrpCount(FSP_IOQ *Ioq); ULONG FspIoqRetriedIrpCount(FSP_IOQ *Ioq);
/* meta cache */ /* meta cache */
enum
{
FspMetaCacheItemHeaderSize = MEMORY_ALLOCATION_ALIGNMENT,
};
typedef struct typedef struct
{ {
KSPIN_LOCK SpinLock; KSPIN_LOCK SpinLock;

View File

@ -33,6 +33,8 @@ typedef struct
ULONG Size; ULONG Size;
__declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 Buffer[]; __declspec(align(MEMORY_ALLOCATION_ALIGNMENT)) UINT8 Buffer[];
} FSP_META_CACHE_ITEM_BUFFER; } FSP_META_CACHE_ITEM_BUFFER;
FSP_FSCTL_STATIC_ASSERT(FIELD_OFFSET(FSP_META_CACHE_ITEM_BUFFER, Buffer) == FspMetaCacheItemHeaderSize,
"FspMetaCacheItemHeaderSize must match offset of FSP_META_CACHE_ITEM_BUFFER::Buffer");
static inline VOID FspMetaCacheDereferenceItem(FSP_META_CACHE_ITEM *Item) static inline VOID FspMetaCacheDereferenceItem(FSP_META_CACHE_ITEM *Item)
{ {
@ -218,7 +220,16 @@ UINT64 FspMetaCacheAddItem(FSP_META_CACHE *MetaCache, PCVOID Buffer, ULONG Size)
Item->RefCount = 1; Item->RefCount = 1;
ItemBuffer->Item = Item; ItemBuffer->Item = Item;
ItemBuffer->Size = Size; ItemBuffer->Size = Size;
try
{
RtlCopyMemory(ItemBuffer->Buffer, Buffer, Size); RtlCopyMemory(ItemBuffer->Buffer, Buffer, Size);
}
except (EXCEPTION_EXECUTE_HANDLER)
{
FspFree(ItemBuffer);
FspFree(Item);
return 0;
}
KeAcquireSpinLock(&MetaCache->SpinLock, &Irql); KeAcquireSpinLock(&MetaCache->SpinLock, &Irql);
if (MetaCache->ItemCount >= MetaCache->MetaCapacity) if (MetaCache->ItemCount >= MetaCache->MetaCapacity)
FspMetaCacheRemoveExpiredItemAtDpcLevel(MetaCache, (UINT64)-1LL); FspMetaCacheRemoveExpiredItemAtDpcLevel(MetaCache, (UINT64)-1LL);