Access UserBuffer BSOD

In my filter,In IRP_MJ_WRITE dispatch routine:
In a MN_NORMAL,not paging IO,and the device object is DO_NEITHER_IO(of course it is),so I use Irp->UserBuffer.
It will works well,but in some situation,it will BSOD.

BYTE * pData=NULL;

pData=Irp->UserBuffer;
for (i=0;i
It will BSOD.
In a example:
When BSOD occurs,I can see the pData is 0x02A00000,and the pData is invalid.

But why?the pData is from user process,and I handle it in this process context.
And what shall I do?

Look at SwapBuffers sample, it provides information how
to deal with the buffers given to READ/WRITE handlers.

L.

Applications can send you invalid buffers and if your driver cannot
correctly detect and handle this, you’re driver is broken.

It is possible this is an application bug, or perhaps it is something
more subtle, but in either case you clearly have a bug at the moment
because you are not properly probing and using structured exception
handling around your access of a user buffer.

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

in my example:
WinWord 2003 in WinXP sp2,it save a document in RDR.
So,Word has a bug???

What’s the properly probing and SEH in this situation?
Anybody can show me the code about it?
Thanks.

And,If I use SEH,I can’t modify the data in Pdata,I just return Error.
That’s to say,this IRP_MJ_WRITE must be bug in App?And the FSD also just return Error?
I can’t miss a normal write,it will modify the data of the file.

Truthfully, I’m not even sure what you are saying.

The normal way this is done is:

__try {

if (UserMode == Irp->RequestorMode) {
// validate that the buffer is in the right address
space
ProbeForRead(Irp->UserBuffer,
IoSp->Parameters.Write.Length, 0);
}

// access buffer here
} __except (MyExceptionFilter(GetExceptionInformation(),
GetExceptionCode()) {
//
// handle exception here
//
Irp->IoStatus.Status = GetExceptionCode();
Irp->IoStatus.Information = 0; // nothing being returned
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return GetExceptionCode();
}

In your exception filter, decide if this is a buffer error (out of
quota, access violation, etc.) and if it is return
EXCEPTION_EXECUTE_HANDLER. Otherwise reject the exception from your
filter (EXCEPTION_CONTINUE_SEARCH) and it’ll still blue screen, just not
because the user buffer is invalid.

My concern is that if you are struggling with something as basic as
this, you are working beyond your current level of knowledge and
experience. When you do not like the answers that we give you, perhaps
you might want to spend more time searching based upon what we’ve told
you. The collective experience of the group on this list is substantial
and it would be wise of you to utilize it with the respect that it is
due.

Regards,

Tony

Tony Mason
Consulting Partner
OSR Open Systems Resources, Inc.
http://www.osr.com

I have observed the situation I described.
It is not because the App use invalid memory!

1.Before I calldown(IoCallDriver) the IRP ,I observed the Irp->UserBuffer is 0x05430000,and I use “DB” command to view the memory,the memory is “???”(that means the memory is invalid?).
2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is STATUS_SUCCESS!
And I use “DB” command to view the memory,the memory is “D0 CF 11 E0…”!That’s the right data,that’s the data of the file!

OK!This is my question:
Why before I CallDown the IRP,the Irp->UserBuffer is invalid?
And After I CallDown the IRP,the IRP->UserBuffer is filled by the correct data?

And thanks for code,I just don’t know SEH.

I would assume its just not paged in yet as you cant page anything while
broken in with a debugger (all interrupts are masked off). You can
attempt to force the pagein however, provided your in the right process
context with “.pagein 0x05430000” and you should then be able to view
the buffer before calling down.

xxxxx@hotmail.com wrote:

I have observed the situation I described.
It is not because the App use invalid memory!

1.Before I calldown(IoCallDriver) the IRP ,I observed the Irp->UserBuffer is 0x05430000,and I use “DB” command to view the memory,the memory is “???”(that means the memory is invalid?).
2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is STATUS_SUCCESS!
And I use “DB” command to view the memory,the memory is “D0 CF 11 E0…”!That’s the right data,that’s the data of the file!

OK!This is my question:
Why before I CallDown the IRP,the Irp->UserBuffer is invalid?
And After I CallDown the IRP,the IRP->UserBuffer is filled by the correct data?

And thanks for code,I just don’t know SEH.


Questions? First check the IFS FAQ at https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@bugcheck.org
To unsubscribe send a blank email to xxxxx@lists.osr.com

Yes,Chris,you are right,thanks.
But,How can I do pagein in my code?
Please give me some hints or codes.

i assume he replied .pagein because you posted that you viewed your buffer
with DB
that implies you were using windbg
and .pagein (notice there is a dot in front) is a windbg extension command
that would pagein the buffer you are trying to view

i dont think he was asking you to do pagein in your code

On 4/23/07, xxxxx@hotmail.com wrote:
>
> Yes,Chris,you are right,thanks.
> But,How can I do pagein in my code?
> Please give me some hints or codes.
>
> —
> Questions? First check the IFS FAQ at
> https://www.osronline.com/article.cfm?id=17
>
> You are currently subscribed to ntfsd as: xxxxx@gmail.com
> To unsubscribe send a blank email to xxxxx@lists.osr.com
>

Since its a usermode address you can probe it in within a __try/__except
block safely. You should be able to just reference it but id recommend
using ProbeForRead() ahead of time to validate the buffer. In either
case if the buffer is invalid (and its has to be a usermode address
reference), it will raise an exception and will be caught with the
__except block.

xxxxx@hotmail.com wrote:

Yes,Chris,you are right,thanks.
But,How can I do pagein in my code?
Please give me some hints or codes.


Questions? First check the IFS FAQ at https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@bugcheck.org
To unsubscribe send a blank email to xxxxx@lists.osr.com

> block safely. You should be able to just reference it but id recommend

using ProbeForRead() ahead of time to validate the buffer.

This is a must, since otherwise the app can pass the kernel space pointer there
and junk the kernel itself.

ProbeForRead() also checks for kernel pointers.


Maxim Shatskih, Windows DDK MVP
StorageCraft Corporation
xxxxx@storagecraft.com
http://www.storagecraft.com

Excellent point. Thanks for clarifying. I suppose in my head the
secondary (unrelated point) I was attempting to make is try/except cant
catch kernel addresses but I ended up just being more confusing then
helpful and really was just wrong in the end. I have seen code
attempting to use try blocks to wrap kernel pointers before.

Maxim S. Shatskih wrote:

> block safely. You should be able to just reference it but id recommend
> using ProbeForRead() ahead of time to validate the buffer.
>

This is a must, since otherwise the app can pass the kernel space pointer there
and junk the kernel itself.

ProbeForRead() also checks for kernel pointers.

Oh,God,I have MmProbeAndLockPages,but still get a exception.
When I meet a non-paging IO,the Irp->MdlAddress is NULL,and according to the flag of the DO,I should take the Irp->UserBuffer.
I have described the case:

>1.Before I calldown(IoCallDriver) the IRP ,I observed the Irp->UserBuffer is
0x05430000,and I use “DB” command to view the memory,the memory is
“???”(that means the memory is invalid?).
>2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is STATUS_SUCCESS!
And I use “DB” command to view the memory,the memory is “D0 CF 11 E0…”!That’s the right data,that’s the data of the file!

OK,the following is my code for handling it:

__try
{
if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, nSize, FALSE, FALSE, NULL)))
{
nRet=STATUS_INSUFFICIENT_RESOURCES;
Irp->IoStatus.Status=nRet;
}
else
{
MmProbeAndLockPages(PtrMdl, Irp->RequestorMode, IoWriteAccess);
pData = MmGetSystemAddressForMdlSafe(PtrMdl, NormalPagePriority );
}
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
nRet=STATUS_INVALID_USER_BUFFER;
Irp->IoStatus.Status=nRet;
IoFreeMdl(PtrMdl);
}

But,when I call MmProbeAndLockPages,will throw the except.
What’s wrong with my code?I think it should work.
Thanks for your help~~~

> But,when I call MmProbeAndLockPages,will throw the except.

What’s wrong with my code?I think it should work.

Nothing wrong. MmProbeAndLockPages finds an invalid memory region and raise
the exception.


Slava Imameyev, xxxxx@hotmail.com

wrote in message news:xxxxx@ntfsd…
> Oh,God,I have MmProbeAndLockPages,but still get a exception.
> When I meet a non-paging IO,the Irp->MdlAddress is NULL,and according to
> the flag of the DO,I should take the Irp->UserBuffer.
> I have described the case:
>>>1.Before I calldown(IoCallDriver) the IRP ,I observed the Irp->UserBuffer
>>>is
> 0x05430000,and I use “DB” command to view the memory,the memory is
> “???”(that means the memory is invalid?).
>>>2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is
>>>STATUS_SUCCESS!
> And I use “DB” command to view the memory,the memory is “D0 CF 11
> E0…”!That’s the right data,that’s the data of the file!
>
> OK,the following is my code for handling it:
>
> __try
> {
> if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, nSize, FALSE, FALSE, NULL)))
> {
> nRet=STATUS_INSUFFICIENT_RESOURCES;
> Irp->IoStatus.Status=nRet;
> }
> else
> {
> MmProbeAndLockPages(PtrMdl, Irp->RequestorMode, IoWriteAccess);
> pData = MmGetSystemAddressForMdlSafe(PtrMdl, NormalPagePriority );
> }
> }
>__except(EXCEPTION_EXECUTE_HANDLER)
> {
> nRet=STATUS_INVALID_USER_BUFFER;
> Irp->IoStatus.Status=nRet;
> IoFreeMdl(PtrMdl);
> }
>
>
> But,when I call MmProbeAndLockPages,will throw the except.
> What’s wrong with my code?I think it should work.
> Thanks for your help~~~
>

MmProbeAndLockPages(PtrMdl, KernelMode, IoWriteAccess);
^^^^^^^^^^

???

wrote in message news:xxxxx@ntfsd…
> Oh,God,I have MmProbeAndLockPages,but still get a exception.
> When I meet a non-paging IO,the Irp->MdlAddress is NULL,and according to
> the flag of the DO,I should take the Irp->UserBuffer.
> I have described the case:
>>>1.Before I calldown(IoCallDriver) the IRP ,I observed the Irp->UserBuffer
>>>is
> 0x05430000,and I use “DB” command to view the memory,the memory is
> “???”(that means the memory is invalid?).
>>>2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is
>>>STATUS_SUCCESS!
> And I use “DB” command to view the memory,the memory is “D0 CF 11
> E0…”!That’s the right data,that’s the data of the file!
>
> OK,the following is my code for handling it:
>
> __try
> {
> if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, nSize, FALSE, FALSE, NULL)))
> {
> nRet=STATUS_INSUFFICIENT_RESOURCES;
> Irp->IoStatus.Status=nRet;
> }
> else
> {
> MmProbeAndLockPages(PtrMdl, Irp->RequestorMode, IoWriteAccess);
> pData = MmGetSystemAddressForMdlSafe(PtrMdl, NormalPagePriority );
> }
> }
>__except(EXCEPTION_EXECUTE_HANDLER)
> {
> nRet=STATUS_INVALID_USER_BUFFER;
> Irp->IoStatus.Status=nRet;
> IoFreeMdl(PtrMdl);
> }
>
>
> But,when I call MmProbeAndLockPages,will throw the except.
> What’s wrong with my code?I think it should work.
> Thanks for your help~~~
>

> MmProbeAndLockPages(PtrMdl, KernelMode, IoWriteAccess);

If access mode is UserMode then the address range is checked to be in user
space, if KernelMode the check is skipped.
So it is reasonable to use Irp->RequestorMode.

Also, for IRP_MJ_WRITE request the operation should be IoReadAccess and
IoWriteAccess for IRP_MJ_READ .

But this doesn’t solve the problem because I suppose the reason is an
invalid range.


Slava Imameyev, xxxxx@hotmail.com

“Lyndon J Clarke” wrote in message
news:xxxxx@ntfsd…
> MmProbeAndLockPages(PtrMdl, KernelMode, IoWriteAccess);
> ^^^^^^^^^^
>
> ???
>
> wrote in message news:xxxxx@ntfsd…
>> Oh,God,I have MmProbeAndLockPages,but still get a exception.
>> When I meet a non-paging IO,the Irp->MdlAddress is NULL,and according to
>> the flag of the DO,I should take the Irp->UserBuffer.
>> I have described the case:
>>>>1.Before I calldown(IoCallDriver) the IRP ,I observed the
>>>>Irp->UserBuffer is
>> 0x05430000,and I use “DB” command to view the memory,the memory is
>> “???”(that means the memory is invalid?).
>>>>2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is
>>>>STATUS_SUCCESS!
>> And I use “DB” command to view the memory,the memory is “D0 CF 11
>> E0…”!That’s the right data,that’s the data of the file!
>>
>> OK,the following is my code for handling it:
>>
>> __try
>> {
>> if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, nSize, FALSE, FALSE,
>> NULL)))
>> {
>> nRet=STATUS_INSUFFICIENT_RESOURCES;
>> Irp->IoStatus.Status=nRet;
>> }
>> else
>> {
>> MmProbeAndLockPages(PtrMdl, Irp->RequestorMode, IoWriteAccess);
>> pData = MmGetSystemAddressForMdlSafe(PtrMdl, NormalPagePriority );
>> }
>> }
>>__except(EXCEPTION_EXECUTE_HANDLER)
>> {
>> nRet=STATUS_INVALID_USER_BUFFER;
>> Irp->IoStatus.Status=nRet;
>> IoFreeMdl(PtrMdl);
>> }
>>
>>
>> But,when I call MmProbeAndLockPages,will throw the except.
>> What’s wrong with my code?I think it should work.
>> Thanks for your help~~~
>>
>
>
>

Fair comment, agreed, IIRC Irp->RequestorMode is exact as FatLockUserBuffer
:slight_smile:

“Slava Imameyev” wrote in message news:xxxxx@ntfsd…
>> MmProbeAndLockPages(PtrMdl, KernelMode, IoWriteAccess);
>
> If access mode is UserMode then the address range is checked to be in user
> space, if KernelMode the check is skipped.
> So it is reasonable to use Irp->RequestorMode.
>
> Also, for IRP_MJ_WRITE request the operation should be IoReadAccess and
> IoWriteAccess for IRP_MJ_READ .
>
> But this doesn’t solve the problem because I suppose the reason is an
> invalid range.
>
> –
> Slava Imameyev, xxxxx@hotmail.com
>
>
> “Lyndon J Clarke” wrote in message
> news:xxxxx@ntfsd…
>> MmProbeAndLockPages(PtrMdl, KernelMode, IoWriteAccess);
>> ^^^^^^^^^^
>>
>> ???
>>
>> wrote in message news:xxxxx@ntfsd…
>>> Oh,God,I have MmProbeAndLockPages,but still get a exception.
>>> When I meet a non-paging IO,the Irp->MdlAddress is NULL,and according to
>>> the flag of the DO,I should take the Irp->UserBuffer.
>>> I have described the case:
>>>>>1.Before I calldown(IoCallDriver) the IRP ,I observed the
>>>>>Irp->UserBuffer is
>>> 0x05430000,and I use “DB” command to view the memory,the memory is
>>> “???”(that means the memory is invalid?).
>>>>>2.I calldown(IoCallDriver) the IRP,the returned NTSTATUS is
>>>>>STATUS_SUCCESS!
>>> And I use “DB” command to view the memory,the memory is “D0 CF 11
>>> E0…”!That’s the right data,that’s the data of the file!
>>>
>>> OK,the following is my code for handling it:
>>>
>>> __try
>>> {
>>> if (!(PtrMdl = IoAllocateMdl(Irp->UserBuffer, nSize, FALSE, FALSE,
>>> NULL)))
>>> {
>>> nRet=STATUS_INSUFFICIENT_RESOURCES;
>>> Irp->IoStatus.Status=nRet;
>>> }
>>> else
>>> {
>>> MmProbeAndLockPages(PtrMdl, Irp->RequestorMode, IoWriteAccess);
>>> pData = MmGetSystemAddressForMdlSafe(PtrMdl, NormalPagePriority );
>>> }
>>> }
>>>__except(EXCEPTION_EXECUTE_HANDLER)
>>> {
>>> nRet=STATUS_INVALID_USER_BUFFER;
>>> Irp->IoStatus.Status=nRet;
>>> IoFreeMdl(PtrMdl);
>>> }
>>>
>>>
>>> But,when I call MmProbeAndLockPages,will throw the except.
>>> What’s wrong with my code?I think it should work.
>>> Thanks for your help~~~
>>>
>>
>>
>>
>
>
>