How to get driver information from IRP

Hi.
I wrote a minifilter to filter some operations on a folder. I want pass the operation from my drivers and stop the operation from untrusted program.
However, I can’t get some information to determine if the IRP came from my drivers. I can get the process information. But when the operation came from driver, the process’s information can help me to determine where the IRP really came from.
Any guidance would be helpful. Thanks.

If it’s a create use an ECP, otherwise there is no generic way. I’m assuming that internal ioctls don’t help? They are the canonical mechanism for driver to driver communication.

@rod_widdowson said:
If it’s a create use an ECP, otherwise there is no generic way. I’m assuming that internal ioctls don’t help? They are the canonical mechanism for driver to driver operation.

I think it’s not about driver to driver operation. The situation is that my driver will do something to the folder which is protect by the minifilter.what I want the minifilter do is allowed the operation from my drivers.

I think we may have a terminology problem. When I say driver I mean a kernel component (as in “Minifilter Driver” or “Device Driver”).

Do you mean some user mode application?

If so doesn’t CallBackData->Thread (and thence PsGetThreadProcess) do what you want? You’ll need a secure way of establishing the user processes information but that’s a given anyway.

@rod_widdowson said:
I think we may have a terminology problem. When I say driver I mean a kernel component (as in “Minifilter Driver” or “Device Driver”).

Do you mean some user mode application?

If so doesn’t CallBackData->Thread (and thence PsGetThreadProcess) do what you want? You’ll need a secure way of establishing the user processes information but that’s a given anyway.

I also think driver means a kernel component.
Sorry. Maybe my explanation is not accurate enough or I didn’t understand you well. Let me describe in detail.

I am writing a minifilter which will filter the operation on a folder I specified. I don’t want people or untrusted program to read/write/delete the folder or something in the folder.
But some of my drivers need to write the text in the folder. And I need the minifilter to pass this type of operations.
What I can’t figure out is how I know the operation is from my drivers. Is there any information in the IRP that can help me judge?

You plan to block the operation at CreateFile time, yes?

Perhaps you can use the RequestorMode to determine if the Create is coming from user mode or kernel mode?

Peter

@“Peter_Viscarola_(OSR)” said:
You plan to block the operation at CreateFile time, yes?

Perhaps you can use the RequestorMode to determine if the Create is coming from user mode or kernel mode?

Peter

Actually, I plan to block all the operation including Create/Read/Write/Delete as long as the operation came from untrusted objects.
But your suggestion get me a good idea. I will try it. Thank you Peter.

Based on the solution, there are another issue here. Someone who write a driver can pass my minifilter, even though I didn’t agree with his permissions.

In addition to what Peter says, if you own the create you use an ECP to say ‘it’s me’. After that because you know the file object you can set a flag on the StreamHandleContext.

It’s when you are borrowing the file object that things get tricky, but if all your operations are on file objects your other drivers created it’s a lot easier…

Also have you thought about doing it with ACLs and making your driver [s] impersonate your service when they do the create. At that stage all the work is done for you.

Are you using ZwXXX api instead of FltXXX ones or a NULL instance?

I ask this because usually you make operations by calling the filters below you and your driver does not see these ops.

@Mauro_Leggieri said:
Are you using ZwXXX api instead of FltXXX ones or a NULL instance?

Yes, I use ZwXX in my drivers and the filter can catch the operation.

@rod_widdowson:
Thank you for your response.
I am a newcomer to writing drivers that I can’t understand all your words.
here are some of my questions and explanation.

if you own the create you use an ECP to say ‘it’s me’.
Also have you thought about doing it with ACLs…
What’s ECP and ACL? Is ACL means ‘anterior cruciate ligament’?

If you own the create you use an ECP to say ‘it’s me’. After that because you know the file object you can set a flag on the StreamHandleContext.
What do you mean in the sentence is whether to set a tag on drivers or on file?
If on drivers, can I get the tag in the minifilter?
If on file, it doesn’t help me to determine where the ops come from, right?

if all your operations are on file objects your other drivers created it’s a lot easier…
The file objects is not all created by my drivers, some of them are existed at the beginning.
My driver will created some file and also need to work with existing files.

Thank you again.

A acl is a Acesss Control List see also this link.

ECP is an Extra Create Parameter

If on drivers, can I get the tag in the minifilter?
If on file, it doesn’t help me to determine where the ops come from, right?
Neither its on the HANDLE (hence my comment

After that because you know the file object you can set a flag on the StreamHandleContext.

The file objects is not all created by my drivers, some of them are existed at the beginning.
This is the most challenging case, but I suggest you start with some more background research before we go down this rabbit hole

I am a newcomer to writing drivers

I cannot recommend strongly enough that you tell your management that you need training. Writing windows device drivers is very challenging. Write file system filters takes that to another level. Our worthy list hosts do an excellent course.

ACL means ‘anterior cruciate ligament’

Yes. Definitely.

http://letmegooglethat.com/?q=ACL+Windows

P

Thank you Peter. Thank you Rod. Thank you for your suggestion and sharing.

I will take Peter’s advice to use RequestorMode and pass all the ops from kernel mode.
I will also learn the methods you tell me. Hope I can master it in the future.

@Cecilia_wll said:

@Mauro_Leggieri said:
Are you using ZwXXX api instead of FltXXX ones or a NULL instance?

Yes, I use ZwXX in my drivers and the filter can catch the operation.

Then I recommend to switch to FltXXX unless you need to send requests to the top. In that case add the ECP’s to identify your own calls.

Based on the solution, there are another issue here. Someone who write a driver can pass my minifilter, even though I didn’t agree with his permissions.

Yes. In general, you cannot prevent this from happening. If an untrusted driver gets into the kernel, it may just simply skip all the filters and pass its requests directly to the file system (for example). Or it may go even lower.

Read/Write…

If you prevent untrusted entities from creating or opening content in your folder, they cannot do other types of operations (reads, writes, IOCTLs…) simply because they do not get a handle to the object protected by your filter. AFAIK with exception of the create, many file operations may be executed asynchronously and in different process context that you would expect. This is especially true when a file gets mapped into memory. Hence I would prefer enforcing your policies during the create operation.

@“Martin_Dráb” said:
In general, you cannot prevent this from happening. If an untrusted driver gets into the kernel, it may just simply skip all the filters and pass its requests directly to the file system (for example). Or it may go even lower.

Actually, the filter can catch the IRP from driver and prevent them. But what I want to do is prevent part of them. Hence my first idea is to catch the driver information in my filter and pass\prevent operations based on driver information.

Actually, the filter can catch the IRP from driver and prevent them.

If an IRP is sent directly to the file system driver (e.g. ntfs.sys), neither Filter Manager (and thus, any minifilter), nor any file system filter driver can catch it since such an IRP does not get through the device stack of the file system instance. The IRP is sent directly to the bottom device object.

More detailed explanation
Device objects form something like chains. IRPs travel from one end of a chain (the top) to another (the bottom) and information about their completion goes in the opposite direction. Because of such traveling patterns, these chains are called device stacks.

When an IRP is created on behalf of an application, it always travels from the top of the device stack to its bottom. However, a kernel driver can examine device stacks and pass its IRPs directly to certain device object, e.g. to the stack bottom. Hence, the IRP goes only through a part of the device stack; if sent to its bottom, it visits only the bottom device.

Device stacks representing instances of mounted file systems consists of the following device objects:

  • file system filter drivers (the top),
  • Filter Manager (and minifilters),
  • file system driver (the bottom).

So, if a driver sends an IRP directly to the bottom, Filter Manager never gets its hands on it.

I hope my explanation is accurrate enough.

But what I want to do is prevent part of them. Hence my first idea is to catch the driver information in my filter and pass\prevent operations based on driver information.

I recommend giving a chance to Peter’s suggestion. If an IRP comes from UserMode, treat it as untrusted, if from KernelMode, label it as trusted. You may also make this check for IRP_MJ_CREATE IRPs only I suppose since applications need to issue these IRPs in order to get a file handle (which is required to perform other types of file operations).

Such approach is quite straightforward to implement and may achieve exactly what you need.

@“Martin_Dráb”
:smile: :smiley:
Thank you Martin, I think I understand your explanation. Your explanation is very detailed.

And your suggestion for checking IRP_MJ_CREATE only is useful. I will try. Thank you again.