Problem with MmProbeAndLockPages

I am trying to do kernel-user communication using shared memory - section objects. I created a section object in my minifilter driver with ZwCreateSection and then mapped a view of it into a virtual address using ZwMapViewOfSection. I have given it full read/write permissions everywhere. In order to access it in an arbitrary user process, I need to get the system address for the buffer - MmGetSystemAddressForMdlSafe. I call MmProbeAndLockPages before calling MmGetSystemAddressForMdlSafe to make sure that the buffer is resident in memory.

The MmProbeAndLockPages call always results in a STATUS_ACCESS_VIOLATION exception no matter what I do. I haven’t got a great deal of experience in writing windows drivers; so I think I must be missing something pretty basic. Here’s the code:

NTSTATUS DriverEntry(
__in PDRIVER_OBJECT DrvObj,
__in PUNICODE_STRING RegPath
)
{
NTSTATUS status;
UNICODE_STRING tmpstr;
OBJECT_ATTRIBUTES objattr;
LARGE_INTEGER secsize;
SIZE_T viewsize;
UNICODE_STRING DeviceName;
UNICODE_STRING SymName;
PDEVICE_OBJECT deviceObject = NULL;
SECURITY_DESCRIPTOR sd;
num_file_ops = 0;
status = FltRegisterFilter( DrvObj, &regstruct, &flthandle );

if(!NT_SUCCESS(status))
return status;

RtlInitUnicodeString(&tmpstr, L"\BaseNamedObjects\HwmfilterMemSect");

status = RtlCreateSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
if(!NT_SUCCESS(status))
return status;
status = RtlSetDaclSecurityDescriptor( &sd, TRUE, NULL, FALSE );
if(!NT_SUCCESS(status))
{
//Free Security Descriptor
return status;
}

InitializeObjectAttributes(
&objattr,
&tmpstr,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
&sd
);

secsize.QuadPart = 0x10000;

status = ZwCreateSection(
&sechandle,
SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY,
&objattr,
&secsize,
PAGE_READWRITE,
SEC_COMMIT,
NULL
);

sharedmem = NULL;
viewsize = PAGE_SIZE;

status = ZwMapViewOfSection(
sechandle,
(HANDLE)-1,
&sharedmem,
0L,
PAGE_SIZE,
NULL,
&viewsize,
ViewShare,
0,
PAGE_READWRITE
);

*(PULONG)sharedmem = 99; // ** Succeeds without any problem

if(!MmIsAddressValid(sharedmem))
DbgPrint(“ZwMapViewOfSection failed silently!!\n”);
.
.
.
}

NTSTATUS modifySharedBuf(const void *dataToWrite, long dataLength)
{
NTSTATUS status = STATUS_SUCCESS;
//make these params global or #defined
mdl = IoAllocateMdl(sharedmem, PAGE_SIZE, FALSE, FALSE, NULL);
if(!mdl)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
try
{
MmProbeAndLockPages(mdl, KernelMode, IoModifyAccess);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
IoFreeMdl(mdl);
return status;
}
shmbuf = MmGetSystemAddressForMdlSafe(mdl ,NormalPagePriority);

if(!shmbuf)
{
DbgPrint(“Failed to create systemwide address\n”);
MmUnlockPages(mdl);
IoFreeMdl(mdl);
return STATUS_INSUFFICIENT_RESOURCES;
}

//Now modify the shared buffer and then free it later

RtlCopyMemory(shmbuf, dataToWrite, dataLength);

MmUnlockPages(mdl);
IoFreeMdl(mdl);
return status;
}

I’ve already got a version of the driver working with the port based user-kernel communication model described in the minifilter documentation. I just want to try this out so that I can do a performance comparison with my specific application scenario. Any help would be greatly appreciated.

If I’m reading this right,this is pretty dangerous: you have an unprotected section object that any arbitrary user mode process can map and scribble on? Malware can completely take over the system this way. Please reconsider this.
Ravi


From: xxxxx@lists.osr.com on behalf of xxxxx@gmail.com
Sent: Tue 6/26/2007 6:21 PM
To: Windows File Systems Devs Interest List
Subject: [ntfsd] Problem with MmProbeAndLockPages

I am trying to do kernel-user communication using shared memory - section objects. I created a section object in my minifilter driver with ZwCreateSection and then mapped a view of it into a virtual address using ZwMapViewOfSection. I have given it full read/write permissions everywhere. In order to access it in an arbitrary user process, I need to get the system address for the buffer - MmGetSystemAddressForMdlSafe. I call MmProbeAndLockPages before calling MmGetSystemAddressForMdlSafe to make sure that the buffer is resident in memory.

The MmProbeAndLockPages call always results in a STATUS_ACCESS_VIOLATION exception no matter what I do. I haven’t got a great deal of experience in writing windows drivers; so I think I must be missing something pretty basic. Here’s the code:

NTSTATUS DriverEntry(
__in PDRIVER_OBJECT DrvObj,
__in PUNICODE_STRING RegPath
)
{
NTSTATUS status;
UNICODE_STRING tmpstr;
OBJECT_ATTRIBUTES objattr;
LARGE_INTEGER secsize;
SIZE_T viewsize;
UNICODE_STRING DeviceName;
UNICODE_STRING SymName;
PDEVICE_OBJECT deviceObject = NULL;
SECURITY_DESCRIPTOR sd;
num_file_ops = 0;
status = FltRegisterFilter( DrvObj, &regstruct, &flthandle );

if(!NT_SUCCESS(status))
return status;

RtlInitUnicodeString(&tmpstr, L"\BaseNamedObjects\HwmfilterMemSect");

status = RtlCreateSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
if(!NT_SUCCESS(status))
return status;
status = RtlSetDaclSecurityDescriptor( &sd, TRUE, NULL, FALSE );
if(!NT_SUCCESS(status))
{
//Free Security Descriptor
return status;
}

InitializeObjectAttributes(
&objattr,
&tmpstr,
OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
NULL,
&sd
);

secsize.QuadPart = 0x10000;

status = ZwCreateSection(
&sechandle,
SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY,
&objattr,
&secsize,
PAGE_READWRITE,
SEC_COMMIT,
NULL
);

sharedmem = NULL;
viewsize = PAGE_SIZE;

status = ZwMapViewOfSection(
sechandle,
(HANDLE)-1,
&sharedmem,
0L,
PAGE_SIZE,
NULL,
&viewsize,
ViewShare,
0,
PAGE_READWRITE
);

*(PULONG)sharedmem = 99; // ** Succeeds without any problem

if(!MmIsAddressValid(sharedmem))
DbgPrint(“ZwMapViewOfSection failed silently!!\n”);
.
.
.
}

NTSTATUS modifySharedBuf(const void *dataToWrite, long dataLength)
{
NTSTATUS status = STATUS_SUCCESS;
//make these params global or #defined
mdl = IoAllocateMdl(sharedmem, PAGE_SIZE, FALSE, FALSE, NULL);
if(!mdl)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
try
{
MmProbeAndLockPages(mdl, KernelMode, IoModifyAccess);
}
except(EXCEPTION_EXECUTE_HANDLER)
{
status = GetExceptionCode();
IoFreeMdl(mdl);
return status;
}
shmbuf = MmGetSystemAddressForMdlSafe(mdl ,NormalPagePriority);

if(!shmbuf)
{
DbgPrint(“Failed to create systemwide address\n”);
MmUnlockPages(mdl);
IoFreeMdl(mdl);
return STATUS_INSUFFICIENT_RESOURCES;
}

//Now modify the shared buffer and then free it later

RtlCopyMemory(shmbuf, dataToWrite, dataLength);

MmUnlockPages(mdl);
IoFreeMdl(mdl);
return status;
}

I’ve already got a version of the driver working with the port based user-kernel communication model described in the minifilter documentation. I just want to try this out so that I can do a performance comparison with my specific application scenario. Any help would be greatly appreciated.


Questions? First check the IFS FAQ at https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@windows.microsoft.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

I would abandon all of this undocumented stuff and use inverted calls and
usual IOCTLs.


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

wrote in message news:xxxxx@ntfsd…
> I am trying to do kernel-user communication using shared memory - section
objects. I created a section object in my minifilter driver with
ZwCreateSection and then mapped a view of it into a virtual address using
ZwMapViewOfSection. I have given it full read/write permissions everywhere. In
order to access it in an arbitrary user process, I need to get the system
address for the buffer - MmGetSystemAddressForMdlSafe. I call
MmProbeAndLockPages before calling MmGetSystemAddressForMdlSafe to make sure
that the buffer is resident in memory.
>
> The MmProbeAndLockPages call always results in a STATUS_ACCESS_VIOLATION
exception no matter what I do. I haven’t got a great deal of experience in
writing windows drivers; so I think I must be missing something pretty basic.
Here’s the code:
>
> NTSTATUS DriverEntry(
> in PDRIVER_OBJECT DrvObj,
>
in PUNICODE_STRING RegPath
> )
> {
> NTSTATUS status;
> UNICODE_STRING tmpstr;
> OBJECT_ATTRIBUTES objattr;
> LARGE_INTEGER secsize;
> SIZE_T viewsize;
> UNICODE_STRING DeviceName;
> UNICODE_STRING SymName;
> PDEVICE_OBJECT deviceObject = NULL;
> SECURITY_DESCRIPTOR sd;
> num_file_ops = 0;
> status = FltRegisterFilter( DrvObj, &regstruct, &flthandle );
>
> if(!NT_SUCCESS(status))
> return status;
>
> RtlInitUnicodeString(&tmpstr, L"\BaseNamedObjects\HwmfilterMemSect");
>
> status = RtlCreateSecurityDescriptor( &sd, SECURITY_DESCRIPTOR_REVISION );
> if(!NT_SUCCESS(status))
> return status;
> status = RtlSetDaclSecurityDescriptor( &sd, TRUE, NULL, FALSE );
> if(!NT_SUCCESS(status))
> {
> //Free Security Descriptor
> return status;
> }
>
> InitializeObjectAttributes(
> &objattr,
> &tmpstr,
> OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
> NULL,
> &sd
> );
>
> secsize.QuadPart = 0x10000;
>
> status = ZwCreateSection(
> &sechandle,
> SECTION_MAP_READ | SECTION_MAP_WRITE | SECTION_QUERY,
> &objattr,
> &secsize,
> PAGE_READWRITE,
> SEC_COMMIT,
> NULL
> );
>
> sharedmem = NULL;
> viewsize = PAGE_SIZE;
>
> status = ZwMapViewOfSection(
> sechandle,
> (HANDLE)-1,
> &sharedmem,
> 0L,
> PAGE_SIZE,
> NULL,
> &viewsize,
> ViewShare,
> 0,
> PAGE_READWRITE
> );
>
> *(PULONG)sharedmem = 99; // ** Succeeds without any problem
>
> if(!MmIsAddressValid(sharedmem))
> DbgPrint(“ZwMapViewOfSection failed silently!!\n”);
> .
> .
> .
> }
>
> NTSTATUS modifySharedBuf(const void *dataToWrite, long dataLength)
> {
> NTSTATUS status = STATUS_SUCCESS;
> //make these params global or #defined
> mdl = IoAllocateMdl(sharedmem, PAGE_SIZE, FALSE, FALSE, NULL);
> if(!mdl)
> {
> return STATUS_INSUFFICIENT_RESOURCES;
> }
> try
> {
> MmProbeAndLockPages(mdl, KernelMode, IoModifyAccess);
> }
> except(EXCEPTION_EXECUTE_HANDLER)
> {
> status = GetExceptionCode();
> IoFreeMdl(mdl);
> return status;
> }
> shmbuf = MmGetSystemAddressForMdlSafe(mdl ,NormalPagePriority);
>
> if(!shmbuf)
> {
> DbgPrint(“Failed to create systemwide address\n”);
> MmUnlockPages(mdl);
> IoFreeMdl(mdl);
> return STATUS_INSUFFICIENT_RESOURCES;
> }
>
> //Now modify the shared buffer and then free it later
>
> RtlCopyMemory(shmbuf, dataToWrite, dataLength);
>
> MmUnlockPages(mdl);
> IoFreeMdl(mdl);
> return status;
> }
>
> I’ve already got a version of the driver working with the port based
user-kernel communication model described in the minifilter documentation. I
just want to try this out so that I can do a performance comparison with my
specific application scenario. Any help would be greatly appreciated.
>

Why do you want to share memory, in the first place??? There are some situations when
it is justified, but these are rare (for example, when you have to do huge data transfers frequently) - in most cases it is much better (and easier) to use the inverted call technique. First of all, shared buffer is always a potential security risk, and, second, you have to synchronize access to it - all potential performance benefits tha you expect to get are washed away by calls to WaitXXX every time you want to access it…

Anton Bassov

In the project that I am working on, the driver requires services from a user-application. So, the driver initiates the transfer of data in response to some intermittent system events. So, I can’t really keep an IRP from user pending waiting for some event to happen which is not even guaranteed to occur at most times. I know that the synchronization costs are pretty high for a shared memory implementation but I can’t think of an alternate efficient architecture most suited to my project.

Search OSR online for “Inverted Call”

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of xxxxx@gmail.com
Sent: Friday, June 29, 2007 13:37
To: Windows File Systems Devs Interest List
Subject: RE:[ntfsd] Problem with MmProbeAndLockPages

In the project that I am working on, the driver requires services from a
user-application. So, the driver initiates the transfer of data in
response to some intermittent system events. So, I can’t really keep an
IRP from user pending waiting for some event to happen which is not even
guaranteed to occur at most times. I know that the synchronization costs
are pretty high for a shared memory implementation but I can’t think of
an alternate efficient architecture most suited to my project.


Questions? First check the IFS FAQ at
https://www.osronline.com/article.cfm?id=17

You are currently subscribed to ntfsd as: xxxxx@evitechnology.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> So, the driver initiates the transfer of data in response to some intermittent system events.

This is exactly the sitation when “inverted call” applies…

I can’t really keep an IRP from user pending waiting for some event to happen which
is not even guaranteed to occur at most times.

Why not??? Sorry, but this is what asynch IO is all about - you just make a problem out of nothing…

Anton Bassov

> In the project that I am working on, the driver requires services from a
user-

application. So, the driver initiates the transfer of data in response to some
intermittent system events. So, I can’t really keep an IRP from user pending
waiting for some event to happen which is not even guaranteed to occur at most
times.

So what? still keep an IRP pending. If necessary, remake the app to be the
service.


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

Thanks for the suggestions about inverted calls guys, I will try to evaluate a new architecture based on this.