[NTOSKRNL]

A hack has gained enough XP and levels up! Congratulations to the MmCreateSection() in charge of forcing file cache initialization.
As show by kmtest:NtCreateSection tests and real world FSD (starting with MS FastFAT and Ext2Fsd), caching of a file can be initialized rather late (ie, on first effective read/write).
That means that our current hack is totally opless on newly created files with 0-size where the IRP_MJ_READ is most of the time opless too.
The hack, thanks to its level up, can now force a write (1-byte) in case read was unsuccessful and end of file.
In other words, this is the hack of a hack (and a hack v2).
It fixes a few failing kmtests.
Thomas, Peter, please retry the FSDs on which you are currently working on and report. Thanks :-)

CORE-11819
CORE-12475

svn path=/trunk/; revision=73384
This commit is contained in:
Pierre Schweitzer 2016-11-26 22:39:08 +00:00
parent 89c3520c86
commit 3ff70dc5d5

View File

@ -2909,9 +2909,6 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
PFILE_OBJECT FileObject;
PMM_SECTION_SEGMENT Segment;
ULONG FileAccess;
IO_STATUS_BLOCK Iosb;
LARGE_INTEGER Offset;
CHAR Buffer;
FILE_STANDARD_INFORMATION FileInfo;
ULONG Length;
@ -2967,7 +2964,6 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
sizeof(FILE_STANDARD_INFORMATION),
&FileInfo,
&Length);
Iosb.Information = Length;
if (!NT_SUCCESS(Status))
{
ObDereferenceObject(Section);
@ -3012,35 +3008,9 @@ MmCreateDataFileSection(PROS_SECTION_OBJECT *SectionObject,
if (FileObject->SectionObjectPointer == NULL ||
FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{
/*
* Read a bit so caching is initiated for the file object.
* This is only needed because MiReadPage currently cannot
* handle non-cached streams.
*/
Offset.QuadPart = 0;
Status = ZwReadFile(FileHandle,
NULL,
NULL,
NULL,
&Iosb,
&Buffer,
sizeof (Buffer),
&Offset,
0);
if (!NT_SUCCESS(Status) && (Status != STATUS_END_OF_FILE))
{
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
return(Status);
}
if (FileObject->SectionObjectPointer == NULL ||
FileObject->SectionObjectPointer->SharedCacheMap == NULL)
{
/* FIXME: handle this situation */
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
return STATUS_INVALID_FILE_FOR_SECTION;
}
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
return STATUS_INVALID_FILE_FOR_SECTION;
}
/*
@ -3836,10 +3806,19 @@ MmCreateImageSection(PROS_SECTION_OBJECT *SectionObject,
if(ImageSectionObject->Segments != NULL)
ExFreePool(ImageSectionObject->Segments);
/*
* If image file is empty, then return that the file is invalid for section
*/
Status = StatusExeFmt;
if (StatusExeFmt == STATUS_END_OF_FILE)
{
Status = STATUS_INVALID_FILE_FOR_SECTION;
}
ExFreePoolWithTag(ImageSectionObject, TAG_MM_SECTION_SEGMENT);
ObDereferenceObject(Section);
ObDereferenceObject(FileObject);
return(StatusExeFmt);
return(Status);
}
Section->ImageSection = ImageSectionObject;
@ -5101,6 +5080,33 @@ MmCreateSection (OUT PVOID * Section,
return Status;
}
// Caching is initialized...
// Hack of the hack: actually, it might not be initialized if FSD init on effective right and if file is null-size
// In such case, force cache by initiating a write IRP
if (Status == STATUS_END_OF_FILE && !(AllocationAttributes & SEC_IMAGE) && FileObject != NULL &&
(FileObject->SectionObjectPointer == NULL || FileObject->SectionObjectPointer->SharedCacheMap == NULL))
{
Status = ZwWriteFile(FileHandle,
NULL,
NULL,
NULL,
&Iosb,
&Buffer,
sizeof(Buffer),
&ByteOffset,
NULL);
if (NT_SUCCESS(Status))
{
LARGE_INTEGER Zero;
Zero.QuadPart = 0LL;
Status = IoSetInformation(FileObject,
FileEndOfFileInformation,
sizeof(LARGE_INTEGER),
&Zero);
ASSERT(NT_SUCCESS(Status));
}
}
}
#endif