No Access to RAM space allocated by kernel

Hello,

My device driver is allocating a continuous 32 MB kernel space.

This space is mapped to user space using the following mechanism:

  1. Application is sending IOCTL request to the device driver.

  2. PVOID UserSpaceCommonBuffer = MmMapLockedPagesSpecifyCache (CommnBufferMdl, UserMode, MmCached, NULL, FLASE, NormalPagePriority)

  3. The value of UserSpaceCommonBuffer is less than 4GB (e.g : 0xA050000)

  4. This value is returned to the application in the IOCTL reply.

But when I’m trying to access this address from the application, I’m getting access violation.
Using the V.S 2010 debugger, I can see that this space is: ???

I also tried an x64 version of the user space application and got the same results.
The O.S is windows 7-64.

Under windows server 2003-32, server 2008-64, server 2012-64, this code works great.

What can cause this problem ? Can it caused by BIOS ?

Thank you,
Zvika

You still need to ensure that the mapping is done in the proper application context.

So you must run the !process command in the debugger to ensure that the driver is running in the context of the app that issued the IO request.

xxxxx@gmail.com wrote:

My device driver is allocating a continuous 32 MB kernel space.

This space is mapped to user space using the following mechanism:

  1. Application is sending IOCTL request to the device driver.
  2. PVOID UserSpaceCommonBuffer = MmMapLockedPagesSpecifyCache (CommnBufferMdl, UserMode, MmCached, NULL, FLASE, NormalPagePriority)
  3. The value of UserSpaceCommonBuffer is less than 4GB (e.g : 0xA050000)
  4. This value is returned to the application in the IOCTL reply.

But when I’m trying to access this address from the application, I’m getting access violation.
Using the V.S 2010 debugger, I can see that this space is: ???

Are you using KMDF? Depending on the synchronization settings you chose
in your driver, it’s possible that your EvtIoDeviceControl handler might
be called in the context of the system process, instead of the original
calling process. You may need an EvtIoInCallerContext handler to get
that guarantee.

What can cause this problem ? Can it caused by BIOS ?

What on earth would lead you down that line of thinking? Or maybe we
shouldn’t explore that.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

Hi Tim, All,

The sample code src\storage\class\cdrom\cdrom.c contains the routine:
DeviceEvtIoInCallerContext:

// 1. All requests that don’t need to access device can be processed immidiately

// 2. Requests that should be put in sequential queue.

// 3. Requests that need to be processed sequentially and in caller’s context.

// 4. Special requests that needs different process in different cases.

// 5. This is default behavior for unknown IOCTLs. To pass it to lower level.

In my device driver there is one IOCTL request that calls MmMapLockedPagesSpecifyCache and returns the virtual address of the pre-allocated kernel buffer in the calling process context.
Is it type 3 ?

Can I cause all other IOCTLs to be handled in the regular IoControl callback used till now ?

Thank you,
Zvika

>In my device driver there is one IOCTL request that calls
MmMapLockedPagesSpecifyCache and returns the virtual address of the
pre-allocated kernel buffer in the calling process context.Is it type 3 ?

The requests need not be handled sequentially, this is not mandatory, but
the driver must run in the app’s context.

Now imagine that your driver maps the buffer into the address space of a
different process but that the returned VA is valid in both processes. This
would lead to memory corruption if the app writes into the buffer and no
exception occurs.

One way to avoid this is to let the driver not only write the mapped
address but also the PID of the process in whose context it is executing.
The app would then be able to compare the PID written by the driver with
its own PID. If these PIDs are different the app would not attempt any
access.

Hello D.T, All,

If the result of PsGetCurrentProcessId is different from the app’s process ID, should I try sending the IOCTL request again ?

A valid VA returned from the device driver is mandatory.

Thank you,
Zvika

Do you call KeStackAttachProcess ?

Hi Slava,

I’m not calling KeStackAttachProcess.

Upon IOCTL request, should I get the process Id from app, and try to attach it by: KeStackAttachProcess ?

Can you please provide sample code ?

Best regards,
Zvika

>If the result of PsGetCurrentProcessId is different from the app’s process ID, should I try sending the IOCTL request again ?

Yes you could but depending on how requests are queued, you could have a lot of bad mappings.

The issuer could also pass its PID in the input buffer and your driver fail the request if it does not run in the proper context. Only filter drivers can use KeStackAttachProcess.

You could also register an EvtIoInCallerContext callback to fill the request’s context space with useful informations about the requestor. Look at WdfDeviceInitSetRequestAttributes.

But remember that a device can be filtered and you may not be at the top of the stack. The callback may not run in the context of the thread that issued the I/O request.

A valid VA returned from the device driver is mandatory.

Yes but a valid VA does not mean that the access is safe.

Sent from my Windows 10 phone

De : xxxxx@gmail.com
Envoyé le :mercredi 5 avril 2017 02:47
À : Windows System Software Devs Interest List
Objet :RE:[ntdev] No Access to RAM space allocated by kernel

Hello D.T, All,

If the result of PsGetCurrentProcessId is different from the app’s process ID, should I try sending the IOCTL request again ?

A valid VA returned from the device driver is mandatory.

Thank you,
Zvika


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:>

Something like this. Disclaimer - I didn’t try to compile it.

NTSTATUS
FooAttachToProcessByPID(
__in HANDLE ProcessID // this is a process ID, in NT an integer PID is defined as HANDLE
)
{

HANDLE ProcessHandle = NULL;
PEPROCESS Process = NULL;

OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID ClientID;
NTSTATUS RC = STATUS_UNSUCCESSFUL;

KAPC_STATE ApcState;

ASSERT( KeGetCurrentIrql() == PASSIVE_LEVEL && !KeAreAllApcsDisabled() );

ClientID.UniqueProcess = ProcessID;
ClientID.UniqueThread = NULL;

InitializeObjectAttributes( &ObjectAttributes,
NULL,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL );

RC = ZwOpenProcess( &ProcessHandle,
STANDARD_RIGHTS_ALL,
&ObjectAttributes,
&ClientID );
if( !NT_SUCCESS( RC ) )
goto __exit;

RC = ObReferenceObjectByHandle( ProcessHandle,
PROCESS_ALL_ACCESS,
*PsProcessType,
KernelMode,
&Process,
NULL );
if( !NT_SUCCESS( RC ) )
goto __exit;

KeStackAttachProcess( Process, &ApcState );
{ // we are attached to the address space of the process

//
// map pages to the process user space
// N.B. if you call PsGetCurrentProcess() or PsGetCurrentProcessId() you will get
// the process to which this thread has been attached
//

} // detach from the process address space
KeUnstackDetachProcess( &ApcState );

__exit:

if( NULL != Process )
ObDereferenceObject( Process );

if( NULL != ProcessHandle )
ZwClose( ProcessHandle );

return RC;
}

You would better let the app allocate its own buffer and then issue an IOCTL upon which the driver would copy the kernel buffer’s content into the user buffer.

This is an expensive copy but it is safer.

Sent from my Windows 10 phone

Do you actually need contiguous memory? If you don’t just let the app
allocate the buffer. If it turns out that your device stack is in fact
causing a process context switch you could possibly provide a separate
control device dedicated for providing support for the buffer ioctl.

Mark Roddy

On Wed, Apr 5, 2017 at 10:46 AM, wrote:

> You would better let the app allocate its own buffer and then issue an
> IOCTL upon which the driver would copy the kernel buffer’s content into the
> user buffer.
>
>
>
> This is an expensive copy but it is safer.
>
>
>
> Sent from my Windows 10 phone
>
>
>
>
>
> —
> NTDEV is sponsored by OSR
>
> Visit the list online at: http:> showlists.cfm?list=ntdev>
>
> MONTHLY seminars on crash dump analysis, WDF, Windows internals and
> software drivers!
> Details at http:
>
> To unsubscribe, visit the List Server section of OSR Online at <
> http://www.osronline.com/page.cfm?name=ListServer&gt;
></http:></http:>

xxxxx@gmail.com wrote:

The sample code src\storage\class\cdrom\cdrom.c contains the routine:
DeviceEvtIoInCallerContext:

// 1. All requests that don’t need to access device can be processed immidiately
// 2. Requests that should be put in sequential queue.
// 3. Requests that need to be processed sequentially and in caller’s context.
// 4. Special requests that needs different process in different cases.
// 5. This is default behavior for unknown IOCTLs. To pass it to lower level.

In my device driver there is one IOCTL request that calls MmMapLockedPagesSpecifyCache and returns the virtual address of the pre-allocated kernel buffer in the calling process context.
Is it type 3 ?

I don’t think it’s useful to think about “types” in this way. The
decision process here is very straightforward. If you need access to
the calling processes memory space, then you need to guarantee that you
are still running in that process context, and that means you need
EvtIoInCallerContext. Otherwise, it’s quite possible that the current
process could have switched to Microsoft Word, and if you map your
memory into Word’s address space, that’s not going to be very useful for
your calling process.

Can I cause all other IOCTLs to be handled in the regular IoControl callback used till now ?

If you don’t need access to the calling processes memory space, then of
course you can. Note that, for METHOD_BUFFERED and METHOD_*_DIRECT
ioctls, the operating system will copy or map the user-mode pages into
kernel memory, so you don’t need to access the process memory space. If
you use METHOD_NEITHER ioctls, which you shouldn’t, then you have the
same problem – you need to use EvtIoInCallerContext.


Tim Roberts, xxxxx@probo.com
Providenza & Boekelheide, Inc.

I hope you understand that a mandatory successful return is impossible as a requirement. There may simply not be any memory available to satisfy this request and it may even fail above your driver.

What you can ensure is that you never return success when providing an invalid response. You have already heard from others about which KMDF callbacks to use to make this happen

Sent from Mailhttps: for Windows 10

From: xxxxx@gmail.commailto:xxxxx
Sent: April 4, 2017 8:47 PM
To: Windows System Software Devs Interest Listmailto:xxxxx
Subject: RE:[ntdev] No Access to RAM space allocated by kernel

Hello D.T, All,

If the result of PsGetCurrentProcessId is different from the app’s process ID, should I try sending the IOCTL request again ?

A valid VA returned from the device driver is mandatory.

Thank you,
Zvika


NTDEV is sponsored by OSR

Visit the list online at: http:

MONTHLY seminars on crash dump analysis, WDF, Windows internals and software drivers!
Details at http:

To unsubscribe, visit the List Server section of OSR Online at http:</http:></http:></http:></mailto:xxxxx></mailto:xxxxx></https:>

Hi Tim, All,

The mapping to user space (with MmMapLockedPagesSpecifyCache) is now handled in DeviceEvtIoInCallerContext.

All other IOCTLs are forwarded to the original IoControl callback with:
WdfDeviceEnqueuRequest

Tim - Thank you very much for this solution.

Best regards,
Zvika