minifilter not able to block paging IO for very small files

Hello experts,

I am working on a an FS minifilter registered for IRP_MJ_WRITE with SKIP_CACHED_IO. I am returning status_access_denied in preoperation callback. This works fine but for very small files, like < 100 bytes, the block operation doesnt prevent the update to the disk. After rebooting the server the contents of the file are seen. I saw some earlier threads and it appears that for very small files the content is stored in the MFT itself. When I use ProcessMonitor, I see a write success for the application and access denied for all subsequent paging IOs. Is there any other way to block the small write ?

Thanks

Gopal

I’d bet that you cannot. This also feels like a wings on a pig moment. By the time you are stopping paging IO a lot of damage has been caused and stopping the IO isn’t going to fix that.

What are you trying to achieve?

I want to allow file creation, but want to block all updates to disk…………In other words the application should have write-protection for data on the FS…but it should be able to create files…The files should be seen since I don’t want to block file creation………since I plan to do later processing on the created files by serving the reads from a remote location.

When I block paging IO in the minifilter, the minifilter gets the callbacks, I return failure, and I get the contents of the file as zero………BUT this mechanism doesn’t work for small files. or the first few bytes of the file. For such small files in-spite of continuous access denied for IRP_MJ_WRITE for the paging IO by System thread when monitored using filespy, yet it gets persisted in the MFT and shows up after reboot.

e.g. the file has 3 characters AAA, it shows these characters in the blocked IO buffers in filespy. Then how come they got persisted in the disk ?

Hope this explanation is useful.

Thank you very much,

Small files data can occupy a free space in file metadata block (like a master file table/inode table). In this case to avoid data aliasing ( with data present in both file metadata cache and file data cache ) the data is cached in file metadata cache only and flushed with PAGING_IO for file metadata (like $MFT file).

Actually, you fall in a common trap with believe that data passed in cached IO never reach an underlying drive except by PAGING_IO (in your case you also assume that this should be PAGING_IO for a file you want to prevent being modified). This is not true. A file system driver has a lot of liberty in cached IO processing. There is no rule that prevents a file system driver from a write-through cache implementation, i.e. passing data to a disc for cached IO, or skipping cache for cached IO (though unlikely because of data alignment issues).

+1 to all that @Slava_Imameyev said…

I want to allow file creation, but want to block all updates to disk…………In other words the application should have write-protection for data on the FS

Starting at the top you can

  • Deny access to applications who ask for any sort of WRITE access. Whilst this is the correct answer nit rarely works because of badly written apps. If that was all it took you’d use an ACL - that’s what they are there for.
  • Deny at the top. Deny section creation, MJ_WRITE, MJ_SET_INFORMATION and a whole bunch of FSCTLs

I’m guessing you did all this and it still didn’t work?

Great info Slava . Thanks Rod. My driver will work in envs where apps will be well behaved i.e. server envs. In summary it appears cached io not necessarily comes back as paged io to the filter. In this case though it is coming as paged io which is blocked and I can see all this with the data being blocked in filespy but somehow the data got stored in the MFT via another path probably due to reasons given by Slava. I think the filter design needs to intercept all app IOs not just paged IOs. Then it could be either the app doing a cached IO or the app doing a paged IO if it’s mmaped. Would filter be sure of intercepting all app IOs atleast? And additionally most but not all the cache flushes ?

In my experience, yes. If you block all writes, including fast io, you prevent data from being written to the file. There are many other ways in which a file can be modified, but if you are only worried about data being written to it, that should do the trick.

As examples of other ways to modify the file, they could open it with an allocation size to create a file of a given size, or use IRP_MJ_SET_INFORMATION to change the end of file, or rename a file into the place of the one you are guarding, also using IRP_MJ_SET_INFORMATION, or create a hardlink to the file you are protecting and get around your monitoring, etc.