A crash after copying data to a buffer getting from an MDL

I wrote a virtual USB bus driver in Windows, it’s a WDM driver. After it enumerate the USBSTOR driver, in the usb bulk or interrupt transfer phase, the USBSTOR driver will send some IRPs with MDL pointer. It means that using direct I/O method (but strangely, the “Method” in the IRP is “Neither”). When I use the MDL to copy data, it cause a crash. The code to deal with the mdl is below:

if(Irp->MdlAddress != NULL)
{
buf = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

//It will not crash without this sentence
RtlMoveMemory(buf, data, dataLength);
}

Without copying data, it will not crash. But when crash happen, there always be some delay from copying, and the point it crash down, not always at one place.
When I print out the data from the buffer before copying to it, I saw some times it’s not all zero. It should be all zero. Possibly, it means the “buf” pointer dosn’t point to the right buffer the data shall be copied to. The data was copied to an unknow place in the kernel, it cause a crash.

The question is why would I get a wrong virtual address by using MmGetSystemAddressForMdlSafe(), is this a bug of USBSTOR driver or what? Should I do something else before copying data? BTW, usually the “buf” is “f8xxxxxx”, it’s higher then normal virtual address like “81xxxxxx”. Does it mean something?

> RtlMoveMemory(buf, data, dataLength);

And from where you get this dataLength?


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

disney_cheng@qq.com wrote:

I wrote a virtual USB bus driver in Windows, it’s a WDM driver. After it enumerate the USBSTOR driver, in the usb bulk or interrupt transfer phase, the USBSTOR driver will send some IRPs with MDL pointer. It means that using direct I/O method (but strangely, the “Method” in the IRP is “Neither”). When I use the MDL to copy data, it cause a crash. The code to deal with the mdl is below:

if(Irp->MdlAddress != NULL)

If you are a filter below USBSTOR, then the IRPs you are receiving are
all URBs. In that case, there is no promise that Irp->MdlAddress
contains anything useful at all. When you get an URB, all of the useful
information is in the URB structure, including the pointer to the data
buffer. Irp->MdlAddress might contain something left over from the
request that USBSTOR received, but if so, that’s just an accident that
you cannot rely on. They might have created an IRP from scratch, and in
that case Irp->MdlAddress will be garbage.


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

It’s the length of “data”, and it’s not bigger than the length of “buf”.

RtlMoveMemory(buf, data, dataLength);

And from where you get this dataLength?


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

I have to say sorry about this. Exactly, I use the TransferBufferMdl pointer in the URB, which is get from the IRP by using URB_FROM_IRP().

if (pUrb->UrbBulkOrInterruptTransfer.TransferBuffer != NULL)
{
RtlMoveMemory(pUrb->UrbBulkOrInterruptTransfer.TransferBuffer, data, dataLength);
}
else if (pUrb->UrbBulkOrInterruptTransfer.TransferBufferMdl != NULL)
{
mdl = pUrb->UrbBulkOrInterruptTransfer.TransferBufferMdl;
buf = MmGetSystemAddressForMdlSafe(mdl, NormalPagePriority);

//It will not crash without this sentence
RtlMoveMemory(buf, data, dataLength);
}

I read the sample codes about using usb bulk transfer in WinWDK sample. The mdl is initialized by MmBuildPartialMdl(), and the docs say we can use MmGetSystemAddressForMdlSafe() to map or get the virtual address of the system space. Is that correct?

If you are a filter below USBSTOR, then the IRPs you are receiving are
all URBs. In that case, there is no promise that Irp->MdlAddress
contains anything useful at all. When you get an URB, all of the useful
information is in the URB structure, including the pointer to the data
buffer. Irp->MdlAddress might contain something left over from the
request that USBSTOR received, but if so, that’s just an accident that
you cannot rely on. They might have created an IRP from scratch, and in
that case Irp->MdlAddress will be garbage.


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

Additional information about this problem. The dispatch routine to handle this IRP is at DISPATCH_LECEL, but I change the IRQL to PASSIVE_LEVEL by KeLowerIrql() at the beginning of dealing with it. Because I have to use TDI driver to send an receive datas, some functions about using TDI must be used at IRQL < DISPATCH_LEVEL.

Typically the rule of thumb is if you don’t originally set IRQL you don’t CHANGE IRQL, or you make damn sure it’s reset to where it started when you got there. So … since you LOWERED the IRQL to do some PASSIVE level processing, were you kind and set it BACK to DISPATCH before you left?

Gary G. Little

----- Original Message -----
From: “disney cheng” <disney_cheng>
To: “Windows System Software Devs Interest List”
Sent: Wednesday, December 15, 2010 5:26:57 AM
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an MDL

Additional information about this problem. The dispatch routine to handle this IRP is at DISPATCH_LECEL, but I change the IRQL to PASSIVE_LEVEL by KeLowerIrql() at the beginning of dealing with it. Because I have to use TDI driver to send an receive datas, some functions about using TDI must be used at IRQL < DISPATCH_LEVEL.


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</disney_cheng>

I thought the rule was that you never lower IRQL if you didn’t raise it in
the first place.

Bill

From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Gary G. Little
Sent: Wednesday, December 15, 2010 8:13 AM
To: Windows System Software Devs Interest List
Subject: Re: [ntdev] A crash after copying data to a buffer getting from an
MDL

Typically the rule of thumb is if you don’t originally set IRQL you don’t
CHANGE IRQL, or you make damn sure it’s reset to where it started when you
got there. So … since you LOWERED the IRQL to do some PASSIVE level
processing, were you kind and set it BACK to DISPATCH before you left?

Gary G. Little

----- Original Message -----
From: “disney cheng” <disney_cheng>
To: “Windows System Software Devs Interest List”
Sent: Wednesday, December 15, 2010 5:26:57 AM
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an
MDL

Additional information about this problem. The dispatch routine to handle
this IRP is at DISPATCH_LECEL, but I change the IRQL to PASSIVE_LEVEL by
KeLowerIrql() at the beginning of dealing with it. Because I have to use TDI
driver to send an receive datas, some functions about using TDI must be used
at IRQL < DISPATCH_LEVEL.


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


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</disney_cheng>

On Wed, Dec 15, 2010 at 6:26 AM, <disney_cheng> wrote:
> KeLowerIrql() at the beginning of dealing with i

No no no. bad dog.

Mark Roddy</disney_cheng>

According to the document of WDK, you are right. The parameter of KeLowerIrql() must retrieved by KeRaiseIrql(). It’s a fatal error if not following this rule. But I don’t think it’s the reason of the problem. Because I saw some one else did this, and it works well. I found a virtual usb bus driver on the internet, and look into it’s IRP process, the IRPs in bulk or interrupt transfer are all sent at Dispatch Level and finished at Passive Level. It means that, the virtual usb bus driver lower the IRQL without raising it back before completing the IRP.
I think the operation of changing the IRQL won’t be treated as a mistake by the system. But it’s easily cause mistakes because many interface function have to work at prescriptive IRQL.

I thought the rule was that you never lower IRQL if you didn’t raise it in
the first place.

> RtlMoveMemory(buf, data, dataLength);

And from where you get this dataLength?


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

This dataLength is smaller then the length of buf, I’ve already checked it.

The documentation is correct. Your code is incorrect. Just because you found
some code someplace doesn’t mean that the code you found is correct. You
must follow the rules.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of disney_cheng@qq.com
Sent: Wednesday, December 15, 2010 9:29 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an
MDL

According to the document of WDK, you are right. The parameter of
KeLowerIrql() must retrieved by KeRaiseIrql(). It’s a fatal error if not
following this rule. But I don’t think it’s the reason of the problem.
Because I saw some one else did this, and it works well. I found a virtual
usb bus driver on the internet, and look into it’s IRP process, the IRPs in
bulk or interrupt transfer are all sent at Dispatch Level and finished at
Passive Level. It means that, the virtual usb bus driver lower the IRQL
without raising it back before completing the IRP.
I think the operation of changing the IRQL won’t be treated as a mistake by
the system. But it’s easily cause mistakes because many interface function
have to work at prescriptive IRQL.

I thought the rule was that you never lower IRQL if you didn’t raise it in
the first place.


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

But it can run correctly. Further more, it load the USBTOR driver as I do.

-----Original Message-----
The documentation is correct. Your code is incorrect. Just because you found
some code someplace doesn’t mean that the code you found is correct. You
must follow the rules.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@qq.com
Sent: Wednesday, December 15, 2010 9:29 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an
MDL

According to the document of WDK, you are right. The parameter of
KeLowerIrql() must retrieved by KeRaiseIrql(). It’s a fatal error if not
following this rule. But I don’t think it’s the reason of the problem.
Because I saw some one else did this, and it works well. I found a virtual
usb bus driver on the internet, and look into it’s IRP process, the IRPs in
bulk or interrupt transfer are all sent at Dispatch Level and finished at
Passive Level. It means that, the virtual usb bus driver lower the IRQL
without raising it back before completing the IRP.
I think the operation of changing the IRQL won’t be treated as a mistake by
the system. But it’s easily cause mistakes because many interface function
have to work at prescriptive IRQL.

I thought the rule was that you never lower IRQL if you didn’t raise it in
the first place.

>But it can run correctly. Further more, it load the USBTOR driver as I do.

If you corrupt a memory buffer and the system continues to run, does it mean
that it isn’t a bug to corrupt the memory buffer? By lowering the IRQL of
the processor you’re breaking a contract with the O/S, just because it
doesn’t crash immediately doesn’t mean that it isn’t a bug.

Writing drivers is hard and has unique challenges, such as dealing with
IRQL. You can’t just exempt yourself from the rules because it’s easier.

Also, try running Driver Verifier on your driver and see if the system
crashes then.

-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!

Really? Then why not go back to where you found that magical code and ask your question there, since you obviously do not like the answers you are getting here?

Gary G. Little

----- Original Message -----
From: “disney cheng” <disney_cheng>
To: “Windows System Software Devs Interest List”
Sent: Wednesday, December 15, 2010 10:03:49 AM
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an MDL

But it can run correctly. Further more, it load the USBTOR driver as I do.

-----Original Message-----
The documentation is correct. Your code is incorrect. Just because you found
some code someplace doesn’t mean that the code you found is correct. You
must follow the rules.

Bill Wandel

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@qq.com
Sent: Wednesday, December 15, 2010 9:29 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an
MDL

According to the document of WDK, you are right. The parameter of
KeLowerIrql() must retrieved by KeRaiseIrql(). It’s a fatal error if not
following this rule. But I don’t think it’s the reason of the problem.
Because I saw some one else did this, and it works well. I found a virtual
usb bus driver on the internet, and look into it’s IRP process, the IRPs in
bulk or interrupt transfer are all sent at Dispatch Level and finished at
Passive Level. It means that, the virtual usb bus driver lower the IRQL
without raising it back before completing the IRP.
I think the operation of changing the IRQL won’t be treated as a mistake by
the system. But it’s easily cause mistakes because many interface function
have to work at prescriptive IRQL.

>I thought the rule was that you never lower IRQL if you didn’t raise it in
the first place.


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</disney_cheng>

The one of correct ways of doing this is put the TDI request to a worker
queue, fire one or more workitems to submit them to the TDI driver.

Calvin

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of disney_cheng@qq.com
Sent: Wednesday, December 15, 2010 3:27 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] A crash after copying data to a buffer getting from an
MDL

Additional information about this problem. The dispatch routine to handle
this IRP is at DISPATCH_LECEL, but I change the IRQL to PASSIVE_LEVEL by
KeLowerIrql() at the beginning of dealing with it. Because I have to use TDI
driver to send an receive datas, some functions about using TDI must be used
at IRQL < DISPATCH_LEVEL.


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

I’d guess the OP has missed something in the code he/she read. He didn’t say
he saw the code lower the irql. Rather, he said because it starts at
dispatch end ends at passive, hence it must have lowered the irql in
between. This is not correct reasoning. Say, I have an SRB starts at dirql,
completes at dispatch, that certainly doesn’t indicate I’m stupid enough to
lower it to dispatch.

Calvin

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Scott Noone
Sent: Wednesday, December 15, 2010 8:26 AM
To: Windows System Software Devs Interest List
Subject: Re:[ntdev] A crash after copying data to a buffer getting from an
MDL

But it can run correctly. Further more, it load the USBTOR driver as I do.

If you corrupt a memory buffer and the system continues to run, does it mean

that it isn’t a bug to corrupt the memory buffer? By lowering the IRQL of
the processor you’re breaking a contract with the O/S, just because it
doesn’t crash immediately doesn’t mean that it isn’t a bug.

Writing drivers is hard and has unique challenges, such as dealing with
IRQL. You can’t just exempt yourself from the rules because it’s easier.

Also, try running Driver Verifier on your driver and see if the system
crashes then.

-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!


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

No I think the OP said exactly that:

“The dispatch routine to handle this IRP is at DISPATCH_LECEL, but I
change the IRQL to PASSIVE_LEVEL by KeLowerIrql() at the beginning of
dealing with it.”

Bad dog.

Mark Roddy

On Wed, Dec 15, 2010 at 12:37 PM, Calvin Guan wrote:
> I’d guess the OP has missed something in the code he/she read. He didn’t say
> he saw the code lower the irql. Rather, he said because it starts at
> dispatch end ends at passive, hence it must have lowered the irql in
> between. This is not correct reasoning. Say, I have an SRB starts at dirql,
> completes at dispatch, that certainly doesn’t indicate I’m stupid enough to
> lower it to dispatch.
>
> Calvin
>
> -----Original Message-----
> From: xxxxx@lists.osr.com
> [mailto:xxxxx@lists.osr.com] On Behalf Of Scott Noone
> Sent: Wednesday, December 15, 2010 8:26 AM
> To: Windows System Software Devs Interest List
> Subject: Re:[ntdev] A crash after copying data to a buffer getting from an
> MDL
>
>>But it can run correctly. Further more, it load the USBTOR driver as I do.
>
> If you corrupt a memory buffer and the system continues to run, does it mean
>
> that it isn’t a bug to corrupt the memory buffer? By lowering the IRQL of
> the processor you’re breaking a contract with the O/S, just because it
> doesn’t crash immediately doesn’t mean that it isn’t a bug.
>
> Writing drivers is hard and has unique challenges, such as dealing with
> IRQL. You can’t just exempt yourself from the rules because it’s easier.
>
> Also, try running Driver Verifier on your driver and see if the system
> crashes then.
>
> -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!
>
>
> —
> 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
>
>
> —
> 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
>

I think that’s what the OP did in his code, but may not be what he actually read from the sample code from the internet.

Anyway, lowering the IRQL in this case is nothing but plain evil.

Several issues, see below…

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of disney_cheng@qq.com
Sent: Tuesday, December 14, 2010 10:56 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] A crash after copying data to a buffer getting from an MDL

I wrote a virtual USB bus driver in Windows, it’s a WDM driver. After it
enumerate the USBSTOR driver, in the usb bulk or interrupt transfer phase,
the USBSTOR driver will send some IRPs with MDL pointer. It means that using
direct I/O method (but strangely, the “Method” in the IRP is “Neither”).
When I use the MDL to copy data, it cause a crash. The code to deal with the
mdl is below:

if(Irp->MdlAddress != NULL)
{
buf = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority);

//It will not crash without this sentence
RtlMoveMemory(buf, data, dataLength); }

***************
There is a serious error here unless you have omitted the code in the
posting. Where is the test that sees if MmGetSystemAddressForMdlSafe
worked? Do you know buf is non-NULL? But it is hard to guess what is going
on here. What is the address of ‘data’? How was it obtained? What is the
value of dataLength? How was it obtained? Essentially, you have apparently
made no attempt to determine what has gone wrong here. You have not
explained to use where the other two parameters come from, so we have no
idea what they mean, or if they could be the problem. You will get these
errors if buf is illegal, if buf has any illegal state from buf to
buf+dataLength-1, if data is illegal, or there is any illegal state from
data to data+datalength-1. We see 1/3 of the problem, which has an obvious
error, but we’re missing the other 2/3.

Note that for USB transfers, you can only transfer the maximum bulk transfer
size on any transaction, e.g., 1K bytes for USB 1.0, 2K bytes for high-speed
USB 2.0, etc., and since you have said nothing about the expected buffer
sizes, or any attempt you are making to limit transfer sizes, there is no
way to tell what is going on here. I might as well say
“I have an error in this statement. What’s wrong?
SUM = DATA + SUM;”

Until you explain where *all* these values come from, or actually tell us,
by using the debugger, what you are seeing for thse values, there’s no good
way to guess, except using psychic vibrations, what is going on. I’m mpt
very good at debugging via psychic vibrations.
******************

Without copying data, it will not crash. But when crash happen, there always
be some delay from copying, and the point it crash down, not always at one
place.
When I print out the data from the buffer before copying to it, I saw some
times it’s not all zero. It should be all zero. Possibly, it means the “buf”
pointer dosn’t point to the right buffer the data shall be copied to. The
data was copied to an unknow place in the kernel, it cause a crash.

The question is why would I get a wrong virtual address by using
MmGetSystemAddressForMdlSafe(), is this a bug of USBSTOR driver or what?
Should I do something else before copying data? BTW, usually the “buf” is
“f8xxxxxx”, it’s higher then normal virtual address like “81xxxxxx”. Does it
mean something?

***********
You could get NULL, an illegal address that I do not see you testing for.

Kernel addresses are going to be in the valid kernel range. With a default
(not 3GB) boot, this means they will potentially be in the range
80000000-FFFFFFFF. I think the higest upper addresses have some specific
value range used for devices, but F8xxxxxx sounds like a reasonable value.
***********


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


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