0

I have a kmdf that allocates a single buffer using MmAllocateContiguousMemorySpecifyCache and gets its mdl:

auto ptr = MmAllocateContiguousMemorySpecifyCache(
    BUFFER_SIZE,
    lowestAcceptible,
    highestAcceptible,
    lowestAcceptible,
    MmCached);

PQUEUE_CONTEXT queueContext = QueueGetContext(queue);
if (ptr)
{
    RtlZeroMemory(ptr, BUFFER_SIZE);
    queueContext->stage_buffer_ptr = ptr;
    queueContext->stage_buffer_byte_size = BUFFER_SIZE;
    queueContext->stage_buffer_bus_address = MmGetPhysicalAddress(ptr).QuadPart;
    queueContext->mdl = IoAllocateMdl(
        ptr,
        static_cast<ULONG>(queueContext->stage_buffer_byte_size),
        false,
        false,
        nullptr
    );

Once that buffer is allocated, the driver handles a ioctl (method neither) that maps the pre-allocated buffer to the requesting process address space using MmMapLockedPagesSpecifyCache:

auto queueContext = QueueGetContext(Queue);

auto user_ptr = MmMapLockedPagesSpecifyCache(
     queueContext->mdl,
     UserMode,
     MmCached,
     nullptr,
     false,
     MM_PAGE_PRIORITY::HighPagePriority
);

A few lines after, I fill the memory with testing values:

auto vals = (int*)queueContext->stage_buffer_ptr; // kernel virtual address
for (auto i = 0; i < 10; ++i)
{
    vals[i] = i;
}

but when the user loops on its mapped address, it gets garbage values.
I tried to debug this issue with WinDbg and when I break after the loop I see the following:

kernel virtual address:

1: kd> dc 0xffffb901`c6f5d000 (ok)

ffffb901`c6f5d000  00000000 00000001 00000002 00000003  ................
ffffb901`c6f5d010  00000004 00000005 00000006 00000007  ................
ffffb901`c6f5d020  00000008 00000009 00000000 00000000  ................
ffffb901`c6f5d030  00000000 00000000 00000000 00000000

user virtual address: (displays junk)

1: kd> dc 0x00000174`423f0000

00000174`423f0000  332c3000 ffffcc05 bc823afb 01d40a37  .0,3.....:..7...
00000174`423f0010  5e784ab3 01d5da99 5e784ab3 01d5da99  .Jx^.....Jx^....
00000174`423f0020  b1de413c 01d5db3f 00002000 00000000  <A..?.... ......
00000174`423f0030  00002000 00000000 00000010 00000000  . ..............

So why don't I see the same values via the pointer received by MmMapLockedPagesSpecifyCache?

GSerg
  • 76,472
  • 17
  • 159
  • 346
Elad Maimoni
  • 3,703
  • 3
  • 20
  • 37
  • *but when the user loops on its mapped address* - where is you map some user buffer ? for what you need **contiguous physical** memory ? you really need it ? `IoAllocateMdl + MmMapLockedPagesSpecifyCache` iswrong here (you **not lock** any pages) - you need `MmBuildMdlForNonPagedPool` (if you allocate nonpaged pool). for what you use `METHOD_NEITHER` when you want map user buffer ? why not `METHOD_OUT_DIRECT` ? and again - absolute invisible where you at all access user buffer, where you map it and write to it. you write to memory absolute unrelated to user buffer – RbMm Feb 09 '20 at 11:48
  • @RbMm Indeed MmBuildMdlForNonPagedPool was the missing part. I use method neither to ensure I call MmMapLockedPagesSpecifyCache in the calling Process context. Isn't it necessary? – Elad Maimoni Feb 09 '20 at 12:32
  • @RbMm regarding why I need contiguous physical memory. The hardware I use does not support Scatter / Gather DMA. so it needs contiguous buffers to be able to perform efficient DMA. – Elad Maimoni Feb 09 '20 at 12:34

0 Answers0