How to wait for an user-mode signal in driver

Hi everyone! I’m developing a KMDF driver

In the callback function SetCreateProcessNotifyRoutineEx (of PsSetCreateProcessNotifyRoutineEx), I get the process name of the new spawned process and send it to the usermode application by using inverted call. After receiving the process name, the usermode application will start another command line application and then notify the driver after doing that, so the driver have to wait for the usermode app to do that, then let the new process start to run. My question is, what is the best way to wait for the notification of the usermode app in my driver?

Thank you!

As you are speaking about a low frequency communication then something like this should do the job ( the code was not copy-pasted but was written in the quick reply form so misprints and omissions are possible )

typedef struct {
LIST_ENTRY Entry;
ULONG MessageID;
KEVENT Event;
} WaitBlock;

static LIST_ENTRY gWaitListHead; // initialize in DriverEntry
static KSPIN_LOCK gWaitListHeadLock; // initialize in DriverEntry
static ULONG gPreviousMessageID = 0;

CallUserAndWait( __in PVOID DataForApp )
{
WaitBlock* wb = ExAllocatePool( NonPagedPool, sizeof(*wb) );

RtlZeroMemory( wb, sizeof(*wb) );

KeinitializeEvent( &wb->Event, SynchronizationEvent );

//
// it is important to add in the list before calling a user mode app
// so the waiting block can be ALWAYS discovered in IOCTL handler
// and a wakeup event is not lost
//
KeAcquireSpinLock( &gWaitListHeadLock, &OldIrql );
{
wb->MessageID = ++gPreviousMessageID;
InsertTailList( &gWaitListHead, &wb->Entry );
}
KeReleaseSpinLock( &gWaitListHeadLock, OldIrql);

CallUserApplication( wb->MessageID, DataForApp );

KeWaitForSingleObject( &wb->Event, UserMode, &Timeout );

KeAcquireSpinLock( &gWaitListHeadLock, &OldIrql );
{
RemoveEntryList( &wb->Entry );
}
KeReleaseSpinLock( &gWaitListHeadLock, OldIrql);

ExFreePool( wb );
}

//
// ProcessWakeIOCTL is called from an IOCTL dispatch handler,
// MessageID is sent by an application via IOCTL or any other
// application to driver communication
//
ProcessWakeIOCTL( __in ULONG MessageID )
{
KeAcquireSpinLock( &gWaitListHeadLock, &OldIrql );
{
//
// traverse gWaitListHead find an entry by MessageID
//
for( entry = gWaitListHead->Flink; entry != &gWaitListHead; entry = entry->Flink ){

WaitBlock* wb = CONTAINING_ENTRY( entry, WaitBlock, Entry );

if( wb->MessageID != MessageID )
continue;

//
// the event must be set under the lock as KeWaitForSingleObject waits with Timeout
// and UserMode mode, the lock guaranties wb->Event validity
//
KeSetEvent( &wb->Event );
break;
}
}
KeReleaseSpinLock( &gWaitListHeadLock, OldIrql);
}

@melissa:
@Slava:

What’s wrong with just issuing an IOCTL?

If I got it right the OP wants to stop (inside a callback) a newly created process from executing in user mode until a response is received.

I haven’t tried this with PsSetCreateProcessNotifyRoutineEx, but in older
versions of Windows with PsSetCreateProcessNotifyRoutine, the system
serialized the callbacks. So the spawning of the command line application
won’t complete until the callback for the original process is done. I
can’t say for sure that you will hit this, but the whole design which
requires creating a second process while in the middle of the first
processes notification callback is likely to run into deadlocks.

Don Burn
Windows Driver Consulting
Website: http://www.windrvr.com

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Monday, October 31, 2016 5:16 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] How to wait for an user-mode signal in driver

Hi everyone! I’m developing a KMDF driver

In the callback function SetCreateProcessNotifyRoutineEx (of
PsSetCreateProcessNotifyRoutineEx), I get the process name of the new
spawned process and send it to the usermode application by using inverted
call. After receiving the process name, the usermode application will start
another command line application and then notify the driver after doing
that, so the driver have to wait for the usermode app to do that, then let
the new process start to run. My question is, what is the best way to wait
for the notification of the usermode app in my driver?

Thank you!


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

>the usermode application will start another command line application and then notify the driver after doing that…

The callback will run in the context of the app in that case because the callback runs in the context of the creator and the driver will be “notified” by the OS rather than the app itself. The driver could pass a “key” to the app in the inverted call and the app would than pass the key back to the driver in the command line. This could be a method.


The operating system calls the driver’s process-notify routine at PASSIVE_LEVEL inside a critical region with normal kernel APCs disabled. When a process is created, the process-notify routine runs in the context of the thread that created the new process. When a process is deleted, the process-notify routine runs in the context of the last thread to exit from the process.

But as Mr Grig pointed out, the IOCTL request is the easiest method. Note that the input buffer of such a request could contain a driver generated key (recieved from the inverted call) for validation.

Hi! Thank you for your replies.

Slava Imameev: there seem to be new knowledge in your solution, so I’m trying to understand it.

Alex Grig: IOCTL is a good idea, but as Slava said, I’m in the SetCreateProcessNotifyRoutineEx callback, and wait for response from usermode before let the new process continue to run, so I don’t now how to handle if I receive an IOCTL.

D.T.: Oh, I forgot the key when using inverted call, so I’ll try it also.

Don Burn:

You’re right! Let me explain a little bit about my design:

I’m developing a WFP callout driver to filter HTTP, FTP traffic at ALE and STREAM layers by appId (FWPM_CONDITION_ALE_APP_ID) in order to monitor traffic of malicious application. I also have a usermode command-line app to input the application path.

My objective is to filter the malicious application only, but some of them start to spawn child processes, so I decided to clone the callout driver (also change all the GUIDs) and use SetCreateProcessNotifyRoutineEx to notify me when a new child process is spawned, then send the new process path to the usermode to start the cloned instance of the callout driver, then let the new process continue to run.

By that way, it’s possible for me to continue to filter if the new process spawns additional child processes in the future.

For example: filtering traffic for “C:\Windows\System32\cmd.exe” -> pass the app path to callout driver -> in cmd.exe, run ftp.exe -> cmd.exe spawns a child process which is “C:\Windows\System32\ftp.exe” -> in SetCreateProcessNotifyRoutineEx, pass this app path to usermode to start cloned instance of the callout driver -> let the new process continue to run -> if then ftp.exe spawns another child process -> continue to pass to another cloned of the callout driver to monitor traffic and so on.

Anyway, this is a design of 2-month experienced driver developer, so I need a lot of helps, please feel free to comment and guide me. Thank you!

Slava Imameev: I’ve got that, your idea is waiting in
SetCreateProcessNotifyRoutineEx. After user-mode app finishing its tasks,
it sends an IOCTL to notify the driver, then when processing that IOCTL,
signaling the event to stop waiting, right?

On Tue, Nov 1, 2016 at 9:42 AM, wrote:

> Hi! Thank you for your replies.
>
> Slava Imameev: there seem to be new knowledge in your solution, so I’m
> trying to understand it.
>
> Alex Grig: IOCTL is a good idea, but as Slava said, I’m in the
> SetCreateProcessNotifyRoutineEx callback, and wait for response from
> usermode before let the new process continue to run, so I don’t now how to
> handle if I receive an IOCTL.
>
> D.T.: Oh, I forgot the key when using inverted call, so I’ll try it also.
>
> Don Burn:
>
> You’re right! Let me explain a little bit about my design:
>
> I’m developing a WFP callout driver to filter HTTP, FTP traffic at ALE and
> STREAM layers by appId (FWPM_CONDITION_ALE_APP_ID) in order to monitor
> traffic of malicious application. I also have a usermode command-line app
> to input the application path.
>
> My objective is to filter the malicious application only, but some of them
> start to spawn child processes, so I decided to clone the callout driver
> (also change all the GUIDs) and use SetCreateProcessNotifyRoutineEx to
> notify me when a new child process is spawned, then send the new process
> path to the usermode to start the cloned instance of the callout driver,
> then let the new process continue to run.
>
> By that way, it’s possible for me to continue to filter if the new process
> spawns additional child processes in the future.
>
> For example: filtering traffic for “C:\Windows\System32\cmd.exe” -> pass
> the app path to callout driver -> in cmd.exe, run ftp.exe -> cmd.exe spawns
> a child process which is “C:\Windows\System32\ftp.exe” -> in
> SetCreateProcessNotifyRoutineEx, pass this app path to usermode to start
> cloned instance of the callout driver -> let the new process continue to
> run -> if then ftp.exe spawns another child process -> continue to pass to
> another cloned of the callout driver to monitor traffic and so on.
>
> Anyway, this is a design of 2-month experienced driver developer, so I
> need a lot of helps, please feel free to comment and guide me. Thank you!
>
>
>
> —
> 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:>

You have to understand that the callback runs in the context of the creator. This means that the driver is aware of the child process creation before the user app actually notifies it. The callback is in CreateProcess’s execution path but when the callback runs, the process execution has not yet started.

So your driver could queue some data about the new process being created and just block in the callback, waiting for the user app to “decide” and then, based on the app “decision”, either let the new process run or call ZwTerminateProcess to stop the newly created process.

You could actually implement this without using neither direct nor inverted calls. Just queuing and synchronizing.

But there is still a question to be answered ?

What happens to the EPROCESS object if your callback calls ZwTerminateProcess ? All registred callbacks are called sequencially by the OS. So other callbacks may run after yours.

In latest versions of Windows you can “exit” a process from within its initial thread.


The?PsSetCreateThreadNotifyRoutineExroutine differs from PsSetCreateThreadNotifyRoutine
?in the context in which the callback is executed. With PsSetCreateThreadNotifyRoutine, the callback is executed on the creator thread. With?PsSetCreateThreadNotifyRoutineEx, the callback is executed on the newly created thread.

Correct.