Security: Handing a Kernel Buffer to Usermode

Peter Viscarola, one of the Cadre of Bright Guys and Gals that work at OSR, posted a note on NTDEV this week that i think bears repeating and explaining a bit, related to a subtle driver security point.

The note that prompted the response had the following code in it:

deviceExtension->VirtualAddress = ExAllocatePool(PagedPool, NumberOfBytes);
if (deviceExtension->VirtualAddress) {
   deviceExtension->Mdl = IoAllocateMdl(deviceExtension->VirtualAddress, NumberOfBytes, FALSE, FALSE, NULL);
   MmProbeAndLockPages(deviceExtension->Mdl, KernelMode, IoModifyAccess);  
   ...
}

The driver eventually wound up mapping deviceExtension->VirtualAddress into a usermode address and returning it to an application. Peter mentioned that there is a security flaw in this architecture, and when asked, explained it as follows:

It is possible for a malicious application to clone your address space, thus  getting a pointer into pool.  
That's all well and good... until the orignal app exits, and your driver returns the block of pool.  At which 
time the malicious app would have access to pool that's being used for ... anything ... perhaps for system 
purposes.

I admit that I had never thought of this, perhaps in part because I never give apps direct access to pool. There are a number of problems with this design, including problems associated with process context — see previous Kernel Mustard articles for more detals on this.

But the scarier part is the security problem. The rest of this may just be bad architecture, but there aren’t many things much worse than a security flaw, especially one that gives the user access to kernel memory. A good rule of thumb is to NEVER map kernel-mode pages into usermode addresses for any reason. This should be an architectural red flag! Far better would be to let the kernel map user space into kernel space for you, using ReadFile/WriteFile or IOCTL with METHOD_IN/OUT_DIRECT.

Peter continues:

You really might want to re-think the whole idea of mapping POOL into  an application's address space.  
This approach can open a complex security loophole that can endanger the system.  I'd recommend allocating 
memory in a section, and using that.  This isn't entirely free of potential problems, but it's better.

The whole architecture sounds suspect to me, and as I said above, I’d just fix the design to not require kernel-mode mapping of memory that gets handed to the user. The kernel itself is the only software that should perform this task, because it has all of the necessary checks to ensure system security.

Thanks to Peter for the excellent point. Now, for 10 Brownie Points, who can explain what problems he was talking about with regard to the section object solution?

Leave a Reply

Your email address will not be published. Required fields are marked *