Deadlock after calling ZwAllocateVirtualMemory

Dear List,

I would like to ask why following piece of code deadlocks after 3rd call to ZwAllocateVirtualMemory.
First two calls to ZwAllocateVirtualMemory are correct and memory is allocated. After doing next call the execution is not going back to my driver.

module_filter - function registered by PsSetLoadImageNotifyRoutine

pseudocode:

VOID module_filter(
PUNICODE_STRING FullImageName,
HANDLE ProcessId,
PIMAGE_INFO ImageInfo
)
{

PEPROCESS pEProcess;
KAPC_STATE apcState;
PVOID mem_base = NULL;
SIZE_T mem_size = 4096;
NTSTATUS st;

// filter unwanted
if (!check_name(FullImageName))
return;

PsLookupProcessByProcessId(ProcessId,&pEProcess);
KeStackAttachProcess(pEProcess,&apcState);

// it is not going back after first two calls
// happens always after “kernel32.dll” is loaded into usermode process

st = ZwAllocateVirtualMemory((HANDLE)-1,&mem_base,NULL,&mem_size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);

// ^---- DEADLOCK

KeUnstackDetachProcess(&apcState);
ObDereferenceObject(pEProcess);

}


thank you!

best regards,
DC


Ovi Mail: Free email account from Nokia
http://mail.ovi.com

Have you read WDK documentation on KeStackAttachProcess?
It clearly says: "Note that attaching a thread to a different process can
prevent asynchronous I/O operations from completing and can potentially
cause deadlocks. "
– pa

wrote in message news:xxxxx@ntdev…
>
>
>
> Dear List,
>
>
> I would like to ask why following piece of code deadlocks after 3rd call
> to ZwAllocateVirtualMemory.
> First two calls to ZwAllocateVirtualMemory are correct and memory is
> allocated. After doing next call the execution is not going back to my
> driver.
>
>
> module_filter - function registered by PsSetLoadImageNotifyRoutine
>
>
> pseudocode:
> ------------------------------------------------------------
> VOID module_filter(
> PUNICODE_STRING FullImageName,
> HANDLE ProcessId,
> PIMAGE_INFO ImageInfo
> )
> {
>
> PEPROCESS pEProcess;
> KAPC_STATE apcState;
> PVOID mem_base = NULL;
> SIZE_T mem_size = 4096;
> NTSTATUS st;
>
>
> // filter unwanted
> if (!check_name(FullImageName))
> return;
>
>
> PsLookupProcessByProcessId(ProcessId,&pEProcess);
> KeStackAttachProcess(pEProcess,&apcState);
>
> // it is not going back after first two calls
> // happens always after “kernel32.dll” is loaded into usermode process
>
> st =
> ZwAllocateVirtualMemory((HANDLE)-1,&mem_base,NULL,&mem_size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
>
> // ^---- DEADLOCK
>
> KeUnstackDetachProcess(&apcState);
> ObDereferenceObject(pEProcess);
>
> }
>
> ------------------------------------------------------------
>
>
> thank you!
>
> best regards,
> DC
>
> --------------------------------------------------------------
>
>

Hello Pavel,

I don’t think this is the issue here because even if i exchange KeStackAttachProcess method to ZwOpenProcess and then i execute ZwAllocateVirtualMemory with the new process handle it still deadlocks on 3rd ZwAllocateVirtualMemory call. Any ideas?

Sample output:


pid: 00000c20 base: 00400000 DLL: \Device\HarddiskVolume1\test.exe
Process handle: 00000004
Closing process
Memory allocated at 00150000 (size=00004000)

pid: 00000c20 BASE: 7c900000 DLL: \SystemRoot\System32\ntdll.dll
Process handle: 00000004
Closing process
Memory allocated at 00160000 (size=00004000)

pid: 00000c20 BASE: 7c800000 DLL: \WINDOWS\system32\kernel32.dll
Process handle: 00000014
–> dead lock <—

  • DC

----- Original message -----
From: “Pavel A.‎”
> To: “Windows System Software Devs Interest List‎”
> Subject: Re:[ntdev] Deadlock after calling ZwAllocateVirtualMemory
> Date: Fri, 4 Jun 2010 00:39:11 +0300
>
>
>Have you read WDK documentation on KeStackAttachProcess?
> It clearly says: "Note that attaching a thread to a different
> process can prevent asynchronous I/O operations from completing and
> can potentially cause deadlocks. "
> – pa
>
> wrote in message news:xxxxx@ntdev…
> >
> >
> >
> > Dear List,
> >
> >
> > I would like to ask why following piece of code deadlocks after 3rd
> > call to ZwAllocateVirtualMemory.
> > First two calls to ZwAllocateVirtualMemory are correct and memory
> > is allocated. After doing next call the execution is not going back
> > to my driver.
> >
> >
> > module_filter - function registered by PsSetLoadImageNotifyRoutine
> >
> >
> > pseudocode:
> > ------------------------------------------------------------
> > VOID module_filter(
> > PUNICODE_STRING FullImageName,
> > HANDLE ProcessId,
> > PIMAGE_INFO ImageInfo
> > )
> > {
> >
> > PEPROCESS pEProcess;
> > KAPC_STATE apcState;
> > PVOID mem_base = NULL;
> > SIZE_T mem_size = 4096;
> > NTSTATUS st;
> >
> >
> > // filter unwanted
> > if (!check_name(FullImageName))
> > return;
> >
> >
> > PsLookupProcessByProcessId(ProcessId,&pEProcess);
> > KeStackAttachProcess(pEProcess,&apcState);
> >
> > // it is not going back after first two calls
> > // happens always after “kernel32.dll” is loaded into usermode process
> >
> > st =
> > ZwAllocateVirtualMemory((HANDLE)-1,&mem_base,NULL,&mem_size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
> >
> > // ^---- DEADLOCK
> >
> > KeUnstackDetachProcess(&apcState);
> > ObDereferenceObject(pEProcess);
> >
> > }
> >
> > ------------------------------------------------------------
> >
> >
> > thank you!
> >
> > best regards,
> > DC
> >
> > --------------------------------------------------------------
> >
> >
>
> —
> 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
>

--------------------------------------------------------------
Ovi Mail: Create an account directly from your phone
http://mail.ovi.com

Well i think i’ve found the reason of the deadlock. I’ve assumed the callback function is always executed at PASSIVE IRQL LEVEL. However after first two loaded modules, IRQL raises to APC LEVEL :frowning:

  • DC

----- Original message -----
From: xxxxx@ovi.com
To: “Windows System Software Devs Interest List‎”
> Subject: Re:[ntdev] Deadlock after calling ZwAllocateVirtualMemory
> Date: Fri, 04 Jun 2010 08:05:36 +0200
>
>
>Hello Pavel,
>
> I don’t think this is the issue here because even if i exchange
> KeStackAttachProcess method to ZwOpenProcess and then i execute
> ZwAllocateVirtualMemory with the new process handle it still
> deadlocks on 3rd ZwAllocateVirtualMemory call. Any ideas?
>
> Sample output:
>
> -------------------------------------
> pid: 00000c20 base: 00400000 DLL: \Device\HarddiskVolume1\test.exe
> Process handle: 00000004
> Closing process
> Memory allocated at 00150000 (size=00004000)
> -------------------------------------
> pid: 00000c20 BASE: 7c900000 DLL: \SystemRoot\System32\ntdll.dll
> Process handle: 00000004
> Closing process
> Memory allocated at 00160000 (size=00004000)
> -------------------------------------
> pid: 00000c20 BASE: 7c800000 DLL: \WINDOWS\system32\kernel32.dll
> Process handle: 00000014
> –> dead lock <—
>
>
> - DC
>
>
> > ----- Original message ----- From: “Pavel A.‎”
> > To: “Windows System Software Devs Interest List‎”
> > Subject: Re:[ntdev] Deadlock after calling ZwAllocateVirtualMemory
> > Date: Fri, 4 Jun 2010 00:39:11 +0300
> >
> >
> > Have you read WDK documentation on KeStackAttachProcess?
> > It clearly says: "Note that attaching a thread to a different
> > process can prevent asynchronous I/O operations from completing and
> > can potentially cause deadlocks. "
> > – pa
> >
> > wrote in message news:xxxxx@ntdev…
> > >
> > >
> > >
> > > Dear List,
> > >
> > >
> > > I would like to ask why following piece of code deadlocks after
> > 3rd > call to ZwAllocateVirtualMemory.
> > > First two calls to ZwAllocateVirtualMemory are correct and memory
> > > is allocated. After doing next call the execution is not going
> > back > to my driver.
> > >
> > >
> > > module_filter - function registered by PsSetLoadImageNotifyRoutine
> > >
> > >
> > > pseudocode:
> > > ------------------------------------------------------------
> > > VOID module_filter(
> > > PUNICODE_STRING FullImageName,
> > > HANDLE ProcessId,
> > > PIMAGE_INFO ImageInfo
> > > )
> > > {
> > >
> > > PEPROCESS pEProcess;
> > > KAPC_STATE apcState;
> > > PVOID mem_base = NULL;
> > > SIZE_T mem_size = 4096;
> > > NTSTATUS st;
> > >
> > >
> > > // filter unwanted
> > > if (!check_name(FullImageName))
> > > return;
> > >
> > >
> > > PsLookupProcessByProcessId(ProcessId,&pEProcess);
> > > KeStackAttachProcess(pEProcess,&apcState);
> > >
> > > // it is not going back after first two calls
> > > // happens always after “kernel32.dll” is loaded into usermode process
> > >
> > > st = >
> > ZwAllocateVirtualMemory((HANDLE)-1,&mem_base,NULL,&mem_size,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);
> > >
> > > // ^---- DEADLOCK
> > >
> > > KeUnstackDetachProcess(&apcState);
> > > ObDereferenceObject(pEProcess);
> > >
> > > }
> > >
> > > ------------------------------------------------------------
> > >
> > >
> > > thank you!
> > >
> > > best regards,
> > > DC
> > >
> > > --------------------------------------------------------------
> > >
> > >
> >
> > —
> > 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
> >
>
> --------------------------------------------------------------
> Ovi Mail: Create an account directly from your phone
> http://mail.ovi.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
>

--------------------------------------------------------------
Ovi Mail: Free email account from Nokia
http://mail.ovi.com

> Well i think i’ve found the reason of the deadlock. I’ve assumed the

callback function is always executed at PASSIVE IRQL LEVEL. However
after first two loaded modules, IRQL raises to APC LEVEL :frowning:

This is a known limitation. For user image loads the callback is
invoked with the process address space lock held, so you can’t
call any APIs which might directly or indirectly try to acquire
the same lock.

The only solution is to defer the operation and perform it outside
of the callback (post it to a work item, etc).


Pavel Lebedinsky/Windows Fundamentals Test