Mapping to user space read only

I know I am one of the people who does not like mapping to user space, but
some times you have to do it. I am wondering if anyone has figured out a
safe approach to doing the mapping such that the region is read only? I’ve
looked at VirtualProtect and ZwProtectVirtualMemory but while I think they
would work, they still leave a security hole. So has anyone come up with
any approaches to this problem?


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

__________ Information from ESET NOD32 Antivirus, version of virus signature database 4458 (20090925) __________

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

Don,

I’ve looked at VirtualProtect and ZwProtectVirtualMemory but while I think they would work, they
still leave a security hole.

What about a section? You can create a dummy disk file of preallocated size of N bytes and open a handle to it with FILE_SHARE_READ access to it. If you do it this way, UM apps will be able to map it into their address spaces but only for RO access. After having mapped this file into memory and app will send you an IOCTL with the address of this mapping. Your driver will build an MDL for this buffer, probe and lock it, and map it into the kernel address space for RW access so that it will be able to write to it (it is understandable that as long as MDL is mapped into the kernel space all subsequent requests from other apps will be a simple no-op).

Actually I don’t know how the system will react to a request of probing and locking a buffer that is backed up not by a pagefile but by a mapped one (particularly the one mapped for RO access), but it could be a good fun just to try it and see what happens …

Anton Bassov

Anton,

Clever idea but I cannot do it for my environment. I need to have the
backing memory contiguous for the hardware behind it, and I sure cannot do
that with a “pseudo file” unless I create a ton of infastructure. Worse
yet I can have N of these, so it gets complex fast.

Don

wrote in message news:xxxxx@ntdev…
>
>
> Don,
>
>> I’ve looked at VirtualProtect and ZwProtectVirtualMemory but while I
>> think they would work, they
>> still leave a security hole.
>
> What about a section? You can create a dummy disk file of preallocated
> size of N bytes and open a handle to it with FILE_SHARE_READ access to it.
> If you do it this way, UM apps will be able to map it into their address
> spaces but only for RO access. After having mapped this file into memory
> and app will send you an IOCTL with the address of this mapping. Your
> driver will build an MDL for this buffer, probe and lock it, and map it
> into the kernel address space for RW access so that it will be able to
> write to it (it is understandable that as long as MDL is mapped into the
> kernel space all subsequent requests from other apps will be a simple
> no-op).
>
> Actually I don’t know how the system will react to a request of probing
> and locking a buffer that is backed up not by a pagefile but by a mapped
> one (particularly the one mapped for RO access), but it could be a good
> fun just to try it and see what happens …
>
>
> Anton Bassov
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4458 (20090925)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4458 (20090925)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

>I know I am one of the people who does not like mapping to user space, but

some times you have to do it. I am wondering if anyone has figured out a
safe approach to doing the mapping such that the region is read only? I’ve
looked at VirtualProtect and ZwProtectVirtualMemory but while I think they
would work, they still leave a security hole. So has anyone come up with
any approaches to this problem?

Are you mapping the pages using MmMapLockedPages(UserMode)? There is
currently no way to make these mappings read-only.

(I think VirtualProtect/NtProtectVirtualMemory would fail for a VAD created
by MmMapLockedPages, and even if it worked there would still be a security
hole as you said).


Pavel Lebedinsky/Windows Kernel Test
This posting is provided “AS IS” with no warranties, and confers no rights.

> I need to have the backing memory contiguous for the hardware behind it,

This one, indeed, seems to be a serious complication…

and I sure cannot do that with a “pseudo file”

This is for sure. It is understandable that MM will use scattered pages for backing up a mapped section

Worse yet I can have N of these, so it gets complex fast.

Well, this is not really a problem - you could have created a pseudo-file for each mapping. Then an application would get the file name from a driver with IOCTL A, map it to its address space and send the mapped address to a driver with IOCTL B.

The major showstopper here is the requirement of physically contiguous range. I don’t think you can
do anything about it in any “official” way, and messing around with PTEs is a plain non-brainer - just consider what happens if an app unmaps a file.

I don’t want to start yet another flame war, but your particular situation is a classical demonstration of how
lack of VFS under Windows results in major complications in a situation that is fairly simple in itself.
If Windows supported memory mapping of device files and allowed driver to register their mmap() and page fault handlers the whole thing would be pretty effortless…

Anton Bassov

Pavel,

I am using MmMapLockedPagesSpecifyCache and the standard approach OSR
and others have documented. As I said in the message quoted below, I am not
a fan of this but there are reasons at times to do it. Here is a case
where I wish Microsoft provided a way to do the protection, since it would
provide a better and safer environment.


Don Burn (MVP, Windows DKD)
Windows Filesystem and Driver Consulting
Website: http://www.windrvr.com
Blog: http://msmvps.com/blogs/WinDrvr

“Pavel Lebedinsky” wrote in message
news:xxxxx@ntdev…
> >I know I am one of the people who does not like mapping to user space,
> >but some times you have to do it. I am wondering if anyone has figured
> >out a safe approach to doing the mapping such that the region is read
> >only? I’ve looked at VirtualProtect and ZwProtectVirtualMemory but while
> >I think they would work, they still leave a security hole. So has
> >anyone come up with any approaches to this problem?
>
> Are you mapping the pages using MmMapLockedPages(UserMode)? There is
> currently no way to make these mappings read-only.
>
> (I think VirtualProtect/NtProtectVirtualMemory would fail for a VAD
> created
> by MmMapLockedPages, and even if it worked there would still be a security
> hole as you said).
>
> –
> Pavel Lebedinsky/Windows Kernel Test
> This posting is provided “AS IS” with no warranties, and confers no
> rights.
>
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4458 (20090925)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4458 (20090925)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

> Actually I don’t know how the system will react to a request of probing and locking a buffer that is

backed up not by a pagefile but by a mapped one (particularly the one mapped for RO access),

Will work. Calling WriteFile on a region from read-only mmaped file is OK.


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

> Calling WriteFile on a region from read-only mmaped file is OK.

…which is not what my concern is about. Under Windows (at least before win7) you cannot immediately detect everyone who maps a given page into its address space unless we speak about a private region. Now consider what happens if you build MDL that is meant to be subsequently used in scatter-gather DMA transfer - at any particular moment pages in this MDL have to be accessible either by CPU or by device but not by both at the same time. Therefore, before you can start a transfer the system has to ensure that target memory is not accessible to the CPU, and in order to do so it has to mark the target page as non-present in in all PTEs that map it . Once it is unable to detect all PTEs that may map a given page into the user space of different processes, it may take a preemptive step and just refuse building MDL for a mapped range “just in case”…

Anton Bassov

On Sun, Sep 27, 2009 at 8:51 AM, wrote:
>> Calling WriteFile on a region from read-only mmaped file is OK.
>
>
> …which is not what my concern is about. Under Windows (at least before win7) you cannot immediately detect everyone who maps a given page into its address space unless we speak about a private region. Now consider what happens if you build MDL that is meant to be subsequently used in scatter-gather DMA transfer - at any particular moment pages in this MDL have to be accessible either by CPU or by device but not by both at the same time. Therefore, before you can start a transfer the system has to ensure that target memory is not accessible to the CPU,

Hmmm … I don’t believe your statement that ‘the system has to ensure
that target memory is not accessible to the CPU’ is true. As far as I
know the OS makes no such effort. Processors are free to scribble all
over memory that is the target of an ongoing DMA operation. Coherence
is a matter of application correctness not OS action.

Mark Roddy

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

wrote in message news:xxxxx@ntdev…
>> Calling WriteFile on a region from read-only mmaped file is OK.
>
>
> …which is not what my concern is about. Under Windows (at least before
> win7) you cannot immediately detect everyone who maps a given page into
> its address space unless we speak about a private region. Now consider
> what happens if you build MDL that is meant to be subsequently used in
> scatter-gather DMA transfer - at any particular moment pages in this MDL
> have to be accessible either by CPU or by device but not by both at the
> same time. Therefore, before you can start a transfer the system has to
> ensure that target memory is not accessible to the CPU, and in order to do
> so it has to mark the target page as non-present in in all PTEs that map
> it . Once it is unable to detect all PTEs that may map a given page into
> the user space of different processes, it may take a preemptive step and
> just refuse building MDL for a mapped range “just in case”…
>
> Anton Bassov

SG DMA by itself does not preclude CPU access to the memory.
Rather, the app developer just by the “common sense” won’t touch this
memory until the DMA completes. Otherwise it would be garbage in - garbage
out.
Also, the memory unit affected by DMA is not a page, it is the cache line
size.
(at least, without MMU, but as Jake O. wrote, no public Windows version
supports MMU yet ).

–pa

How about you create a read-only memory mapping object (ZwCreateSection) on \Device\PhysicalMemory and map it to the app space?

> I don’t believe your statement that 'the system has to ensure that target memory is not accessible

to the CPU’ is true.As far as I know the OS makes no such effort. Processors are free to scribble
all over memory that is the target of an ongoing DMA operation.

…pretty much the same way thread X is free to modify a variable while thread Y tries to do the same.

Coherence is a matter of application correctness not OS action.

But the OS must provide some facilities for it, because apps and drivers are just unable to do it on their own without the OS’s assistance. In our particular situation the OS has either to temporribly make pages unaccessible to the CPU (something that Windows does not and cannot do because it does not know who maps them into their address spaces) , or refuse to lock MDL unless the target buffer is owned by a requesting process, or whatever it chooses to do - otherwise WriteFile() call on “C:/xxx.Mydiskfile” made by a process X may screw up DMA requested by DeviceIoControl() call made by process Y on the “////.//Mydevice” …

Anton Bassov

> How about you create a read-only memory mapping object (ZwCreateSection)

on \Device\PhysicalMemory and map it to the app space?

IIRC, starting from W2K3 SP2 UM apps cannot open \Device\PhysicalMemory for any access regardless of account privileges. Therefore, it is not going to work on modern systems…

Anton Bassov

For any future person searching the archives for answers about DMA:

Please ignore Anton “Soviet Bloke” Bassov. He frequently writes in ways
that can seem authoritative without actual information to back up what he
writes.


Jake Oshins
Hyper-V I/O Architect
Windows Kernel Group

This post implies no warranties and confers no rights.


wrote in message news:xxxxx@ntdev…
>> I don’t believe your statement that ‘the system has to ensure that target
>> memory is not accessible
>>to the CPU’ is true.As far as I know the OS makes no such effort.
>>Processors are free to scribble
>> all over memory that is the target of an ongoing DMA operation.
>
> …pretty much the same way thread X is free to modify a variable while
> thread Y tries to do the same.
>
>> Coherence is a matter of application correctness not OS action.
>
> But the OS must provide some facilities for it, because apps and drivers
> are just unable to do it on their own without the OS’s assistance. In our
> particular situation the OS has either to temporribly make pages
> unaccessible to the CPU (something that Windows does not and cannot do
> because it does not know who maps them into their address spaces) , or
> refuse to lock MDL unless the target buffer is owned by a requesting
> process, or whatever it chooses to do - otherwise WriteFile() call on
> “C:/xxx.Mydiskfile” made by a process X may screw up DMA requested by
> DeviceIoControl() call made by process Y on the “////.//Mydevice” …
>
>
> Anton Bassov
>

Anton,

AFAIK you are correct, my target systems are Windows Server 2008 and
Windows Server 2008 R2 64-bit in both cases, so I don’t think that will
work. It does beg the question, has anyone created a section object on a
raw device? I could potentially change my driver stack so that the
read-only case is administered this way.

Don

wrote in message news:xxxxx@ntdev…
>> How about you create a read-only memory mapping object (ZwCreateSection)
>>on \Device\PhysicalMemory and map it to the app space?
>
> IIRC, starting from W2K3 SP2 UM apps cannot open \Device\PhysicalMemory
> for any access regardless of account privileges. Therefore, it is not
> going to work on modern systems…
>
> Anton Bassov
>
>
> Information from ESET NOD32 Antivirus, version of virus
> signature database 4462 (20090927)

>
> The message was checked by ESET NOD32 Antivirus.
>
> http://www.eset.com
>
>
>

Information from ESET NOD32 Antivirus, version of virus signature database 4462 (20090927)

The message was checked by ESET NOD32 Antivirus.

http://www.eset.com

> Please ignore Anton “Soviet Bloke” Bassov. He frequently writes in ways that can seem

authoritative without actual information to back up what he writes.

Where is anything even remotely “authoritative” in my statements here??? I am just discussing my thoughts about possible complications of the approach that I had suggested myself, without saying anything definitively - as I said earlier, “it would be a fun to try it and see what happens”, again, without saying anything definitively…

In other words, this is just yet another pointless and unmotivated personal attack. What is the point you are trying to make here???

Anton Bassov

>by CPU or by device but not by both at the same time. Therefore, before you can start a transfer the

system has to ensure that target memory is not accessible to the CPU, and in order to do so it has to
mark the target page as non-present in in all PTEs that map it .

Absolutely no, DMA does not even bother doing these strange things.


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

> Absolutely no, DMA does not even bother doing these strange things.

Normally it just does not have to do it because it is target app’s/device’s responsibility to ensure that it not access the target range while DMA is in progress. However, please note that I was speaking about a very special case of a mapped section that may be accessed by different processes and by different means at the same time (i.e. Write File() on cached disk file combined with DMA requested by IOCTL to device file) transparently to one another…

Anton Bassov

I mean, the actual section creation and mapping (to user app space) will be done by the kernel mode driver, so \Device\PhysicalMemory is accessible in this case.

"Normally it just does not have to do it "

Which kernel component is this ‘it’ and what and when does it perform
this strange thing?

Mark Roddy

On Sun, Sep 27, 2009 at 2:15 PM, wrote:
>> Absolutely no, DMA does not even bother doing these strange things.
>
> Normally it just does not have to do it because it is target app’s/device’s responsibility to ensure that it not access the target range while DMA is in progress. However, ?please note that I was speaking about a very special case of a mapped section that may be accessed by different processes and ?by ?different means at the same time (i.e. Write File() on cached disk file combined with DMA requested by IOCTL to device file) transparently to one another…
>
> 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
>