Geeks With Blogs
Kate Moss' Open Space

 

Consider the following code piece, it may look fine at the first glance but could pop out access violation under stress test

In the user mode applicatio



BYTE buffer[ 256 ]; // On stack
DWORD read;

while (<condition>) {

 if (ReadFile(hDriver, buffer, sizeof(buffer), &read, NULL) && (read > 0)){

   // Do something

 }

}

And inside the kernel mode driver:

 

ULONG
DRV_Read(
 HANDLE hOpen, //@parm [IN]  HANDLE returned by XXX_Open 
 PUCHAR pBuffer, //@parm [IN,OUT] Pointer to valid memory.  
 ULONG Count) //@parm [IN]  Size in bytes of pTargetBuffer.
{

  < Input params validation>

  // Read the data whatever available in the internal receive buffer
  // Occasionally, Data Abort happened at the following line
  *pBuffer = READ_REGISTER_UCHAR (DATA_PORT_ADDR);

  <etc>
}

So what's going on here?
Firstly, we must understand user mode stack is demand committed and since we allocate a relative large pool (256 bytes, compare the the page size, 4KB), there is a good chance the buffer may cross the page boundary. i.e. part or all of the memory for buffer is not yet committed.
As the driver is in kernel mode but the buffer address still in user mode, so when accessing this address, a page fault will be generated.
Normally, kernel can recover the stack page fault gracefully, but committing a user stack (untrusted stack) in kernel mode is likely to expose more risk, so kernel just fails it and let the access violation (data abort) happened naturally!

OK, so how do we fix it?
Since the data abort is due to uncommitted page in stack, a simple workaround is to foce page in the stack before pass to driver, for example

buffer[0] = 0;
if (ReadFile(hDriver, buffer, sizeof(buffer), &read, NULL) && (read > 0))
...

Assign data to start of buffer will force kernel to resolve the potential page fault and commit the page when needed. 
Apparently, it looks hacky and we should seek a solution to commit the page in driver.
And here is the answer,
LockPages.
Use LockPages to lock the buffer when entering the driver handlers, such as XXX_Read, and UnlockPages it before return to commit the user buffer in driver explicitly.

 

Posted on Saturday, July 9, 2011 6:21 PM | Back to top


Comments on this post: Passing a Buffer in User Mode Stack to Drivers

No comments posted yet.
Your comment:
 (will show your gravatar)


Copyright © Kate Moss' Open Space | Powered by: GeeksWithBlogs.net