thread context in filter driver

In a filter driver, I’m trying to reliably determine the thread that originally caused/created an IRP. Why? Because I want to see if the thread (in a usermode program) that issues DeviceIoControl is the same thread that issued the CreateFile on the device. But mostly because I’m trying to understand thread context in drivers.

Many things I’ve read indicate that the thread, and I assume therefore the value in Irp->Tail.Overlay.Thread, would match the thread of the usermode program that issued the call, at least for the above two calls. But I’ve read (I don’t remember where) that in a non-top-level filter driver the thread could be an arbitrary thread in cases where a higher level doesn’t pass the IRP directly down (like queuing it).

The article at http://msdn.microsoft.com/en-us/library/ff540124(v=VS.85).aspx specifies “thread context requirements” for the dispatch routines. It makes be believe that the value in Irp->Tail.Overlay.Thread is in the usermode program (again, for the above two calls) regardless of where my driver is in the stack.

The documentation for IoGetRequestorProcess gives me similar worries (so I assume gets EPROCESS from the ETHREAD pointer somehow)

I’d like to believe the MSDN article. Can anyone add any insight to this?

Mike

The article, you refer confirms that both Create and DeviceControl (except paging I/O) will come in non-arbitrary context. If it doesn’t, it should be considered as a bug in filter above. As requestor (here UM application) is not in paging I/O path, when sending the IOCL request it must arrive in non-arbitrary context. That’s my understanding.

Bronislav Gabrhelik

>Many things I’ve read indicate that the thread, and I assume therefore the

value in Irp->Tail.Overlay.Thread, would match the thread of >the usermode
program that issued the call, at least for the above two calls

In the case where there are no filters above your filter, this is 100%
accurate for these two calls.

But I’ve read (I don’t remember where) that in a non-top-level filter
driver the thread could be an arbitrary thread in cases where a higher
>level doesn’t pass the IRP directly down (like queuing it).

When there are no filters above you, you are called directly by the I/O
manager as a result of the user requests. This means that you get defined
behavior in your dispatch entry point: you are called in the context of the
requesting thread (and thus process) and the thread field of the IRP matches
the current thread.

However, when there is another filter above you there is someone between you
and the I/O manager, which means they can change the behavior in subtle
ways. This is not to say that it’s common or recommended (see the thread
“SID of requesting thread” from earlier this week), but it’s possible. For
example, a filter may rely on the fact that most drivers don’t care that the
request arrives in the context of the requesting thread, just that it
arrives in the context of the requesting process (see KeStackAttachProcess
for how you can get back to a particular process context). This would allow
that filter to post the operation to a worker thread and send it down later
from a different thread but in the same process context. It’s a bit fast and
loose, but the file system filter world is a crazy place…

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

Hope to see you at the next OSR kernel debugging class February 14th in
Columbia, MD!

wrote in message news:xxxxx@ntfsd…

In a filter driver, I’m trying to reliably determine the thread that
originally caused/created an IRP. Why? Because I want to see if the thread
(in a usermode program) that issues DeviceIoControl is the same thread that
issued the CreateFile on the device. But mostly because I’m trying to
understand thread context in drivers.

Many things I’ve read indicate that the thread, and I assume therefore the
value in Irp->Tail.Overlay.Thread, would match the thread of the usermode
program that issued the call, at least for the above two calls. But I’ve
read (I don’t remember where) that in a non-top-level filter driver the
thread could be an arbitrary thread in cases where a higher level doesn’t
pass the IRP directly down (like queuing it).

The article at
http://msdn.microsoft.com/en-us/library/ff540124(v=VS.85).aspx specifies
“thread context requirements” for the dispatch routines. It makes be believe
that the value in Irp->Tail.Overlay.Thread is in the usermode program
(again, for the above two calls) regardless of where my driver is in the
stack.

The documentation for IoGetRequestorProcess gives me similar worries (so I
assume gets EPROCESS from the ETHREAD pointer somehow)

I’d like to believe the MSDN article. Can anyone add any insight to this?

Mike

Scott,

I’ve been wondering about this. Suppose driver D assumes that it is called
directly from the I/O Manager, and therefore that it is in PASSIVE_LEVEL at
the top-level dispatch routines. Now, I plunk a filter driver F on top of
it. If I just do the WDF equivalent of IoCallDriver from the passive-level
thread, and don’t mess with anything that might put me into DISPATCH_LEVEL
or change the process context, can I guarantee that I have not violated the
preconditions for successful execution of the driver? Particularly if
driver D is doing “mode Neither” I/O where it assumes that it is going to
have the process context available.

And if I create a new IRP, what magic do I need to do to guarantee I don’t
violate the preconditions of the former top-level driver? The suggestion
seemed to be that a minifilter driver would be the correct solution here, if
I’ve understood correctly.

I’d rather not have to mess with thread or process context unless that is
actually required, because this sounds a bit fragile.

Basically, these are just questions for my own curiosity.
joe

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

>If I just do the WDF equivalent of IoCallDriver from the passive-level

thread, and don’t mess with anything that might put me into DISPATCH_LEVEL
or change the process context, can I guarantee that I have not violated the
preconditions for successful execution of the driver?

Absolutely. IoCallDriver/WdfRequestSend are basically just subroutine calls
into the target driver’s dispatch entry point, so they do not represent any
kind of change in thread context. It has to work this way otherwise you
wouldn’t ever be able to filter a highest level driver.

And if I create a new IRP, what magic do I need to do to guarantee I don’t
violate the preconditions of the former top-level driver?

Just make sure that you send the request at passive level with the requestor
mode set to kernel. If you’re sending the request from kernel mode you will
(presumably) supply kernel buffers thus the process context isn’t as
important. The only exception is sending a create, which has special
considerations due to the security context (i.e. token) of the requestor.

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

Hope to see you at the next OSR kernel debugging class February 14th in
Columbia, MD!

“Joseph M. Newcomer” wrote in message news:xxxxx@ntfsd…

Scott,

I’ve been wondering about this. Suppose driver D assumes that it is called
directly from the I/O Manager, and therefore that it is in PASSIVE_LEVEL at
the top-level dispatch routines. Now, I plunk a filter driver F on top of
it. If I just do the WDF equivalent of IoCallDriver from the passive-level
thread, and don’t mess with anything that might put me into DISPATCH_LEVEL
or change the process context, can I guarantee that I have not violated the
preconditions for successful execution of the driver? Particularly if
driver D is doing “mode Neither” I/O where it assumes that it is going to
have the process context available.

And if I create a new IRP, what magic do I need to do to guarantee I don’t
violate the preconditions of the former top-level driver? The suggestion
seemed to be that a minifilter driver would be the correct solution here, if
I’ve understood correctly.

I’d rather not have to mess with thread or process context unless that is
actually required, because this sounds a bit fragile.

Basically, these are just questions for my own curiosity.
joe

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

> This would allow that filter to post the operation to a worker thread and send it down later from

a different thread but in the same process context.

In this case, wouldn’t the higher level filter have to make sure the thread context is set to the same non-arbitrary thread to satisfy the “thread context requirements” specified by MS?

Maybe the thread context isn’t what I should be concerned about. The value of the Thread in the IRP is what I really care about. I have been assuming that it is the same as the thread context. Is that a bad assumption?

Another solution is to make sure that no drivers are loaded on top of mine. Is that even possible?

–mike

As a legacy filter driver, there’s no way to guarantee your order in
the stack, much less that no one will be loaded on top of you.

On Tue, Dec 28, 2010 at 10:58 AM, wrote:
>> This would allow that filter to post the operation to a worker thread and send it down later from
>> a different thread but in the same process context.
>
> In this case, wouldn’t the higher level filter have to make sure the thread context is set to the same non-arbitrary thread to satisfy the “thread context requirements” specified by MS?
>
> Maybe the thread context isn’t what I should be concerned about. The value of the Thread in the IRP is what I really care about. I have been assuming that it is the same as the thread context. Is that a bad assumption?
>
> Another solution is to make sure that no drivers are loaded on top of mine. Is that even possible?
>
> --mike
>
>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

>In this case, wouldn’t the higher level filter have to make sure the thread

context is set to the same non-arbitrary thread to satisfy the >“thread
context requirements” specified by MS?

There is no (documented) way to get back to a particular thread context in a
driver, so this wouldn’t be possible from a filter. Again, usually what
drivers typically care about is process context and not particular thread
context, which is why posting might work.

Maybe the thread context isn’t what I should be concerned about. The value
of the Thread in the IRP is what I really care about. I have >been assuming
that it is the same as the thread context. Is that a bad assumption?

What are you trying to do exactly? When I originally read your question I
thought it was just a thought experiment and approached it as such. If there
is a particular problem that you’re trying to address then we should talk
about that to get you to the right solution.

-scott


Scott Noone
Consulting Associate
OSR Open Systems Resources, Inc.
http://www.osronline.com

Hope to see you at the next OSR kernel debugging class February 14th in
Columbia, MD!

wrote in message news:xxxxx@ntfsd…

This would allow that filter to post the operation to a worker thread and
send it down later from
a different thread but in the same process context.

In this case, wouldn’t the higher level filter have to make sure the thread
context is set to the same non-arbitrary thread to satisfy the “thread
context requirements” specified by MS?

Maybe the thread context isn’t what I should be concerned about. The value
of the Thread in the IRP is what I really care about. I have been assuming
that it is the same as the thread context. Is that a bad assumption?

Another solution is to make sure that no drivers are loaded on top of mine.
Is that even possible?

–mike

This quest started after reading about IoGetRequestorProcess. In XP, I don’t see how that function is reliable at all to see which UM program issued the request. Perhaps that would be a better topic for the discussion. Disassembly (in XP) shows that it uses Tail.Overlay.Thread so it is only as reliable as that value. So I started assuming that value represents the current thread context, which may be why I’m confusing people, including myself.

No it does not represent the current thread, as the documentation state
it is the thread the requested the I/O operation, i.e the thread that
called the I/O manager to create the IRP in most cases.

Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

xxxxx@cyberpointllc.com” wrote in
message news:xxxxx@ntfsd:

> This quest started after reading about IoGetRequestorProcess. In XP, I don’t see how that function is reliable at all to see which UM program issued the request. Perhaps that would be a better topic for the discussion. Disassembly (in XP) shows that it uses Tail.Overlay.Thread so it is only as reliable as that value. So I started assuming that value represents the current thread context, which may be why I’m confusing people, including myself.

To expand on what Mr. Burn wrote a bit…

The value in Tail.Overlay.Thread is definitively reliable for determining the thread/process that issue an IRP for requests originating from user mode (which is what we’re talking about, I think).

As Mr. Noone pointed out previously, if you’re the first driver entered from the I/O Manager you are guaranteed to be called in the context of the requesting thread/process. After that… barring control or pre-existing knowledge of all the drivers that are above you in the device branch in which your driver resides… the process and thread context in which your driver is called is arbitrary.

Peter
OSR

The promise of “if you are the first driver entered from the IO
manager, you will be in the context of the requesting thread/process”
has always seemed a little hollow to me given that advice of equal
weight is given elsewhere that “you cannot assume anything about your
position / ordering in any stack of devices”.

Is the Tail.Overlay.Thread value used by the IO manager to queue an
APC on IRP completion? I have a memory of being told / reading this
once, that this was how async pending IO finished …

On Wed, Dec 29, 2010 at 11:02 AM, wrote:
> To expand on what Mr. Burn wrote a bit…
>
>


>
> The value in Tail.Overlay.Thread is definitively reliable for determining the thread/process that issue an IRP for requests originating from user mode (which is what we’re talking about, I think).
>
>


>
> As Mr. Noone pointed out previously, if you’re the first driver entered from the I/O Manager you are guaranteed to be called in the context of the requesting thread/process. ?After that… barring control or pre-existing knowledge of all the drivers that are above you in the device branch in which your driver resides… the process and thread context in which your driver is called is arbitrary.
>
> Peter
> OSR
>
>
> —
> NTFSD is sponsored by OSR
>
> For our schedule of debugging and file system seminars
> (including our new fs mini-filter seminar) visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at http://www.osronline.com/page.cfm?name=ListServer
>

Well, perhaps. Except if the context in which you’re called is a constraint imposed by your driver. Imagine file systems trying to support (say) fast I/O if they couldn’t assume the process context in which there are called.

In a word: Yes.

Peter
OSR