I've determined empirically that, on my system, a memory mapped file created to be a certain size is always completely zeroed by default. For example, using the call
HANDLE hMM =
CreateFileMapping (h,
NULL,
PAGE_READWRITE,
0,
0x01400000,//20MB
NULL);
.. and writing into a mapped view of that file always results in a 20MB file that is completely zeroed, except where I have written non-zero data.
I'm wondering if uninitialized parts of the file can be assumed to be zeros. Is this behavior guaranteed on Windows in general?
The CreateFileMapping documentation (Remarks section) explicitly states that
If the file is extended, the contents of the file between the old end of the file and the new end of the file are not guaranteed to be zero; the behavior is defined by the file system.
so, if your file on disk starts empty, it's not guaranteed to be zeroed (since you are expanding it); I don't think that file system drivers would take the risk of leaking potentially sensitive information that way, but who knows, maybe some file system driver recycles pages already used for your process (and this shouldn't be a security risk).
On the other hand, I don't know if filesystems that do not offer security at all (e.g. FAT) would be so concerned to give you the content of the clusters that they happened to allocate for the new part of the file.
If, instead, you are creating a memory section not backed by a file on disk but by the paging file it's guaranteed that the memory you get is all zeroed:
The initial contents of the pages in a file mapping object backed by the operating system paging file are 0 (zero).
This is guaranteed probably because when creating a memory-only paging file the memory manager has the complete control on what's going on, and it takes the pages from the blanked pages pool.
All newly allocated pages are zeroed before they are made accessible to user-mode, because otherwise sensitive information could be leaked from kernel-mode or other processes. This applies to things like NtAllocateVirtualMemory
/VirtualAlloc
and NtCreateSection
/CreateFileMapping
.
I imagine the same concept extends to files, because any decent file system wouldn't want to leak information in this way.
EDIT: However, take that last paragraph with a grain of salt - both the documentation for CreateFileMapping and SetEndOfFile claim that the extended portion of the file is not defined. I'll do some more investigation.
EDIT 2: OK, the Win32 MSDN documentation is definitely wrong. The documentation for ZwSetInformationFile states:
If you set FileInformationClass to
FileEndOfFileInformation, and the
EndOfFile member of
FILE_END_OF_FILE_INFORMATION specifies
an offset beyond the current
end-of-file mark, ZwSetInformationFile
extends the file and pads the
extension with zeros.
So there you go. The extended portion is guaranteed to be zero.
Yes, as pointed out by wj32. This is related to c2 requirements which NT has met since its birth. However depending on what you are trying to do, you should probably look into sparse files.