Potential access violations from Callback routine

Dear All,

We have a driver, developed to support Busmaster DMA operation. As such,
it uses a callback routine, often known as AdapterControl, which is
invoked by making a call to IoAllocateAdapterChannel.

My concern is that the callback routine runs at IRQL DISPATCH_LEVEL. As
such, it is my understanding that it cannot tolerate any page faults that
might be generated by making accesses to pageable memory. How can I be
confident that none of the memory accesses that are made from within
AdapterControl could lead to access violations?

Can I be sure that accesses to local (stack-based) variables from within
AdapterControl are safe (it seems that this must be so, but I’m not sure
why). There are a number of parameters passed to AdapterControl. We do not
use DeviceObject or Irp in our Busmaster application. MapRegisterBase is a
pointer supplied by the HAL and I would assume that this would be safe.
However, we use the context parameter to pass in a pointer to some DMA
parameters. It would seem that this referenced data should reside in
non-paged space, otherwise there is the potential for pagefaults and
consequently an exception. Is this correct and what is the best way to
ensure that this memory containing the DMA parameters can be safely
accessed?

Additionally, the call to IoAllocateAdapterChannel must be called at IRQL
DISPATCH_LEVEL and so it is bounded by a KeRaiseIrql/KeLowerIrql pair. It
would seem that accesses to pageable memory from within this bounded
region might also be unsafe. In this case, would it be best to transfer
all parameters used by IoAllocateAdapterChannel to local (stack-based)
variables outside this region?

Could the above scenario explain a reported “Blue Screen” on Win2K that
read
-----------------------------snip-----------------------------
STOP:0x000001E (0C0000005, 0xBD1FFC5A, 0x00000000, 0x00000020)
KMODE_EXCEPTION_NOT_HANDLED
*** ADDRESSS BD1FFC5A base at BD1EE000, DateStamp 3ab89e57 - ourdriver.sys
-----------------------------snip-----------------------------
The report suggests that the callback routine was not being used at this
time and so the driver was not running at IRQL DISPATCH_LEVEL. What other
situations might give rise to this access violation?

This seems quite an important issue but I haven’t seen much made of it in
the literature. Have I missed something?

Thanks for any help,
Richard


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

> confident that none of the memory accesses that are made from within

AdapterControl could lead to access violations?

Ensure that no pointers to pageable stuff are dereferenced in this routine.

Can I be sure that accesses to local (stack-based) variables from within
AdapterControl are safe (it seems that this must be so, but I’m not sure

Yes, the stack of the running thread is page-locked.

why). There are a number of parameters passed to AdapterControl. We do not
use DeviceObject or Irp in our Busmaster application. MapRegisterBase is a
pointer supplied by the HAL and I would assume that this would be safe.

Surely. MapRegisterBase is not a pointer - it is some opaque value passed to
the AdapterControl callback which it must pass to IoMapTransfer.
A kind of the “handle”, it is only called PVOID. The value is meaningful
only to HAL internals.

However, we use the context parameter to pass in a pointer to some DMA
parameters. It would seem that this referenced data should reside in
non-paged space, otherwise there is the potential for pagefaults and
consequently an exception. Is this correct

Yes.

and what is the best way to
ensure that this memory containing the DMA parameters can be safely
accessed?

Allocate it from nonpaged pool.
If this is a part of your device extension - it is nonpaged.

Additionally, the call to IoAllocateAdapterChannel must be called at IRQL
DISPATCH_LEVEL and so it is bounded by a KeRaiseIrql/KeLowerIrql pair. It
would seem that accesses to pageable memory from within this bounded
region might also be unsafe.

Yes.

Could the above scenario explain a reported “Blue Screen” on Win2K that
read
-----------------------------snip-----------------------------
STOP:0x000001E (0C0000005, 0xBD1FFC5A, 0x00000000, 0x00000020)
KMODE_EXCEPTION_NOT_HANDLED

Such thing is usually AV fault on IRQL < DISPATCH_LEVEL.
Wrong pointer access on DISPATCH_LEVEL is IRQL_NOT_LESS_OR_EQUAL.

Max


You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com

>We have a driver, developed to support Busmaster DMA operation. As such,

it uses a callback routine, often known as AdapterControl, which is
invoked by making a call to IoAllocateAdapterChannel.

My concern is that the callback routine runs at IRQL DISPATCH_LEVEL. As
such, it is my understanding that it cannot tolerate any page faults that
might be generated by making accesses to pageable memory. How can I be
confident that none of the memory accesses that are made from within
AdapterControl could lead to access violations?

Page faults while running at DISPATCH_LEVEL are bad (as in blue screen).
You have to ASSURE you only touch page locked memory. The kernel stack will
always be page locked, as will the device extension, as will most of the
common kernel data structures. Data passed from an app may not be, but you
probably had to call MmProbeAndLockPages to get an MDL/system virtual
address accessible from arbitrary context anyway (as in you can’t just
initiate your DMA in the read/write call, but have queued the IRP and
initiated the DMA when the device interrupts with the completion of the
previous operation).

I have to admit, I can’t offhand think of a documented list that describes
the page locked state of every memory block returned from every kernel API
(hint hint Microsoft doc people). Actually, just a list of structures that
aren’t might be sufficient. Clearly memory you allocate in the driver from
non-paged pool has this issue.

A reason the AdapterControl callback has to be at DISPATCH_LEVEL is because
this assures your code can’t be preempted, and has appropriate SMP locking.
Having everything totally ready to go BEFORE allocating a potentially
shared DMA channel minimizes the time the “adapter” is busy. Processing a
page fault could take eons compared to the DMA.

A thing I often do is allocate EVERYTHING page locked initially in driver
development, and then over time, as the driver moves forward, carefully
move data/code to pageable space. A driver that has a little extra locked
memory is a lot better than having one byte that should have been locked,
and isn’t.

Often in driver development, it’s good to think in terms of “what are the
consequences of being wrong”. ANYTHING that could cause a blue screen is
horribly bad. As many things are a bit fuzzy, taking the path of least
danger is best, until something clearly proves resource consumption is too
high or performance is too low. The number one mantra should be “stability
is top priority”.

  • Jan

You are currently subscribed to ntdev as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntdev-$subst(‘Recip.MemberIDChar’)@lists.osr.com