IRQL management using file system filter driver

Hi all,

i am practicing using sync mechanism (mutex) in a minifilter and i am
having some doubts related to it.

I have a global to minifilter structure which data have to be
synchronize. Following i describe how data is manipulated:

  1. User-mode sends data to minifilter using “FilterSendMessage”
  2. Minifilter receives data via a callback routine given to
    “FltCreateCommunicationPort”. Data is written in the global structure
    inside the callback routine like this:

ExAcquireFastMutex(myMutex);

WriteData();

ExReleaseFastMutex(myMutex);

  1. Minifilter filters IRP Create and read the structure, performing
    some checkings:

ExAcquireFastMutex(myMutex);

ReadData();

ExReleaseFastMutex(myMutex);

My doubts are:

  • I have read (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
    that it is necessary to raise the IRQL when using mutex, preventing
    the interruption or pre-emption of the executing code, but what would
    be the problem if the IRQL is not raised?
  • If a mutex raise the IRQL, normally to APC_LEVEL, what happens if it
    is used some routine that needs PASSIVE_LEVEL?. I refer this because
    driver vierifier shown me this error.
  • If a mutex raise the IRQL to APC_LEVEL, it is possible that the
    minifilter driver execute code in DISPATCH_LEVEL and what would
    happen?.

Thank you guys for the help.

Fran

Comments inline:

“Fran Baena” wrote in message news:xxxxx@ntdev:

> My doubts are:
> - I have read (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
> that it is necessary to raise the IRQL when using mutex, preventing
> the interruption or pre-emption of the executing code, but what would
> be the problem if the IRQL is not raised?

The call raises the IRQL for you

> - If a mutex raise the IRQL, normally to APC_LEVEL, what happens if it
> is used some routine that needs PASSIVE_LEVEL?. I refer this because
> driver vierifier shown me this error.

It is an error, you need to redesign your code to not call routines that
must run at passive level while holding the mutex.

> - If a mutex raise the IRQL to APC_LEVEL, it is possible that the
> minifilter driver execute code in DISPATCH_LEVEL and what would
> happen?.
>

If once the mutex is held you raise the thread to DISPATCH_LEVEL there
is no problem. Of course you can only do operations legal at dispatch
when at that level.

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

You might want to ask minifilter question over on ntfsd.

  1. if you don’t follow the rules bad things may happen.
  2. running at dispatch level after acquiring the mutex is not in
    itself a problem, accessing pageable code and data is.

Mark Roddy

On Thu, Jun 2, 2011 at 2:01 PM, Fran Baena wrote:
> Hi all,
>
> i am practicing using sync mechanism (mutex) in a minifilter and i am
> having some doubts related to it.
>
> I have a global to minifilter structure which data have to be
> synchronize. Following i describe how data is manipulated:
>
> 1. User-mode sends data to minifilter using “FilterSendMessage”
> 2. Minifilter receives data via a callback routine given to
> “FltCreateCommunicationPort”. Data is written in the global structure
> inside the callback routine like this:
>
> ExAcquireFastMutex(myMutex);
>
> WriteData();
>
> ExReleaseFastMutex(myMutex);
>
> 3. Minifilter filters IRP Create and read the structure, performing
> some checkings:
>
> ExAcquireFastMutex(myMutex);
>
> ReadData();
>
> ExReleaseFastMutex(myMutex);
>
>
> My doubts are:
> ?- I have read (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
> that it is necessary to raise the IRQL when using mutex, preventing
> the interruption or pre-emption of the executing code, but what would
> be the problem if the IRQL is not raised?
> - If a mutex raise the IRQL, normally to APC_LEVEL, what happens if it
> is used some routine that needs PASSIVE_LEVEL?. ?I refer this because
> driver vierifier shown me this error.
> - If a mutex raise the IRQL to APC_LEVEL, it is possible that the
> minifilter driver execute code in DISPATCH_LEVEL and what would
> happen?.
>
>
> Thank you guys for the help.
>
> Fran
>
> —
> NTDEV is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars 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
>

Fran Baena wrote:

My doubts are:

You get into a potential deadlock situation if two processes with
different IRQLs are competing for the same resource. If a higher
priority thread (which cannot block) needs to grab a mutex owned by a
lower priority thread, the higher priority thread cannot release the CPU
so that the lower priority thread can run and release it.

By raising the IRQL to the same level, all of the threads are forced to
share equally. The mutex holder will eventually be able to run and
release the mutex.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Doing reads and writes under a lock is surely a bad idea.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

“Fran Baena” wrote in message news:xxxxx@ntdev…
> Hi all,
>
> i am practicing using sync mechanism (mutex) in a minifilter and i am
> having some doubts related to it.
>
> I have a global to minifilter structure which data have to be
> synchronize. Following i describe how data is manipulated:
>
> 1. User-mode sends data to minifilter using “FilterSendMessage”
> 2. Minifilter receives data via a callback routine given to
> “FltCreateCommunicationPort”. Data is written in the global structure
> inside the callback routine like this:
>
> ExAcquireFastMutex(myMutex);
>
> WriteData();
>
> ExReleaseFastMutex(myMutex);
>
> 3. Minifilter filters IRP Create and read the structure, performing
> some checkings:
>
> ExAcquireFastMutex(myMutex);
>
> ReadData();
>
> ExReleaseFastMutex(myMutex);
>
>
> My doubts are:
> - I have read (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
> that it is necessary to raise the IRQL when using mutex, preventing
> the interruption or pre-emption of the executing code, but what would
> be the problem if the IRQL is not raised?
> - If a mutex raise the IRQL, normally to APC_LEVEL, what happens if it
> is used some routine that needs PASSIVE_LEVEL?. I refer this because
> driver vierifier shown me this error.
> - If a mutex raise the IRQL to APC_LEVEL, it is possible that the
> minifilter driver execute code in DISPATCH_LEVEL and what would
> happen?.
>
>
> Thank you guys for the help.
>
> Fran
>

>> - I have read

> (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
> that it is necessary to raise the IRQL when using mutex,
> preventing the interruption or pre-emption of the executing code,
> but what would be the problem if the IRQL is not raised?

You get into a potential deadlock situation if two processes with
different IRQLs are competing for the same resource. If a higher
priority thread (which cannot block) needs to grab a mutex owned
by a lower priority thread, the higher priority thread cannot
release the CPU so that the lower priority thread can run and
release it.

By raising the IRQL to the same level, all of the threads are
forced to share equally. The mutex holder will eventually be
able to run and release the mutex.

No, that’s not the reason. Being at APC_LEVEL has no impact on how
threads are scheduled or whether they can block.

The actual reason why disabling APCs (either by raising to APC_LEVEL
or by entering a critical region) is necessary before acquiring a lock
is to prevent deadlocks that can occur if a user thread is suspended
while holding a kernel lock. See for example discussion under
“Security Issues” in this article:

Locks, Deadlocks, and Synchronization
http://msdn.microsoft.com/en-us/library/ms810047.aspx

Outstanding paper. This one provides background as well.
http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx

mm
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Pavel Lebedynskiy
Sent: Thursday, June 02, 2011 5:21 PM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] IRQL management using file system filter driver

> - I have read
> (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
> that it is necessary to raise the IRQL when using mutex,
> preventing the interruption or pre-emption of the executing code,
> but what would be the problem if the IRQL is not raised?

You get into a potential deadlock situation if two processes with
different IRQLs are competing for the same resource. If a higher
priority thread (which cannot block) needs to grab a mutex owned
by a lower priority thread, the higher priority thread cannot
release the CPU so that the lower priority thread can run and
release it.

By raising the IRQL to the same level, all of the threads are
forced to share equally. The mutex holder will eventually be
able to run and release the mutex.

No, that’s not the reason. Being at APC_LEVEL has no impact on how
threads are scheduled or whether they can block.

The actual reason why disabling APCs (either by raising to APC_LEVEL
or by entering a critical region) is necessary before acquiring a lock
is to prevent deadlocks that can occur if a user thread is suspended
while holding a kernel lock. See for example discussion under
“Security Issues” in this article:

Locks, Deadlocks, and Synchronization
http://msdn.microsoft.com/en-us/library/ms810047.aspx


NTDEV is sponsored by OSR

For our schedule of WDF, WDM, debugging and other seminars 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

2011/6/2 Pavel Lebedynskiy :
>>> ?- I have read
>>> (http://msdn.microsoft.com/en-us/windows/hardware/gg487402.aspx)
>>> that it is necessary to raise the IRQL when using mutex,
>>> preventing the interruption or pre-emption of the executing code,
>>> but what would be the problem if the IRQL is not raised?
>>
>> You get into a potential deadlock situation if two processes with
>> different IRQLs are competing for the same resource. ?If a higher
>> priority thread (which cannot block) needs to grab a mutex owned
>> by a lower priority thread, the higher priority thread cannot
>> release the CPU so that the lower priority thread can run and
>> release it.
>>
>> By raising the IRQL to the same level, all of the threads are
>> forced to share equally. ?The mutex holder will eventually be
>> able to run and release the mutex.
>
> No, that’s not the reason. Being at APC_LEVEL has no impact on how
> threads are scheduled or whether they can block.
>
> The actual reason why disabling APCs (either by raising to APC_LEVEL
> or by entering a critical region) is necessary before acquiring a lock
> is to prevent deadlocks that can occur if a user thread is suspended
> while holding a kernel lock. See for example discussion under
> “Security Issues” in this article:

OK, i understand the importance of raising the IRQL when acquiring a
mutex. I have two more questions:
1) IRQL belongs to the thread or the processor? At “Scheduling, Thread
Context, and IRQL” document the definition says that is related to the
processor, but in practice it is referenced to the thread: thread A
running in IRQL=PASSIVE_LEVEL…
2) What happens if a thread acquire a mutex raising the IRQL and it is
not released in such thread? The next scheduled thread will run at
previous thread IRQL?
3) What happens if a thread runs in IRQL=DISPATCH_LEVEL and acquires a
fast mutext (it is supposed that it raises the IRQL to APC_LEVEL)?

Thank you for the answers. I really apreciate your collaboration.
Fran

>1) IRQL belongs to the thread or the processor? At "Scheduling, Thread

To processor, but the difference between APC_LEVEL and PASSIVE_LEVEL - also to the thread.

  1. What happens if a thread acquire a mutex raising the IRQL and it is
    not released in such thread?

Deadlock.

  1. What happens if a thread runs in IRQL=DISPATCH_LEVEL and acquires a
    fast mutext (it is supposed that it raises the IRQL to APC_LEVEL)?

Crash due to assert-kind thing in Ke I believe.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>>1) IRQL belongs to the thread or the processor? At "Scheduling, Thread

To processor, but the difference between APC_LEVEL and PASSIVE_LEVEL - also to the thread.

So, in thread pre-emption, what IRQL is selected? The new thread IRQL?
Current processor IRQL?.

>2) What happens if a thread acquire a mutex raising the IRQL and it is
>not released in such thread?

Deadlock.

So, if a thread raises IRQL via mutex and the release mutex is not in
the thread code (by any reason), what is the IRQL for the next
scheduled thread?

>3) What happens if a thread runs in IRQL=DISPATCH_LEVEL and acquires a
>fast mutext (it is supposed that it raises the IRQL to APC_LEVEL)?

Crash due to assert-kind thing in Ke I believe.

In this case, what should we do? Not acquiring the mutex (what sounds
unsafe)? Or it is just a design problem?

Thank you for answering.
Fran

Fran Baena wrote:

OK, i understand the importance of raising the IRQL when acquiring a
mutex. I have two more questions:

  1. IRQL belongs to the thread or the processor? At “Scheduling, Thread
    Context, and IRQL” document the definition says that is related to the
    processor, but in practice it is referenced to the thread: thread A
    running in IRQL=PASSIVE_LEVEL…

Well, the question is a little confusing. Really, the answer is
“both”. It’s almost like another CPU register. When a thread is not
running, the thread still has an IRQL. When it gets scheduled, the IRQL
is set for that processor by (in part) modifying the interrupt controller.

In your mental model, you need to think about it both ways. The current
processor has an IRQL, but it does so because the thread it is running
has that IRQL.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

> So, in thread pre-emption, what IRQL is selected? The new thread IRQL?

Current processor IRQL?.

There is no preemption of >= DISPATCH.

So, either APC or PASSIVE is selected, depending on the new thread.

So, if a thread raises IRQL via mutex and the release mutex is not in
the thread code (by any reason), what is the IRQL for the next
scheduled thread?

For FAST_MUTEX - see above.

In this case, what should we do? Not acquiring the mutex (what sounds
unsafe)? Or it is just a design problem?

Mutex just plain does not work on >= DISPATCH. Only spinlocks work there.


Maxim S. Shatskih
Windows DDK MVP
xxxxx@storagecraft.com
http://www.storagecraft.com

>> 2) What happens if a thread acquire a mutex raising the IRQL and it is

> not released in such thread?

Deadlock.

Or an APC_INDEX_MISMATCH bugcheck, if the thread tries to return to user mode while still running with APCs disabled.

Thank you for the help. It was really helpul.
Fran