Is FlushFileBuffers required to sync file data across many processes? - windows

I have a file which is read/write by many processes, they use a mutex to serialize the read/writes.
Is it required that I call FlushFileBuffers after WriteFile in ProcessA so that ProcessB would see these changes? Or would ProcessB be guaranteed to see the changes that ProcessA made, assuming the OS disk cache for this file is shared between all processes? After calling WriteFile I do not call CloseHandle on the file, I leave it open in all processes but they have the FILE_SHARE_READ and FILE_SHARE_WRITE flags passed to CreateFile.
This is required to work across Windows XP to Windows 8.1 - I've found that calling FlushFileBuffers presents an unacceptable performance bottleneck.

Processes which have a memory-mapped view of the file have direct access to the page in the disk cache; accesses are coherent with all other processes on the same machine, and your mutex is sufficient for synchronization.
Processes which use file access APIs need to call FlushFileBuffers to ensure coherency.
If you can't get away from shared files for IPC (for example, you can't change one of the participants), you can at least migrate the ones you do control to memory-mapped file views, for a big performance benefit.

Related

Can we safely access user-mode buffer passed as argument in syscalls, or do we need to use copy_from_user? (Linux)

Let's assume I'm hooking a syscall such as openat in Linux using an LKM. Now coming from a Windows driver development world, i have two questions:
Considering that the file path is passed as an argument in openat, Can we safely directly access that buffer (read or write), which is a user-mode address, without using copy_from_user? Because in Windows, certain callbacks are guaranteed to be called at the context of the calling process, thus we can safely assume that the buffer address is correct and not for another context, and even if they are not in the same context, we can attach to the calling process.
In Windows, there is a concept of paged out memory and IRQL, which means that on callbacks that have IRQL of DISPATCH or above, we cannot access memory that is paged out. Is there a similar concept in Linux? For example what happens if the user-mode address is paged out and i try to access it? Can i catch the exception? In Windows we can catch the exception for accessing invalid user-mode addresses, but invalid kernel-mode address access cannot be caught and it causes a BSOD.
I'm asking this because i need to hook opennat to monitor some file opens, but the problem is that if i try to allocate a kernel buffer and then use copy_from_user to get the file path, this will take a lot of time, but if i can somehow safely access the user-mode buffer directly without any copy and read or write to it, this will save up a lot of time. In Windows, even if the context is invalid, we can still attach to that process, lock the user-mode buffer with the help of MDL, and read/write to it, but I'm not sure if this is possible in Linux or not.

Determine which process created shared memory in Windows

The system I'm working on has many processes running. In the context of shared memory, some are servers and some are clients.
They create/access the shared memory through CreateFileMapping and MapViewOfFile.
I recently changed a structure on one of the clients, which led the client to attempt to map a region of shared memory which is bigger than what was created by the server process. The result is Access Denied.
My problem is, I have no idea which darn process created the memory in the first place. Is there a way of accessing such meta-information about shared memory in order to determine which server program needs to be recompiled?
To confirm, it is MapViewOfFile which is failing, with an error code of 5: Access denied.
Two types of shared memory exist: dynamic (using CreateFileMapping...your scenario) and static (memory mapping declared in PE Section(s) characteristics). One could test the existence of PE sections with shared memory characteristics on file and process level.
On the other side, the reason why MapViewOfFile failed might be other than the different sizes of mapped memory (e.g. credentials, offset of memory, ....)

Different ways to ask Windows to write data to disk

Usually, when an application writes to one of it's files on disk, the file modified timestamp changes.
Sometimes, and in my case it is an application written in ProvideX (a Business Basic derivative i believe) doing the writing, the modified timestamp does not change after a write. A program like MyTrigger will not pick up on the write operation either, but Sysinternals ProcessMonitor does log the disk activity.
It seems obvious that there are different ways to ask windows to perform write operations, and the request could then be hooked or logged in various different ways as well.
I need to be able to hook the write operations coming from the ProvideX application. Any pointers on the different ways windows writes to disk, and the type of hooks available for them would be greatly appreciated.
Thanks
User-mode process can write to the file either using WriteFile API function or using MMF, memory-mapped file API (CreateFileMapping/MapViewOfFile/Write to memory block). Maybe your application goes MMF way. MMF writes to files very differently from WriteFile API, but they both lead to the same end point - IRP sent to file system driver. File system filter driver (such as the one used by Sysinternals stuff) can track write requests on that IRP level. It is technically possible to distinguish between write operations initiated by MMF and WriteFile as different IRPs are sent (cached and non-cached writing is involved). It seems that directory change monitoring function in windows tracks only one IRP type, and this causes MyTrigger to miss the change.

Storing a value in Memory Independent of Process

I need a way to store a value somewhere for temporarily by say Process A. Process A can exit the after storing the value in memory. After sometime Process B comes accesses the same location of memory and read the value. I need to store in memory, because I dont want the data to persistent across reboots. But as long as the system is up, it Independent of the Process the data must be accessible. I tried MailSlots and Temporary files in windows, both seem to have problem where the process reference count drops to zero , the entities dont persist in memory. What is a suitable mechanism for this in Windows preferably using Win32 API?
Ganesh
Write a service that is started at boot time, and let it create some shared memory.
This shared memory can then be filled by process A, and process B can read it afterwards.
If your system is rebooted, the shared memory is gone and you have a fresh, new piece of shared memory.
Make sure that your service correctly 'initializes' the shared memory.
Is there a reason why the data must be resident in memory when ProcessA quits as opposed to being stored somewhere on disk? I ask as you mention temporary files which should work unless ProcessA fails in an unexpected way.
Depending on your needs a nice way to provide shared/fast/atomic data is via the ESENT API.
Try the following. I can't say I know this works, but it seems reasonable.
Create a shared memory file in the global namespace using OpenFileMapping. Then call Duplicatehandle and for the target process handle use some process that will live longer than process A. You may be able to add the handle to winlogon.exe This should stop the shared memory from being destroyed when process A terminates. Then in process B you can look up the shared memory file.
Well, I managed to a create a MailSlot on a Process which doesnt exit, the other two Processes can read and write to the MailSlot server as clients... Even if the clients exit, the Mailslot will still have the data... the MailSlot server enables me to store data in volatile memory has long as the MailSlot server process is up.. or the OS is up.. and vanishes on OS reboot... Thanks for all the ideas and help.... :)

Flush disk write cache

When the policy for a disk in Windows XP and Vista is set to enable write caching on the hard disk, is there a way to flush a file that has just been written, and ensure that it has been committed to disk?
I want to do this programmatically in C++.
Closing the file does perform a flush at the application level, but not at the operating system level. If the power is removed from the PC after closing the file, but before the operating system has flushed the disk write cache, the file is lost, even though it was closed.
.NET FileStream.Flush() will NOT flush the Windows cache for that file content; Flush() only flushes the .NET internal file buffer. In .NET 4.0, Microsoft fixed the problem by adding an optional parameter to Flush() which if set true causes FlushFileSystemBuffers to be called. In .NET 3.5 and below your only choice is to call FlushFileBuffers via pinvoke. See MSDN'sFileStream.Flush community comment for how to do this.
You should not fix this at the time you close the file. Windows will cache, unless you open the file passing FILE_FLAG_WRITE_THROUGH to CreateFile().
You may also want to pass FILE_FLAG_NO_BUFFERING; this tells Windows not to keep a copy of the bytes in cache.
This is more efficient than FlushFileBuffers(), according to the CreateFile documentation on MSDN.
See also file buffering and file caching on MSDN.
You haven't specified the development environment, so:
.Net
IO streams have a .Flush method that does what you want.
Win32 API
There is the FlushFileBuffers call, which takes a file handle as argument.
EDIT (based on a comment from the OA): FlushFileBuffers does not need administrative privileges; it does only if the handle passed to it is the handle for a volume, not for a single file.
You should also note, that your data might not get flushed to the actual disk, even when invoking a flush method of your frameworks API.
Calling the flush method will only tell the kernel to flush its pages to disk. However, if you have the disk write-cache turned on, it is allowed to delay the actual writing process indefinitely.
In order to ensure that your data gets written to the physical layer you have to turn of the write cache in your operating system. This most often comes with a performance penalty up to one or two orders of magnitude when dealing with a lot of small io-operations.
Battery based support (UPS) or disks that accept commands to flush the disk write-cache are another option to deal with this problem.
From the microsoft documents you would use _flushall and link in COMMODE.OBJ to ensure that all buffers were committed to disk.
See here: https://jeffpar.github.io/kbarchive/kb/066/Q66052/
When you initially open your file using fopen, include the "c" mode option as the LAST OPTION:
fopen( path, "wc") // w - write mode, c - allow immediate commit to disk
Then when you want to force a flush to disk, call
_flushall()
We made this call before calling
fclose()
We experienced the exact issue you described and this approach fixed it.
Note that this approach does NOT required Administrative rights, which FlushFileBuffers does require, as others have mentioned.
From that above site:
"Microsoft C/C++ version 7.0 introduces the "c" mode option for the fopen()
function. When an application opens a file and specifies the "c" mode, the
run-time library writes the contents of the file buffer to disk when the
application calls the fflush() or _flushall() function. "
You can open/create the file with the FileOptions.WriteThrough flag, which will cause the file to write directly into the disk, bypassing any caches.
E.g.
var file = File.Open(
"1.txt",
new FileStreamOptions
{
Options = FileOptions.WriteThrough
});
// - OR -
var file = new FileStream(
"1.txt",
FileMode.Create,
FileAccess.Write,
FileShare.None,
4096,
FileOptions.WriteThrough)

Resources