Mapping kernel virtual address in user space

Hello,

My WDK kernel driver allocates a continuous physical RAM buffer using AllocateCommonBuffer.

The return value of AllocateCommonBuffer is the virtual address allocated.

How can I map this address from user space so I can access this buffer ?

Thanks,
Zvika

> How can I map this address from user space so I can access this buffer ?

The idea in itself is really bad in the Windows world for the security reasons, although all OSes that support mmap() do exactly that without any security implications. If you are just desperate to do it, MmMapLockedPagesSpecifyCache routine() is your friend (certainly you have to build MDL that describes your physical pages first)…

Anton Bassov

Zvi Vered wrote:

Hello,

My WDK kernel driver allocates a continuous physical RAM buffer using
AllocateCommonBuffer.

The return value of AllocateCommonBuffer is the virtual address allocated.

How can I map this address from user space so I can access this buffer ?

IoAllocateMdl, MmBuildMdlForNonPagedPool, and MmMapLockedPagesSpecifyCache.


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

First why do you want to do this? Is your device insanely fast so you
need to not have an additional copy? Tell us how many MB/sec you are
looking for. Mapping the buffer is a potential security hole so let us
know why you need it.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Zvi Vered” wrote in message news:xxxxx@ntdev:

> Hello,
>
> My WDK kernel driver allocates a continuous physical RAM buffer using AllocateCommonBuffer.
>
> The return value of AllocateCommonBuffer is the virtual address allocated.
>
> How can I map this address from user space so I can access this buffer ?
>
> Thanks,
> Zvika

Remember this is the guy that felt it was important to use
AllocateCommonBuffer to get a 1-page contiguous buffer. I think he really
doesn’t understand how any of this works. For one page, there is no
serious penalty for a copy. Probably has a DMA card designed by an
amateur. A prime example, though, that the question he asked is not the
question he needs answered.
joe

First why do you want to do this? Is your device insanely fast so you
need to not have an additional copy? Tell us how many MB/sec you are
looking for. Mapping the buffer is a potential security hole so let us
know why you need it.

Don Burn
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Zvi Vered” wrote in message news:xxxxx@ntdev:
>
>> Hello,
>>
>> My WDK kernel driver allocates a continuous physical RAM buffer using
>> AllocateCommonBuffer.
>>
>> The return value of AllocateCommonBuffer is the virtual address
>> allocated.
>>
>> How can I map this address from user space so I can access this buffer ?
>>
>> Thanks,
>> Zvika
>
>
> —
> 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
>

Also, you NEED TO MAKE SURE THE BUFFER IS UNMAPPED WHEN THE PROCESS EXITS.

If you don’t do that, welcome to a lovely bugcheck.

It’s not that simple, though. The best way to do that is to link the buffer with a pended IOCTL issued by the process. But if you think about that, a DIRECT buffer mapped to the kernel space provides as good shared memory, and much simpler to implement.

Hello,

I’m aware that mappinc a kernel space buffer to user space is a security
hole.

This is done for 2 reasons:

  1. The WDK driver is a rewrite of an old WDM driver written 10 years ago. I
    have to keep the same functionality.

  2. The FPGA gets data at ~300MB/sec (theoretical rate: 3.125Gb/sec) and
    writes it to physical buffer pre-allocated by AllocateCommonBuffer.

FPGA only gets the start address of this buffer and then increments the
address according to the size it received.

User space application has to read the data (Each time 4MB) and save it
do disk.

This is why we chose not to copy data from kerenl by reading it and then
saving to disk.

Mr. Roberts advised using:
IoAllocateMdl, MmBuildMdlForNonPagedPool, and MmMapLockedPagesSpecifyCache.

Should MmMapLockedPagesSpecifyCache called upon IOCTL request from the
driver ?

The first parameter for IoAllocateMdl is virtual address. Is it the return
value of AllocateCommonBuffer ?

Thanks,
Zvika.

----- Original Message -----
From: “Don Burn”
Newsgroups: ntdev
To: “Windows System Software Devs Interest List”
Sent: Tuesday, October 04, 2011 22:38
Subject: Re:[ntdev] Mapping kernel virtual address in user space

> First why do you want to do this? Is your device insanely fast so you
> need to not have an additional copy? Tell us how many MB/sec you are
> looking for. Mapping the buffer is a potential security hole so let us
> know why you need it.
>
>
> Don Burn
> Windows Filesystem and Driver Consulting
> Website: http://www.windrvr.com
> Blog: http://msmvps.com/blogs/WinDrvr
>
>
>
>
> “Zvi Vered” wrote in message news:xxxxx@ntdev:
>
>> Hello,
>>
>> My WDK kernel driver allocates a continuous physical RAM buffer using
>> AllocateCommonBuffer.
>>
>> The return value of AllocateCommonBuffer is the virtual address
>> allocated.
>>
>> How can I map this address from user space so I can access this buffer ?
>>
>> Thanks,
>> Zvika
>
>
> —
> 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

> Also, you NEED TO MAKE SURE THE BUFFER IS UNMAPPED WHEN THE PROCESS EXITS.

If you don’t do that, welcome to a lovely bugcheck.

???

The OP got a pointer to the buffer (as it is known in the KM portion of address space) as a return value of
AllocateCommonBuffer() , so that he will access this buffer from his driver.Why on Earth should he bugcheck when the process exits???You seem to assume that driver will access the target buffer by the address that is known in the userland, but this is very unlikely to be the case - then he would have to do it only in context of the target process…

Anton Bassov

> Remember this is the guy that felt it was important to use AllocateCommonBuffer to get a 1-page

contiguous buffer. I think he really doesn’t understand how any of this works. For one page,
there is no serious penalty for a copy. Probably has a DMA card designed by an amateur.
A prime example, though, that the question he asked is not the question he needs answered

Mr. Newcomer is, certainly, positive and optimistic, as usual…

Anton Bassov

>> Also, you NEED TO MAKE SURE THE BUFFER IS UNMAPPED WHEN THE PROCESS EXITS.

> If you don’t do that, welcome to a lovely bugcheck.

???

Was talking about mapping to the user process…

wrote in message news:xxxxx@ntdev…

>Why on Earth should he bugcheck when the process exits???You seem to assume
>that driver will access the target buffer by the address that is known in
>the userland, but this is very unlikely to be the case - then he would have
>to do it only in context of the target process…

You should realize the OS cannot do the bookkeeping for you and unmap the
pages from the process automatically.According to you it should remove the
mapping automatically on process termination, right ? In your scenario of
course the driver might continue to use the user VA, that is not unlikely at
all. The driver has to know the mapping does not exist, otherwise bugcheck,
right ?

Then at a certain point the driver might get unloaded and the driver
destroys its buffer. Then what, should the OS just take the mapped pages
out from under the process which might (or not) be still alive ? How does
the driver know the mapping still exists or not ? Or you wanted also OS
support for unmapping pages that are no longer mapped anyway ? Then noone
can tell if an unmapping succeeded or not, thus creating a mess with an
entire new class of bugs.

Fortunately we get a PROCESS_HAS_LOCKED_PAGES or
DRIVER_LEFT_LOCKED_PAGES_IN_PROCESS in time.

Regards,

Daniel Terhell
Resplendence Software Projects Sp
xxxxx@resplendence.com
http://www.resplendence.com

wrote in message news:xxxxx@ntdev…
> The OP got a pointer to the buffer (as it is known in the KM portion of
> address space) as a return value of
> AllocateCommonBuffer() , so that he will access this buffer from his
> driver.Why on Earth should he bugcheck when the process exits???You seem
> to assume that driver will access the target buffer by the address that is
> known in the userland, but this is very unlikely to be the case - then he
> would have to do it only in context of the target process…
>

Sorry, some of my arguments do not hold because the unmapping should always
take place in the context of the user process anyway so there would be no
way the driver could unmap without the process being alive. Still, for the
logic of operations in many cases it is essential for the driver to know if
the memory is still shared or not and drivers need to be notified about the
process and the mapping going away so a bugcheck is welcome.

Daniel Terhell
Resplendence Software Projects Sp
xxxxx@resplendence.com
http://www.resplendence.com

I presume he’s referring to the “process exited with locked pages” bugcheck.

Sent from my Windows Phone


From: xxxxx@hotmail.com
Sent: 10/5/2011 6:01 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] Mapping kernel virtual address in user space

Also, you NEED TO MAKE SURE THE BUFFER IS UNMAPPED WHEN THE PROCESS EXITS.
If you don’t do that, welcome to a lovely bugcheck.

???

The OP got a pointer to the buffer (as it is known in the KM portion of address space) as a return value of
AllocateCommonBuffer() , so that he will access this buffer from his driver.Why on Earth should he bugcheck when the process exits???You seem to assume that driver will access the target buffer by the address that is known in the userland, but this is very unlikely to be the case - then he would have to do it only in context of the target process…

Anton Bassov


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

Much good advice here, but I don’t think anybody actually HELPED the OP by explaining to him that the place to do the unmap operation is in his driver’s handling of IRP_MJ_CLEANUP.

So, OP: Application opens a handle to your driver, in response to an IOCTL from the user app and operating in the context of the requesting process you do the mapping as explained by the always helpful Mr. Roberts (using MmMapLockedPagesSpecifyCache – I don’t recommend mapping non-paged pool specifically into the user’s address space… that’s bad … but rather allocate a separate chunk of memory and map THAT into both Kernel Virtual address space and the user’s virtual address space) returning the mapped address as a result of that IOCTL. When the user closes the handle (or the thread exits) you’ll get an IRP_MJ_CLEANUP… THAT’s the time to unmap the block of memory.

We’ve discussed this here on NTDEV a thousand times. You can search the archives, and you can also refer to this article which gives you a WDM-based example of what you need to do… the original article was written several years back, but what updates in January of this year:

http://www.osronline.com/article.cfm?id=39

P

Dear Peter,

Thank you for your help !

Best regards,
Zvika

----- Original Message -----
From:
To: “Windows System Software Devs Interest List”
Sent: Wednesday, October 05, 2011 18:44
Subject: RE:[ntdev] Mapping kernel virtual address in user space

> Much good advice here, but I don’t think anybody actually HELPED the OP by
> explaining to him that the place to do the unmap operation is in his
> driver’s handling of IRP_MJ_CLEANUP.
>
> So, OP: Application opens a handle to your driver, in response to an IOCTL
> from the user app and operating in the context of the requesting process
> you do the mapping as explained by the always helpful Mr. Roberts (using
> MmMapLockedPagesSpecifyCache – I don’t recommend mapping non-paged pool
> specifically into the user’s address space… that’s bad … but rather
> allocate a separate chunk of memory and map THAT into both Kernel Virtual
> address space and the user’s virtual address space) returning the mapped
> address as a result of that IOCTL. When the user closes the handle (or
> the thread exits) you’ll get an IRP_MJ_CLEANUP… THAT’s the time to unmap
> the block of memory.
>
> We’ve discussed this here on NTDEV a thousand times. You can search the
> archives, and you can also refer to this article which gives you a
> WDM-based example of what you need to do… the original article was
> written several years back, but what updates in January of this year:
>
> http://www.osronline.com/article.cfm?id=39
>
> P
>
> —
> 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 I don’t think anybody actually HELPED the OP by
explaining to him that the place to do the unmap operation is in his driver’s
handling of IRP_MJ_CLEANUP.”

Unfortunately, this may not be the right place. Suppose the device handle got inherited by virtue of calling CreateProcess (or duplicated into another process otherwise), and then the original process exits. IRP_MJ_CLEANUP is not called yet.

The only reliable guaranteed approach to clean the mapping is to tie it with a pended IRP. When the IRP is completed due to cancel request or intentionally, undo the mapping.

> You should realize the OS cannot do the bookkeeping for you and unmap the pages from

the process automatically.According to you it should remove the mapping automatically
on process termination, right ? In your scenario of course the driver might continue to use the user VA,
that is not unlikely at all. The driver has to know the mapping does not exist, otherwise bugcheck, right ?

Actually, I don’t know how all the above may be possibly related to my post …

Look - the driver has a kernel address of the buffer target buffer (it got returned by AllocateCommonBuffer()), and, as long as this address is valid, the driver can access it without having to worry about bugchecks. The validity of this address has absolutely nothing to do with a UM mapping that happens to refer to the same physical pages…

Then at a certain point the driver might get unloaded and the driver destroys its buffer.
Then what, should the OS just take the mapped pages out from under the process which might
(or not) be still alive ? How does the driver know the mapping still exists or not ? Or you wanted
also OS support for unmapping pages that are no longer mapped anyway ? Then noone can
tell if an unmapping succeeded or not, thus creating a mess with an entire new class of bugs.

Actually, you did a good job of explaining to the OP why mapping a driver-allocated memory to
the userland is a bad idea under Windows. However, it is still unrelated to my post - I don’t understand what you are arguing about…

Sorry, some of my arguments do not hold because the unmapping should always take place
in the context of the user process anyway so there would be no way the driver could unmap
without the process being alive.

Goo that you understood it yourself …

Anton Bassov

@Anton:

Bug Check 0x76: PROCESS_HAS_LOCKED_PAGES

You’ll see it if the client process exits while the driver forgot to unmap the pages.

That sounds a lot like DO_DIRECT_IO or METHOD_[IN,OUT]_DIRECT, so the real
question why are the not adequate?
joe

“but I don’t think anybody actually HELPED the OP by
explaining to him that the place to do the unmap operation is in his
driver’s
handling of IRP_MJ_CLEANUP.”

Unfortunately, this may not be the right place. Suppose the device handle
got inherited by virtue of calling CreateProcess (or duplicated into
another process otherwise), and then the original process exits.
IRP_MJ_CLEANUP is not called yet.

The only reliable guaranteed approach to clean the mapping is to tie it
with a pended IRP. When the IRP is completed due to cancel request or
intentionally, undo the mapping.


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

“That sounds a lot like DO_DIRECT_IO or METHOD_[IN,OUT]_DIRECT, so the real
question why are the not adequate?”

The OP needs to support a half-assed FPGA that can’s do Scatter/Gather and needs a VERY big contiguous buffer, and needs to transfer 300 MB/s from that buffer to disk.