Minifilter not intercepting IRP_MJ_WRITE, when a file is copied

Hi,

I am writing a minifilter for encryption and decryption.
When a file is copied to network volume, the minifiter intercepts IRP_MJ_CREATE and IRP_MJ_CLOSE. It is not intercepting any IRP_MJ_WRITE.
But the file is copied to the network folder.I have verified this on the remote computer.

I am seeing this behavior only in network volumes.
Volumes on the local disks work properly. The filter can intercept IRP_MJ_WRITE when a file is copied to local disk.

Please help me in understanding how a file is copied to a network volume.

Thanks,
S Ramakrishnan

one more additional info

Intercepting only the paging io by using the flag FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO.

Hi,

In Windows caching is managed by a file system. When a file system receives a “cached write” request it usually calls CcCopyWrite, so data goes in cache. Your driver intercepts cache flush requests as non cached IO(actually paging IO). But nothing prevents a file system from skipping a call to CcCopyWrite and writing directly to a backing store especially when a backing store doesn’t have alignment requirements ( as in network FS). There are some conditions to be meet for this scenario - e.g. there should not be user mapped views for a file.

This doesn’t exclude the possibility that there is a deficiency in your implementation and non cached( paging IO ) was sent but was not processed by your filter in case of network FS.

one more additional information.
If a notepad file is created inside the network volume, some data is typed
and saved then the filter driver gets IRP_MJ_WRITE.
But when a file is copied to the network volume, the filter driver does not
get IRP_MJ_WRITE.
Please let me know the way to intercept the write IRP and encrypt the file.

Thanks,
S Ramakrishnan

On Sat, Nov 19, 2016 at 10:20 PM, wrote:

> Hi,
>
> In Windows caching is managed by a file system. When a file system
> receives a “cached write” request it usually calls CcCopyWrite, so data
> goes in cache. Your driver intercepts cache flush requests as non cached
> IO(actually paging IO). But nothing prevents a file system from skipping a
> call to CcCopyWrite and writing directly to a backing store especially when
> a backing store doesn’t have alignment requirements ( as in network FS).
> There are some conditions to be meet for this scenario - e.g. there should
> not be user mapped views for a file.
>
> This doesn’t exclude the possibility that there is a deficiency in your
> implementation and non cached( paging IO ) was sent but was not processed
> by your filter in case of network FS.
>
>
>
>
> —
> NTFSD is sponsored by OSR
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

Notepad uses a memory mapped file, this is analogues to file being cached. When Memory Manager flushes dirty pages the filter receives paging IO.

The correct implementation requires an isolation filter like OSR Data Modification Kit.
In your case you can try to intercept a cached IO for network FS and process it as non cached(i.e. encrypt/decrypt) if ( NULL == FileObject->SectionObjectPointer || NULL == FileObject->SectionObjectPointer->DataSection ).

What I am copying is also a notepad file.

On Sun, Nov 20, 2016 at 11:46 AM, wrote:

>


>
> Notepad uses a memory mapped file, this is analogues to file being cached.
> When Memory Manager flushes dirty pages the filter receives paging IO.
>
>


>
> The correct implementation requires an isolation filter like OSR Data
> Modification Kit.
> In your case you can try to intercept a cached IO for network FS and
> process it as non cached(i.e. encrypt/decrypt) if ( NULL == FileObject->SectionObjectPointer
> || NULL == FileObject->SectionObjectPointer->DataSection ).
>
> —
> NTFSD is sponsored by OSR
>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:>

> The correct implementation requires an isolation filter like OSR Data
Modification Kit.

In your case you can try to intercept a cached IO for network FS and
process it as non cached(i.e. encrypt/decrypt) if ( NULL ==
FileObject->SectionObjectPointer
|| NULL == FileObject->SectionObjectPointer->DataSection ).

If you intercept all paging i/o and non-cached i/o you don’t need DMK.

Rama,
You can reset FLTFL_OPERATION_REGISTRATION_SKIP_CACHED_IO flag and skip all
cached i/o in PreCallback and PostCallback to try to see IRP_MJ_WRITE irp
you could miss.

You still need a DMK like solution as you don’t have control over underlying FSD and filters behavior. It is possible to fine tune a filter for a particular FS build in a particular environment but this solution is not universal and is easily broken by a third party filter or system update.

DMK is not about cached vs non cached filtering.

> You still need a DMK like solution as you don’t have control over
underlying FSD

How are you going to control underlying FSD by upper FSD which works
through underlying FSD?

is easily broken by a third party filter or system update.

For example?

Do you want to say if i filter all paging i/o and non-cached i/o to
encrypt/decrypt data there may be a case when some another filter can break
my encryption? And DMK solves this?

DMK initializes FileObject in IRP_MJ_CREATE and completes create request. The system and user applications work with a file object which is under full DMK control. DMK defines any policy for a file. The underlying FSD is used as a backing store for a file initialized by DMK and has(almost) no influence on DMK capabilities. There is no one-to-one correspondence for IO to a DMK initialized file object and a file object on underlying FSD. DMK might flush data to a backing store FSD whenever it decides it is appropriate to do so.

Exactly. You have wrong ideas about cached and non-cached processing implementation.

For example a file system developer decides to process some non-cached non-paging IO through the cache and your filter(which you are proud of) is stuffed. The same can be done by a filter by modifying IRP parameters from non-cached to cached ones.

> DMK initializes FileObject in IRP_MJ_CREATE and completes create request.
The system and user applications work with a file object which is under
full DMK control. DMK defines any policy for a file. The underlying FSD is
used

as a backing store for a file initialized by DMK and has(almost) no
influence on DMK capabilities. There is no one-to-one correspondence for IO
to a DMK initialized file object and a file object on underlying FSD. DMK
might flush data > to a backing store FSD whenever it decides it is
appropriate to do so.

You have wrong ideas about cached and non-cached processing
implementation.

I did something like this to encrypt/decrypt files and to represent a file
within system twice. Encrypted instance of the file and decrypted instance
of the file. You can do any i/o with both instances simultaneously. File
names was also encrypted. So if you have access key to a file you’ll see it
as decrypted. If you haven’t it you’ll see file as encrypted. To let
simultaneous access to both file instances i needed upper FSD which can
control both instances and maintain their coherency. So i developed a FSD
which can do it. Such implementation was needed for organizations who wants
to hide real file content from system administrators. I had to solve very
different problems while developing. For example, i needed to attach legacy
FSD filter directly to file system device object. And i did it. So i have
some ideas about cached and non-cached processing implementation.

Exactly

That’s not true. If you have filter which simple encrypts/decrypts data
there is no third party filter which could break your encryption. Except of
cases if filter developer decided to skip some filter in the stack. But
such filters would break everything and system will go crazy quickly.

For example a file system developer decides to process some non-cached
non-paging IO through the cache and your filter

What would happen to DMK if its backing store(i mean underlying FSD which
we try to control) decides to process non-cached I/O through the cache? I
can answer to you. The system will hang because of when underlying file
system do cached write, it usually make a call to CcCanIWrite before making
a call to CcCopyWrite. Therefore CcCanIWrite can defer IRP until there
would be enough number of non-modified pages. But DMK sent IRP_MJ_WRITE
because of memory manager flushes pages. So they never be flushed, because
underlying FSD(because of cache manager) waits for non-modified pages to be
flushed.

And one more question. You told that somebody needs DMK to be able to
control underlying file system. But how DMK can control a decidion of FSD
to make non-cached IRP cached one? And how DMK can control a decidion of
some filter which modifies IRP parameters? No way. You can’t protect
youself against such scenarious.

The same can be done by a filter by modifying IRP parameters from
non-cached to cached ones.

System will go crazy quickly with such filter.

> because underlying FSD(because of cache manager) waits for non-modified
pages to be flushed.

I beg your pardon,

modified pages to be flushed. :slight_smile:

Anatoly, as I sad you full of wrong ideas about FSD and DMK, not only OSR DMK but data modification implementation in general. I will use a word DMK for the class of stackable file system implementations.

DMK is completely decoupled from underlying FSD. The key word is DECOUPLED. DMK doesn’t care how underlying FSD is implemented, it just reads/writes stream of data by any conventional(ZwReadFile/ZwWriteFile) or non-conventional(paging IO) method.

In some cases a user mode service can be used to flush data asynchronously from DMK secondary storage to an underlying file system. DMK can use cache and any type of secondary storage to temporary hold data as long as this doesn’t cause deadlocks. For example - I used a pagefile to temporary store data flushed by paging IO before a user mode service initiates flushing to an underlying FS.

All the problems you outlined with Cc** functions is just a result of a bad design when you tightly coupled DMK file system to an underlying FSD. You just wiped out a lot of DMK advantages by downgrading it to a simple filter behavior.

If you believe that you can reliably implement data modification by modifying non-cached and paging IRP then good luck. It requires some experience to understand that this doesn’t work universally.

System doesn’t care how non-cached non-paged IO is processed. It is perfectly legitimate to convert non-cached IO to cached IO in a filter. Non-cached IO is not “sacred” like paging IO.

> DMK is completely decoupled from underlying FSD. The key word is
DECOUPLED.DMK doesn’t care how underlying FSD is implemented, it just
reads/writes stream of data by any conventional(ZwReadFile/ZwWriteFile) or

non-conventional(paging IO) method.

Answer the question. Does decoupling mean that DMK is not depended on
underlying FSD? And if it’s depended on(and it is) how can you control bad
implement of FSD?

All the problems you outlined with Cc** functions is just a result of a
bad design when you tightly coupled DMK file system to an underlying FSD.

I responded on your example about underlying FSD decides to process
non-cached i/o through the cache. That was your example. And i told you
what happens to DMK(which is DECOUPLED from underlying FSD) if underlying
FSD decides to process non-cached i/o through the cache. Was i wrong? If i
was then why?

If you believe that you can reliably implement data modification by
modifying non-cached and paging IRP then good luck. It requires some
experience to understand that this doesn’t work universally.

Did such a thousand times. And have things work well in many organizations.

System doesn’t care how non-cached non-paged IO is processed. It is
perfectly legitimate to convert non-cached IO to cached IO in a filter.
Non-cached IO is not “sacred” like paging IO.

But DMK may have sent this non-cached IRP to underlying FSD because of it
gets paging i/o IRP. And if underlying FSD convert non-cached IRP to cached
one there can be deadlock. And i told why.

or non-conventional(paging IO) method.

Are you talking about sending paging i/o to underlying FSD directly? If you
do then you get a lots of problems. For example, paging i/o resource
acquiring before sending this IRP. You can’t do it.

Anatoly, as I sad you full of wrong ideas about FSD and DMK, not only OSR
DMK but data modification implementation in general. I will use a word DMK
for the class of stackable file system implementations.

Did you pay your attention you don’t describe reasons why i am wrong but
just insist that i have no right ideas?

I feel like I am in a backseat of a KGB’s car.

Yes, in general it doesn’t depend. Try to think about DMK as a network FSD. Network FSD doesn’t depend on the server FSD implementation.

You don’t need to “control bad implement of FSD”. You just use another FSD as a backing store. There is no need to do this in DMK’s IRP_MJ_WRITE routine when processing paging IO. You are trying to map your bad experience to the whole class of stackable file systems.

BTW what you call “bad implement of FSD” is a way NTFS is implemented. NTFS processes non-cached IO through the cache for some file types.

You were completely correct. The problem is that your DMK implementation had a design flaw - it flushed data directly to underlying FS in response to paging write. I experienced the same issues with deadlocks when I implemented my first data modification 12 years ago without a temporary backing store.

Not only you, it is a common(but incorrect) practice. You don’t comprehend the idea that this implementation depends on underlying FSD and filters behavior and should be tailored to a particular environment. In some cases it can’t work if for example an underlying FSD processes cached and non-cached IO inconsistently relating to cache usage as it happens with network FS.

This is a design flaw I told you about. Your DMK implementation was not completely decoupled. Actually such implementation is unusable for a lot of tasks. For example if a user mode service must verify/modify data before it is allowed to go on an external drive. Your implementation will deadlock or run out of memory( and this is what happened 12 years ago with my first DMK).

Did you notice the word “non-conventional”?

Really? There was a number of explanations why your ideas were not completely correct( not wrong ). Maybe I should have made it more explicit.

> Yes, in general it doesn’t depend. Try to think about DMK as a network
FSD. Network FSD doesn’t depend on the server FSD implementation.

Reading and writing the file streams are not dependency?

You don’t need to “control bad implement of FSD”.

Once again i’ll tell you your example. You told that underlying FSD can
process non-cached i/o through the cache. This can lead to deadlock since
you use ZwWriteFile. How you personally would protect against it?

BTW what you call “bad implement of FSD” is a way NTFS is implemented.
NTFS processes non-cached IO through the cache for some file types.

What are these types?

The problem is that your DMK implementation had a design flaw - it
flushed data directly to underlying FS in response to paging write.

How it must flush them then? With which means?

I experienced the same issues with deadlocks when I implemented my first
data modification 12 years ago without a temporary backing store.

I don’t have deadlock. I use non-cached writes.

You don’t comprehend the idea that this implementation depends on
underlying FSD and filters behavior and should be tailored to a particular
environment.

Once again, those IRPs which DMK sends with ZwReadFile/ZwWriteFile don’t go
through the file system stack? And if they don’t then how they reach their
backing store?

In some cases it can’t work if for example an underlying FSD processes
cached and non-cached IO inconsistently relating to cache usage as it
happens with network FS.

For example?

Your DMK implementation was not completely decoupled

What is complete decoupling? Not using underlying FSD at all?

Your implementation will deadlock or run out of memory( and this is what
happened 12 years ago with my first DMK).

I stress tested my FSD. With very low memory conditions.

Did you notice the word “non-conventional”?

Then how? And what for DMK is still using ZwReadFile/ZwWriteFile?

Really? There was a number of explanations why your ideas were not
completely correct( not wrong ). Maybe I should have made it more explicit.

You told about only a fact. You almost didn’t explain things.

Only in a philosophical sense.

It will deadlock in you implementation as I told you there is a design flaw to issue IO to an underlying FSD in response to paging IO. I do not issue IO to an underlying FS in response to paging write.

This is an incorrect implementation. NTFS converts non-cached writes to cached ones for some file types ( encrypted and compressed for example ). As I said FSD should not honor non-cached IO, this is just an advise to FSD. BTW issuing a recursive IO to a file except a pagefile is a receipt for a deadlock.

There is IoCreateFileSpecifyDeviceObjectHint ( preferable solution ) or DMK can filter by file object and pass through backing store file objects IO( some issues with upper filters are possible ).

NTFS, network FSDs. You can remove non-cached processing from FastFAT and do it as cached IO.

Did you notice that I was talking about your design application to another task where it would deadlock or run out of memory?

Just call them from a worker thread of from a service.

Is is not possible to explain anything to a person who doesn’t want to listen and flips.

> Only in a philosophical sense.

Ok. What is a sense of dependency we’re talking about? From what DMK is
decoupled? Please explain.

I do not issue IO to an underlying FS in response to paging write.

But what you do then? Can i ask?

NTFS converts non-cached writes to cached ones for some file types (
encrypted and compressed for example ).

I tested also a lot with NTFS encrypted and compressed files.

As I said FSD should not honor non-cached IO, this is just an advise to
FSD.

As far as i know, it’s not advice to FSD. It’s direct indication what to do
and how to do.

There is IoCreateFileSpecifyDeviceObjectHint ( preferable solution )

Ok, but before file system device object there are also filters. Filter
manager for example. This is part of file system stack. Or not?

You can remove non-cached processing from FastFAT and do it as cached IO.

How?

Did you notice that I was talking about your design application to
another task where it would deadlock or run out of memory?

Yes. For me there is a service which do data modifications. And there is no
deadlocks.

Just call them from a worker thread of from a service.

What for?

Is is not possible to explain anything to a person who doesn’t want to
listen and flips.

I understood your example of converting IRPs from non-cached to cached
ones. Your example leads to modified data will appear in cache. That’s
wrong. I understood everything.

So i asked you questions now and in previous posts. I’m very intresting,
what you do when you get paging i/o in your DMK.

So you are unable to convert non-cached non-paging IO in FastFAT to a cached IO. I think this should put an end to our discussion.

Sapienti sat.