sys: FSP_FILE_NODE: correctly handle FileInfo cache in the presence of streams

This commit is contained in:
Bill Zissimopoulos 2016-10-06 12:13:16 -07:00
parent e4cabc50c5
commit eb2000a194
2 changed files with 55 additions and 30 deletions

View File

@ -417,6 +417,12 @@ BOOLEAN FspExpirationTimeValid(UINT64 ExpirationTime)
return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (KeQueryInterruptTime() < ExpirationTime); return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (KeQueryInterruptTime() < ExpirationTime);
} }
static inline static inline
BOOLEAN FspExpirationTimeValidEx(UINT64 ExpirationTime, UINT64 CurrentTime)
{
/* if ExpirationTime is 0 or -1 then ExpirationTime else CurrentTime < ExpirationTime */
return 1 >= ExpirationTime + 1 ? (0 != ExpirationTime) : (CurrentTime < ExpirationTime);
}
static inline
BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime) BOOLEAN FspExpirationTimeValid2(UINT64 ExpirationTime, UINT64 CurrentTime)
{ {
return CurrentTime < ExpirationTime; return CurrentTime < ExpirationTime;
@ -919,14 +925,14 @@ typedef struct FSP_FILE_NODE
UNICODE_STRING FileName; UNICODE_STRING FileName;
PWSTR ExternalFileName; PWSTR ExternalFileName;
/* locked under Header.Resource */ /* locked under Header.Resource */
UINT64 InfoExpirationTime; UINT64 FileInfoExpirationTime, BasicInfoExpirationTime;
UINT32 FileAttributes; UINT32 FileAttributes;
UINT32 ReparseTag; UINT32 ReparseTag;
UINT64 CreationTime; UINT64 CreationTime;
UINT64 LastAccessTime; UINT64 LastAccessTime;
UINT64 LastWriteTime; UINT64 LastWriteTime;
UINT64 ChangeTime; UINT64 ChangeTime;
ULONG InfoChangeNumber; ULONG FileInfoChangeNumber;
UINT64 Security; UINT64 Security;
ULONG SecurityChangeNumber; ULONG SecurityChangeNumber;
ULONG DirInfoChangeNumber; ULONG DirInfoChangeNumber;
@ -1013,7 +1019,11 @@ BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileOb
static inline static inline
ULONG FspFileNodeFileInfoChangeNumber(FSP_FILE_NODE *FileNode) ULONG FspFileNodeFileInfoChangeNumber(FSP_FILE_NODE *FileNode)
{ {
return FileNode->InfoChangeNumber; if (0 != FileNode->MainFileNode)
return (FileNode->MainFileNode->FileInfoChangeNumber & 0xfffff) |
((FileNode->FileInfoChangeNumber & 0xfff) << 20);
else
return FileNode->FileInfoChangeNumber & 0xfffff;
} }
BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize); BOOLEAN FspFileNodeReferenceSecurity(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);
VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size); VOID FspFileNodeSetSecurity(FSP_FILE_NODE *FileNode, PCVOID Buffer, ULONG Size);
@ -1024,7 +1034,6 @@ ULONG FspFileNodeSecurityChangeNumber(FSP_FILE_NODE *FileNode)
{ {
if (0 != FileNode->MainFileNode) if (0 != FileNode->MainFileNode)
FileNode = FileNode->MainFileNode; FileNode = FileNode->MainFileNode;
return FileNode->SecurityChangeNumber; return FileNode->SecurityChangeNumber;
} }
BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize); BOOLEAN FspFileNodeReferenceDirInfo(FSP_FILE_NODE *FileNode, PCVOID *PBuffer, PULONG PSize);

View File

@ -855,7 +855,14 @@ VOID FspFileNodeGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *FileIn
FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart; FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart;
FileInfo->FileSize = FileNode->Header.FileSize.QuadPart; FileInfo->FileSize = FileNode->Header.FileSize.QuadPart;
FileInfo->FileAttributes = FileNode->FileAttributes; UINT32 FileAttributesMask = ~(UINT32)0;
if (0 != FileNode->MainFileNode)
{
FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY;
FileNode = FileNode->MainFileNode;
}
FileInfo->FileAttributes = FileNode->FileAttributes & FileAttributesMask;
FileInfo->ReparseTag = FileNode->ReparseTag; FileInfo->ReparseTag = FileNode->ReparseTag;
FileInfo->CreationTime = FileNode->CreationTime; FileInfo->CreationTime = FileNode->CreationTime;
FileInfo->LastAccessTime = FileNode->LastAccessTime; FileInfo->LastAccessTime = FileNode->LastAccessTime;
@ -867,25 +874,20 @@ BOOLEAN FspFileNodeTryGetFileInfo(FSP_FILE_NODE *FileNode, FSP_FSCTL_FILE_INFO *
{ {
PAGED_CODE(); PAGED_CODE();
BOOLEAN Result; UINT64 CurrentTime = KeQueryInterruptTime();
if (FspExpirationTimeValid(FileNode->InfoExpirationTime)) if (0 != FileNode->MainFileNode)
{ {
FileInfo->AllocationSize = FileNode->Header.AllocationSize.QuadPart; /* if this is a stream the main file basic info must have not expired as well! */
FileInfo->FileSize = FileNode->Header.FileSize.QuadPart; if (!FspExpirationTimeValidEx(FileNode->MainFileNode->BasicInfoExpirationTime, CurrentTime))
return FALSE;
FileInfo->FileAttributes = FileNode->FileAttributes;
FileInfo->ReparseTag = FileNode->ReparseTag;
FileInfo->CreationTime = FileNode->CreationTime;
FileInfo->LastAccessTime = FileNode->LastAccessTime;
FileInfo->LastWriteTime = FileNode->LastWriteTime;
FileInfo->ChangeTime = FileNode->ChangeTime;
Result = TRUE;
} }
else
Result = FALSE;
return Result; if (!FspExpirationTimeValidEx(FileNode->FileInfoExpirationTime, CurrentTime))
return FALSE;
FspFileNodeGetFileInfo(FileNode, FileInfo);
return TRUE;
} }
VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject, VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
@ -906,15 +908,29 @@ VOID FspFileNodeSetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileObject,
FileNode->Header.AllocationSize.QuadPart = AllocationSize; FileNode->Header.AllocationSize.QuadPart = AllocationSize;
FileNode->Header.FileSize.QuadPart = FileInfo->FileSize; FileNode->Header.FileSize.QuadPart = FileInfo->FileSize;
FileNode->FileAttributes = FileInfo->FileAttributes; FileNode->FileInfoExpirationTime = FileNode->BasicInfoExpirationTime =
FileNode->ReparseTag = FileInfo->ReparseTag; FspExpirationTimeFromMillis(FsvolDeviceExtension->VolumeParams.FileInfoTimeout);
FileNode->CreationTime = FileInfo->CreationTime; FileNode->FileInfoChangeNumber++;
FileNode->LastAccessTime = FileInfo->LastAccessTime;
FileNode->LastWriteTime = FileInfo->LastWriteTime; FSP_FILE_NODE *MainFileNode = FileNode;
FileNode->ChangeTime = FileInfo->ChangeTime; UINT32 FileAttributesMask = ~(UINT32)0;
FileNode->InfoExpirationTime = FspExpirationTimeFromMillis( if (0 != FileNode->MainFileNode)
FsvolDeviceExtension->VolumeParams.FileInfoTimeout); {
FileNode->InfoChangeNumber++; FileAttributesMask = ~(UINT32)FILE_ATTRIBUTE_DIRECTORY;
MainFileNode = FileNode->MainFileNode;
MainFileNode->BasicInfoExpirationTime = FileNode->BasicInfoExpirationTime;
MainFileNode->FileInfoChangeNumber++;
}
MainFileNode->FileAttributes =
(MainFileNode->FileAttributes & ~FileAttributesMask) |
(FileInfo->FileAttributes & FileAttributesMask);
MainFileNode->ReparseTag = FileInfo->ReparseTag;
MainFileNode->CreationTime = FileInfo->CreationTime;
MainFileNode->LastAccessTime = FileInfo->LastAccessTime;
MainFileNode->LastWriteTime = FileInfo->LastWriteTime;
MainFileNode->ChangeTime = FileInfo->ChangeTime;
if (0 != CcFileObject) if (0 != CcFileObject)
{ {
@ -934,7 +950,7 @@ BOOLEAN FspFileNodeTrySetFileInfo(FSP_FILE_NODE *FileNode, PFILE_OBJECT CcFileOb
{ {
PAGED_CODE(); PAGED_CODE();
if (FileNode->InfoChangeNumber != InfoChangeNumber) if (FspFileNodeFileInfoChangeNumber(FileNode) != InfoChangeNumber)
return FALSE; return FALSE;
FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo); FspFileNodeSetFileInfo(FileNode, CcFileObject, FileInfo);