Doubt with MDL

I have a chunk of memory allocated from non paged pool using
ExAllocatePoolWithTag.

I want to map this to use space. So I write this function:

NTSTATUS

MapMemoryToUser(

IN PVOID pVAD,

IN ULONG uLength,

OUT PMDL *pMemMDL,

OUT PVOID *pUserVA)

{

PMDL pMDL;

PVOID pUserVAToReturn;

if((!pVAD)||(0 == uLength)) {

return STATUS_INVALID_PARAMETER;

}

// Allocate a buffer to share with the application

pMDL = IoAllocateMdl( pVAD,

uLength,

FALSE, // Secondary buffer

FALSE, // ChargeQuota

NULL); // IRP

if(!pMDL) {

return STATUS_INSUFFICIENT_RESOURCES;

}

MmBuildMdlForNonPagedPool(pMDL);

//

// The preferred V5 way to map the buffer into user space

//

pUserVAToReturn = MmMapLockedPagesSpecifyCache( pMDL, // MDL

UserMode, // Mode

MmCached, // Caching

NULL, // Address

FALSE, // Bugcheck?

NormalPagePriority); // Priority

// If we get NULL back, the request didn’t work.

if(!pUserVAToReturn) {

IoFreeMdl(pMDL);

return STATUS_INSUFFICIENT_RESOURCES;

}

// Return the allocated pointers.

*pUserVA = pUserVAToReturn;

*pMemMDL = pMDL;

return STATUS_SUCCESS;

}

this funciton is called in the context of a user thread and we tag the MDL
to the IRP there.

When I want to free the MDL I want to preserve the pVAD as it is. I just
want to unmap the MDL and the pUserVA. Will that work? this code from osr’s
article is below:

void UnMapMemory(

IN PMDL PMdl,

PVOID UserVa)

{

//

// Make sure we have an MDL to free.

//

if(!PMdl) {

return;

}

//

// Unmap the pages.

//

MmUnmapLockedPages(UserVa,PMdl);

//

// Free the pages from the MDL.

//

MmFreePagesFromMdl(PMdl); // I have doubts if I need to do this?

//

// Release the MDL.

//

IoFreeMdl(PMdl);

}

… and your QUESTION is ???

Peter
OSR

P.S. I encourage you to NOT map non-paged pool into user virtual address space.

Peter,

I am not sure whether this is the right way to do wht I am doing.

The pVAD is allocated at DriverEntry.

Later on when the user app comes up and sends the IOCTL (after opening the
device), the MDL is created and mapped to pUserVA.

so…

  1. Are there now two virtual addresses pointing to the underlying same
    physical address?
  2. Will the free routine (borrowed from OSR article), free the physical
    pages for both? If so, I dont want that, I want to preserve the pVAD and
    it’s mapping as the driver keeps using this memory long after the user app
    ends.
  3. Is this the right way to create a shared memory? Will the user app be
    able to see the memory updates dynamically as and when the driver updates
    it’s contents using the pVAD pointer?
  4. an lastly, as you point out, NPP shouldnt be mapepd to user space, what
    is the best method to create a shared memory between a user and a kernel
    driver?

On Thu, Jun 30, 2011 at 8:11 PM, wrote:

> … and your QUESTION is ???
>
> Peter
> OSR
>
> P.S. I encourage you to NOT map non-paged pool into user virtual address
> space.
>
> —
> 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 have a chunk of memory allocated from non paged pool using ExAllocatePoolWithTag.

I want to map this to use space.

I would really go the vice versa - allocate in user mode and map to kernel space in the driver.

Also, I cannot imagine how the user-mode VAD created by MmMapXxx can survive its MDL destruction.


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

>Also, I cannot imagine how the user-mode VAD created by MmMapXxx can
survive its MDL destruction.

I dont need the user-mode VAD to survive. Perhaps the scenario wasn’t clear.
I am pretty sure I am not doing this right, and even after reading the OSR
papers multiple times I have some gray areas regarding MDLs…

I have a kernel mode NPP buffer, it has a kernel modeVAD, lets call it
pKVAD.

I create an MDL out of it and map it to user mode, lets call the user mode
VAD as pUVAD.

pUVAD is only created when my user mode app exists. The idea is to share a
common buffer which kernel can write to, and user can read from.

once app closes, I will need to destry pUVAD and the MDL.

My qn is, will this also destroy pKVAD?

On Thu, Jun 30, 2011 at 11:57 PM, Maxim S. Shatskih
wrote:

> >I have a chunk of memory allocated from non paged pool using
> ExAllocatePoolWithTag.
> >I want to map this to use space.
>
> I would really go the vice versa - allocate in user mode and map to kernel
> space in the driver.
>
> Also, I cannot imagine how the user-mode VAD created by MmMapXxx can
> survive its MDL destruction.
>
> –
> Maxim S. Shatskih
> Windows DDK MVP
> xxxxx@storagecraft.com
> http://www.storagecraft.com
>
>
> —
> 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
>

No the system va for the nonpagedpool buffer allocated though
exallocatepool is not going to go away, ever, for the life of this
system boot.

Mark Roddy

On Thu, Jun 30, 2011 at 2:57 PM, A P wrote:
>>Also, I cannot imagine how the user-mode VAD created by MmMapXxx can
>> survive its MDL destruction.
>
> I dont need the user-mode VAD to survive. Perhaps the scenario wasn’t clear.
> I am pretty sure I am not doing this right, and even after reading the OSR
> papers multiple times I have some gray areas regarding MDLs…
>
> I have a kernel mode NPP buffer, it has a kernel modeVAD, lets call it
> pKVAD.
>
> I create an MDL out of it and map it to user mode, lets call the user mode
> VAD as pUVAD.
>
> pUVAD is only created when my user mode app exists. The idea is to share a
> common buffer which kernel can write to, and user can read from.
>
> once app closes, I will need to destry pUVAD and the MDL.
>
> My qn is, will this also destroy pKVAD?
>
>
>
>
> On Thu, Jun 30, 2011 at 11:57 PM, Maxim S. Shatskih
> wrote:
>>
>> >I have a chunk of memory allocated from non paged pool using
>> > ExAllocatePoolWithTag.
>> >I want to map this to use space.
>>
>> I would really go the vice versa - allocate in user mode and map to kernel
>> space in the driver.
>>
>> Also, I cannot imagine how the user-mode VAD created by MmMapXxx can
>> survive its MDL destruction.
>>
>> –
>> Maxim S. Shatskih
>> Windows DDK MVP
>> xxxxx@storagecraft.com
>> http://www.storagecraft.com
>>
>>
>> —
>> 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
>
> — 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

Sorry, I’m reading quickly (while doing other work) and your use of “VAD” confused me. To me, VAD means “Virtual Address Descriptors” as in the VAD table. See:

http://my.safaribooksonline.com/book/operating-systems-and-server-administration/microsoft-windows/9780735625303/memory-management/virtual_address_descriptors

Or, here:
http://www.osronline.com/article.cfm?article=60

ANYhow… I think Mr. Roddy answered your question.

Peter
OSR

In addition to what others said, you must wrap the call to MmMapLockedPagesSpecifyCache in try/except (since you’re specifying UserMode), and you don’t need the MmFreePagesFromMdl call in the unmap function (since you built the MDL using MmBuildMdlForNonPagedPool, not MmAllocatePagesForMdl).

Make sure to read the security warning at the bottom of the MmMapLockedPagesSpecifyCache documentation page (http://msdn.microsoft.com/en-us/library/ff554629(VS.85).aspx).

Additionally, make sure your unmap function is called in the context of the same process where you mapped the data.

From: xxxxx@lists.osr.com [mailto:xxxxx@lists.osr.com] On Behalf Of A P
Sent: Thursday, June 30, 2011 7:26 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] Doubt with MDL

I have a chunk of memory allocated from non paged pool using ExAllocatePoolWithTag.

I want to map this to use space. So I write this function:

NTSTATUS

MapMemoryToUser(

IN PVOID pVAD,

IN ULONG uLength,

OUT PMDL *pMemMDL,

OUT PVOID *pUserVA)

{

PMDL pMDL;

PVOID pUserVAToReturn;
if((!pVAD)||(0 == uLength)) {
return STATUS_INVALID_PARAMETER;

}
// Allocate a buffer to share with the application

pMDL = IoAllocateMdl( pVAD,

uLength,

FALSE,
// Secondary buffer

FALSE,
// ChargeQuota

NULL);
// IRP
if(!pMDL) {
return STATUS_INSUFFICIENT_RESOURCES;

}

MmBuildMdlForNonPagedPool(pMDL);
//
// The preferred V5 way to map the buffer into user space
//

pUserVAToReturn = MmMapLockedPagesSpecifyCache( pMDL,
// MDL

UserMode,
// Mode

MmCached,
// Caching

NULL,
// Address

FALSE,
// Bugcheck?

NormalPagePriority);
// Priority
// If we get NULL back, the request didn’t work.
if(!pUserVAToReturn) {

IoFreeMdl(pMDL);
return STATUS_INSUFFICIENT_RESOURCES;

}
// Return the allocated pointers.

*pUserVA = pUserVAToReturn;

*pMemMDL = pMDL;
return STATUS_SUCCESS;

}

this funciton is called in the context of a user thread and we tag the MDL to the IRP there.

When I want to free the MDL I want to preserve the pVAD as it is. I just want to unmap the MDL and the pUserVA. Will that work? this code from osr’s article is below:

void
UnMapMemory(

IN PMDL PMdl,

PVOID UserVa)

{
//
// Make sure we have an MDL to free.
//
if(!PMdl) {
return;

}
//
// Unmap the pages.
//

MmUnmapLockedPages(UserVa,PMdl);
//
// Free the pages from the MDL.
//

MmFreePagesFromMdl(PMdl); // I have doubts if I need to do this?
//
// Release the MDL.
//

IoFreeMdl(PMdl);

}
— 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 thank all of you for being so very patient and typing out such descriptive
emails to make me understand and clear my doubts.

Best regards

AP

On Fri, Jul 1, 2011 at 6:03 AM, Pavel Lebedynskiy wrote:

> In addition to what others said, you must wrap the call to
> MmMapLockedPagesSpecifyCache in try/except (since you?re specifying
> UserMode), and you don?t need the MmFreePagesFromMdl call in the unmap
> function (since you built the MDL using MmBuildMdlForNonPagedPool, not
> MmAllocatePagesForMdl).
>
>
**
>
> Make sure to read the security warning at the bottom of the
> MmMapLockedPagesSpecifyCache documentation page (
> http://msdn.microsoft.com/en-us/library/ff554629(VS.85).aspx).

>
> ****
>
> Additionally, make sure your unmap function is called in the context of the
> same process where you mapped the data.
>
>

>
> From: xxxxx@lists.osr.com [mailto:
> xxxxx@lists.osr.com] On Behalf Of A P
> Sent: Thursday, June 30, 2011 7:26 AM
> To: Windows System Software Devs Interest List
> Subject: [ntdev] Doubt with MDL

>
> ****
>
> I have a chunk of memory allocated from non paged pool using
> ExAllocatePoolWithTag.
>
>

>
> I want to map this to use space. So I write this function:
>
>

>
> NTSTATUS
>
> MapMemoryToUser(

>
> IN PVOID pVAD,
>
> IN ULONG uLength,

>
> OUT PMDL pMemMDL,
>
> OUT PVOID pUserVA)

>
> {
>
> PMDL pMDL;

>
> PVOID pUserVAToReturn;

>
> if((!pVAD)||(0 == uLength)) {
**
>
> return STATUS_INVALID_PARAMETER;
>
> }

>
> // Allocate a buffer to share with the application
>
> pMDL = IoAllocateMdl( pVAD,

>
> uLength,
>
> FALSE,

>
> // Secondary buffer
>
> FALSE,

>
> // ChargeQuota
>
> NULL);

>
> // IRP
>
> if(!pMDL) {

>
> return STATUS_INSUFFICIENT_RESOURCES;
>
> }

>
> MmBuildMdlForNonPagedPool(pMDL);
>
> //

>
> // The preferred V5 way to map the buffer into user space
>
> //

>
> pUserVAToReturn = MmMapLockedPagesSpecifyCache( pMDL,
>
> // MDL

>
> UserMode,
>
> // Mode

>
> MmCached,
>
> // Caching

>
> NULL,
>
> // Address

>
> FALSE,
>
> // Bugcheck?

>
> NormalPagePriority);
>
> // Priority

>
> // If we get NULL back, the request didn’t work.
>
> if(!pUserVAToReturn) {

>
> IoFreeMdl(pMDL);
>
> return STATUS_INSUFFICIENT_RESOURCES;

>
> }
>
> // Return the allocated pointers.

>
> *pUserVA = pUserVAToReturn; *
>
> pMemMDL = pMDL;

>
> return STATUS_SUCCESS;
>
> }

>
>
>
>

>
> this funciton is called in the context of a user thread and we tag the MDL
> to the IRP there.
>
> When I want to free the MDL I want to preserve the pVAD as it is. I just
> want to unmap the MDL and the pUserVA. Will that work? this code from osr’s
> article is below:

>
>
>
> void

>
> UnMapMemory(
>
> IN PMDL PMdl,

>
> PVOID UserVa)
>
> {

>
> //
>
> // Make sure we have an MDL to free.

>
> //
>
> if(!PMdl) {

>
> return;
>
> }

>
> //
>
> // Unmap the pages.

>
> //
>
> MmUnmapLockedPages(UserVa,PMdl);

>
> //
>
> // Free the pages from the MDL.

>
> //
>
> MmFreePagesFromMdl(PMdl); // I have doubts if I need to do this?

>
> //
>
> // Release the MDL.

>
> //
>
> IoFreeMdl(PMdl);

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

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