MmSecureVirtualMemory returns NULL

Hi,

I have a driver that accepts user-mode pointers. These pointers are first secured (via MmSecureVirtualMemory) before being used further on (see code below).
Everything works fine, until I use more than 1 thread in the user application.
MmSecureVirtualMemory starts returning NULL (no exceptions are raised).
What could be the reason for returning NULL?

Thanks,
Kurt

__try
{
SecuredAddress=MmSecureVirtualMemory(Address, Size, PAGE_READWRITE);
}
__except(EXCEPTION_EXECUTE_HANDLER) //catch all exceptions
{
KdPrint((“MmSecureVirtualMemory failed for 0x%08X.\n”,Address));
}

If you’re trying to secure the same region of memory in more than one
thread.

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@barco.com
Sent: Monday, August 27, 2007 10:43
To: Windows System Software Devs Interest List
Subject: [ntdev] MmSecureVirtualMemory returns NULL

Hi,

I have a driver that accepts user-mode pointers. These pointers are
first secured (via MmSecureVirtualMemory) before being used further on
(see code below).
Everything works fine, until I use more than 1 thread in the user
application.
MmSecureVirtualMemory starts returning NULL (no exceptions are raised).
What could be the reason for returning NULL?

Thanks,
Kurt

__try
{
SecuredAddress=MmSecureVirtualMemory(Address, Size,
PAGE_READWRITE);
}
__except(EXCEPTION_EXECUTE_HANDLER) //catch all exceptions
{
KdPrint((“MmSecureVirtualMemory failed for 0x%08X.\n”,Address));
}


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

Well, I don’t think the regions overlap.
This is a trace of the adresses being secured.
There are 2 threads, each having 2 buffers:
First thread: 0x00CA0040 and 0x01060040
Second thread:0x00E80040 and 0x01240040
As can be seen, one of the buffers fails to be mmsecured.

Each thread is looping: allocate 2 buffers, lock buffers, free buffers
[LockBuffer] Address: 0x00E80040 [size: 1920000]
[LockBuffer] Address: 0x00CA0040 [size: 1920000]
[LockBuffer] Address: 0x01240040 [size: 1920216]
[LockBuffer] Secured address is NULL - status is: 0x00000000
[LockBuffer] Address: 0x01060040 [size: 1920216]
[LockBuffer] Address: 0x00E80040 [size: 1920000]
[LockBuffer] Address: 0x01240040 [size: 1920216]
[LockBuffer] Address: 0x00CA0040 [size: 1920000]
[LockBuffer] Secured address is NULL - status is: 0x00000000

Why not just probe and lock the UM buffer with MmProbeAndLockPages?

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@barco.com
Sent: Monday, August 27, 2007 9:09 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] MmSecureVirtualMemory returns NULL

Well, I don’t think the regions overlap.
This is a trace of the adresses being secured.
There are 2 threads, each having 2 buffers:
First thread: 0x00CA0040 and 0x01060040
Second thread:0x00E80040 and 0x01240040
As can be seen, one of the buffers fails to be mmsecured.

Each thread is looping: allocate 2 buffers, lock buffers, free buffers
[LockBuffer] Address: 0x00E80040 [size: 1920000]
[LockBuffer] Address: 0x00CA0040 [size: 1920000]
[LockBuffer] Address: 0x01240040 [size: 1920216]
[LockBuffer] Secured address is NULL - status is: 0x00000000
[LockBuffer] Address: 0x01060040 [size: 1920216]
[LockBuffer] Address: 0x00E80040 [size: 1920000]
[LockBuffer] Address: 0x01240040 [size: 1920216]
[LockBuffer] Address: 0x00CA0040 [size: 1920000]
[LockBuffer] Secured address is NULL - status is: 0x00000000


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

Well, now I am calling MmSecureVirtualAddress followed by MmProbeAndLockPages.
Is this redundant?
And still, the first time MmSecureVA is called for address 0x01240040, it returns NULL, the second time not. I just discovered, that the same phenomenon occurs when running a single threaded app 2 or more times.

I have personally never used the MmSecure DDI nor have I seen any threat
model which called for its use. Looking at its use within windows, it
used only in GDI/video drivers when the video frame buffer is
virtualized. For any other case, you do not need to make the MmSecure
call.

d

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@barco.com
Sent: Monday, August 27, 2007 10:34 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] MmSecureVirtualMemory returns NULL

Well, now I am calling MmSecureVirtualAddress followed by
MmProbeAndLockPages.
Is this redundant?
And still, the first time MmSecureVA is called for address 0x01240040,
it returns NULL, the second time not. I just discovered, that the same
phenomenon occurs when running a single threaded app 2 or more times.


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

Ok thanks a lot Doron, I’ll leave it out.

It is not redundant.

MmSecureVirtualMemory ensures that the user-mode address you are trying to access cannot be unmapped or remapped (of course you still need an exception handler to catch page-in failures).

MmProbeAndLockPages ensures that the physical pages cannot be paged out, but they could still be removed from the current process’s page tables.

MmGetSystemAddressForMdlSafe takes the locked physical pages and maps them into system VA space where no application can muck with them.

In general you don’t need MmSecure and should use MmGetSystemAddress and then access pages through the kernel address.

-p

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@barco.com
Sent: Monday, August 27, 2007 10:34 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] MmSecureVirtualMemory returns NULL

Well, now I am calling MmSecureVirtualAddress followed by MmProbeAndLockPages.
Is this redundant?
And still, the first time MmSecureVA is called for address 0x01240040, it returns NULL, the second time not. I just discovered, that the same phenomenon occurs when running a single threaded app 2 or more times.


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

I use the MmSecureVirtualMemory to avoid that a user-mode program frees the memory. Because I am writing a driver and a library (not the end application), I want to protect against ‘end-user’ bugs, and hence against a BSOD. The user buffers are used in DMA operations.
To put it in another way; if I just call MmProbeAndLockPages, is the system protected against an accidental call to free() in or crash of the end-user application?
Why is MmSecureVirtualAddress returning NULL (not an exception)?

Nothing that you’re doing will have any impact on free(). Free is a CRT function and can repurpose the memory even if you’ve secured it. The only thing that it stops is someone using VirtualAlloc/Free type functions to release or change the protections on the underlying pages.

When you use MmProbeAndLockPages and MmGetSystemAddressForMdlSafe you’re protected against someone freeing the pages … the app’s address space will be modified but not your mapping.

Protecting against the application changing the contents of the pages is on your driver. If you have control information in those buffers you need to capture that into memory the application cannot modify (kernel stack or kernel pool) before validating and then only trust your captured copy.

-p

-----Original Message-----
From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@barco.com
Sent: Monday, August 27, 2007 11:35 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] MmSecureVirtualMemory returns NULL

I use the MmSecureVirtualMemory to avoid that a user-mode program frees the memory. Because I am writing a driver and a library (not the end application), I want to protect against ‘end-user’ bugs, and hence against a BSOD. The user buffers are used in DMA operations.
To put it in another way; if I just call MmProbeAndLockPages, is the system protected against an accidental call to free() in or crash of the end-user application?
Why is MmSecureVirtualAddress returning NULL (not an exception)?


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

> Why is MmSecureVirtualAddress returning NULL (not an exception)?

The documentation says that NULL is returned if the memory cannot be
secured. If it is already secured, it can’t be secured again. The except
blocks are only for access of that memory.

A process that has used memory in an OS request that becomes an IRP (such as
read, write, IoCtl, etc.) has told the OS about that memory. The only
exception being embedded pointers in a IoCtl request. Once that memory has
been used by an IRP, it cannot be fully freed until the IRP completes. That
is why if a process is terminated with a request still running, the OS will
not completely shutdown the process until all are completed or 5 minutes has
elapsed. After the timeout, any buffers being used remain allocated to that
process which is stuck in limbo. This is to prevent reassignment of a chunk
of memory that may be the target of a DMA read while it contains something
else such as currently executing code or stack pages belonging to another
process.

If your library uses embedded pointers, I would recommend you abandon that
approach so the normal protections provided by the OS can be utilized.
Remember any driver can use the filesystem techniques to allow one ‘read’ to
mean different things. In the create, add a pseudo ‘filename’ to the device
name. Write the driver so it can see that name and maintain separate
instances for it compared to another. These separate instances could be
written to do some task that a control code and embedded buffer pointer was
used to do. Some stack may not allow this, but the normal driver design
permits it. It is just rarely used outside of the filesystems.

I did not see any notes indicating that this function was designed for video
drivers. I have never tried to use it and from the comments in this thread,
I don’t think I ever will. Looks like it could serve a good purpose, but if
the OS allows an app to change the page protections on a buffer currently
being used in kernel mode, then a BSOD is a good idea. The ‘baseball bat up
side the head’ is a good instruction method. A few BSODs will get those
trying to be ‘smarter’ than your library to start playing by the rules.


David J. Craig
Engineer, Sr. Staff Software Systems
Broadcom Corporation

wrote in message news:xxxxx@ntdev…
>I use the MmSecureVirtualMemory to avoid that a user-mode program frees the
>memory. Because I am writing a driver and a library (not the end
>application), I want to protect against ‘end-user’ bugs, and hence against
>a BSOD. The user buffers are used in DMA operations.
> To put it in another way; if I just call MmProbeAndLockPages, is the
> system protected against an accidental call to free() in or crash of the
> end-user application?
> Why is MmSecureVirtualAddress returning NULL (not an exception)?
>

No need in this, just use them under __try/__except, and exception will
arise and be caught if something will go wrong.


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

wrote in message news:xxxxx@ntdev…
> Hi,
>
> I have a driver that accepts user-mode pointers. These pointers are first
secured (via MmSecureVirtualMemory) before being used further on (see code
below).
> Everything works fine, until I use more than 1 thread in the user
application.
> MmSecureVirtualMemory starts returning NULL (no exceptions are raised).
> What could be the reason for returning NULL?
>
> Thanks,
> Kurt
>
> __try
> {
> SecuredAddress=MmSecureVirtualMemory(Address, Size, PAGE_READWRITE);
> }
>__except(EXCEPTION_EXECUTE_HANDLER) //catch all exceptions
> {
> KdPrint((“MmSecureVirtualMemory failed for 0x%08X.\n”,Address));
> }
>
>

To add to this, as Peter says, using SEH after MmSecureVirtualMemory is
*very* important. This has historically been the source of a number of bugs
among things that rely heavily on MmSecureVirtualMemory, such as win32k.sys;
MmSecureVirtualMemory won’t protect you if somebody hands you a VA that is
part of a section view mapped to a network-backed file and then the user
pulls the plug on the network cable, for instance; you’ll get a
STATUS_IN_PAGE_ERROR exception even after securing the VM, and then you’re
toast if you didn’t guard the access in SEH.

I would avoid MmSecureVirtualMemory, period. You still need to use SEH with
it, and at that point, there is really very little gain over just a probe +
try/catch for all accesses anyway. All MmSecureVirtualMemory does is create
a false sense of security that you might be able to touch “secured” VM
without SEH after the fact, which is false.


Ken Johnson (Skywing)
Windows SDK MVP
http://www.nynaeve.net
“Peter Wieland” wrote in message
news:xxxxx@ntdev…
It is not redundant.

MmSecureVirtualMemory ensures that the user-mode address you are trying to
access cannot be unmapped or remapped (of course you still need an exception
handler to catch page-in failures).

MmProbeAndLockPages ensures that the physical pages cannot be paged out, but
they could still be removed from the current process’s page tables.

MmGetSystemAddressForMdlSafe takes the locked physical pages and maps them
into system VA space where no application can muck with them.

In general you don’t need MmSecure and should use MmGetSystemAddress and
then access pages through the kernel address.

-p

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@barco.com
Sent: Monday, August 27, 2007 10:34 AM
To: Windows System Software Devs Interest List
Subject: RE:[ntdev] MmSecureVirtualMemory returns NULL

Well, now I am calling MmSecureVirtualAddress followed by
MmProbeAndLockPages.
Is this redundant?
And still, the first time MmSecureVA is called for address 0x01240040, it
returns NULL, the second time not. I just discovered, that the same
phenomenon occurs when running a single threaded app 2 or more times.


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

I found the cause of the problem.
MmSecureVirtualMemory was called from the IODeviceControl callback. The pointer to user memory was contained in a struct. When using one thread, the code was OK, but when using more than one thread, now and then the pointer was in the wrong thread context (which is normal).
I solved this problem, by probing and locking the buffer in an EvtIoInCallerContext callback routine.