I made some changes to my control device object to support overlapped
calls of DeviceIoControl, and I seem to have introduced a pool
corruption bug somewhere. I have driver verifier on with pool tracking,
and I’ve enabled special pool for all of my tags, and I cannot find the
problem.
The symptom I’m seeing (3 times now, consistently) is that I get a
bugcheck DRIVER_CORRUPTED_EXPOOL (c5), with a very specific address
(0x107) and the problem is happening in ExAllocatePoolWithTag for a call
to NtQueryVolumeInformationFile. My driver isn’t on the call stack, so
I have to assume it corrupted the pool earlier. The code that’s
exposing the problem is our code, but it’s not mine and I don’t have
symbols at the moment. I am pretty sure it’s not directly invoking
anything of mine at any point though. I’ll fill in on this point
tomorrow morning once I can talk to the guy who does that stuff.
If anybody sees any glaring errors in the code below, or can glean any
useful information from the !analyze, please fill me in. At this point,
I can only guess that I’m corrupting the pool with my handling of
workitem allocation and freeing, but I can’t see a way to get a tag on
that allocation, despite the fact that pooltag.txt lists some tags for
various workitems.
Thanks,
~Eric
typedef struct write_ctx {
PIRP irp;
PIO_STACK_LOCATION irp_sp;
EHR_WRITE_ARGS *args;
PIO_WORKITEM wi;
} write_ctx_t;
static NTSTATUS ehr_file_write_async (PDEVICE_OBJECT device, PIRP irp,
PIO_STACK_LOCATION irp_sp, EHR_WRITE_ARGS *args)
{
// NOT STATUS_SUCCESS, we have to return S_P if we
IoMarkIrpPending
NTSTATUS status = STATUS_PENDING;
write_ctx_t *wctx = NULL;
// TODO: use a lookaside list
wctx = ExAllocatePoolWithTag (PagedPool, sizeof (write_ctx_t),
EHR_WRITE_CTX_TAG);
TEST_ALLOC_AND_ABORT (wctx);
wctx->wi = IoAllocateWorkItem (device);
TEST_ALLOC_AND_ABORT (wctx->wi);
wctx->irp = irp;
wctx->irp_sp = irp_sp;
wctx->args = args;
IoMarkIrpPending (irp);
IoQueueWorkItem (wctx->wi, ehr_file_write_async_worker,
DelayedWorkQueue,
wctx);
out:
if (status != STATUS_PENDING) {
if (wctx->wi) {
IoFreeWorkItem (wctx->wi);
}
if (wctx) {
DBG_PRINT_WRAPPER ((“\n\n>>> FREED wctx in
write_async!!! <<<\n\n”));
ExFreePoolWithTag (wctx, EHR_WRITE_CTX_TAG);
}
}
return status;
}
static VOID ehr_file_write_async_worker (PDEVICE_OBJECT device, VOID
*ctx)
{
NTSTATUS status;
write_ctx_t *wctx = (write_ctx_t *) ctx;
status = ehr_file_write_sync (wctx->irp, wctx->irp_sp,
wctx->args);
wctx->irp->IoStatus.Status = status;
IoFreeWorkItem (wctx->wi);
IoCompleteRequest (wctx->irp, IO_NO_INCREMENT);
ExFreePoolWithTag (wctx, EHR_WRITE_CTX_TAG);
}
************************************************************************
*******
*
*
* Bugcheck Analysis
*
*
*
************************************************************************
*******
Use !analyze -v to get detailed debugging information.
BugCheck C5, {107, d0000002, 1, 808933b7}
*** ERROR: Symbol file could not be found. Defaulted to export symbols
for OurDLL.dll -
*** ERROR: Module load completed but symbols could not be loaded for
OurService.exe
************************************************************************
*
***
***
***
***
*** Your debugger is not using the correct symbols
***
***
***
*** In order for this command to work properly, your symbol path
***
*** must point to .pdb files that have full type information.
***
***
***
*** Certain .pdb files (such as the public OS symbols) do not
***
*** contain the required information. Contact the group that
***
*** provided you with these symbols if you need this command to
***
*** work.
***
***
***
*** Type referenced: kernel32!pNlsUserInfo
***
***
***
************************************************************************
*
************************************************************************
*
***
***
***
***
*** Your debugger is not using the correct symbols
***
***
***
*** In order for this command to work properly, your symbol path
***
*** must point to .pdb files that have full type information.
***
***
***
*** Certain .pdb files (such as the public OS symbols) do not
***
*** contain the required information. Contact the group that
***
*** provided you with these symbols if you need this command to
***
*** work.
***
***
***
*** Type referenced: kernel32!pNlsUserInfo
***
***
***
************************************************************************
*
Probably caused by : ntkrpamp.exe ( nt!ExAllocatePoolWithTag+83f )
Followup: MachineOwner
nt!RtlpBreakWithStatusInstruction:
80871f20 cc int 3
kd> !analyze -v
************************************************************************
*******
*
*
* Bugcheck Analysis
*
*
*
************************************************************************
*******
DRIVER_CORRUPTED_EXPOOL (c5)
An attempt was made to access a pageable (or completely invalid) address
at an interrupt request level (IRQL) that is too high. This is caused
by drivers that have corrupted the system pool. Run the driver verifier
against any new (or suspect) drivers, and if that doesn’t turn up the
culprit, then use gflags to enable special pool.
Arguments:
Arg1: 00000107, memory referenced
Arg2: d0000002, IRQL
Arg3: 00000001, value 0 = read operation, 1 = write operation
Arg4: 808933b7, address which referenced memory
Debugging Details:
************************************************************************
*
***
***
***
***
*** Your debugger is not using the correct symbols
***
***
***
*** In order for this command to work properly, your symbol path
***
*** must point to .pdb files that have full type information.
***
***
***
*** Certain .pdb files (such as the public OS symbols) do not
***
*** contain the required information. Contact the group that
***
*** provided you with these symbols if you need this command to
***
*** work.
***
***
***
*** Type referenced: kernel32!pNlsUserInfo
***
***
***
************************************************************************
*
************************************************************************
*
***
***
***
***
*** Your debugger is not using the correct symbols
***
***
***
*** In order for this command to work properly, your symbol path
***
*** must point to .pdb files that have full type information.
***
***
***
*** Certain .pdb files (such as the public OS symbols) do not
***
*** contain the required information. Contact the group that
***
*** provided you with these symbols if you need this command to
***
*** work.
***
***
***
*** Type referenced: kernel32!pNlsUserInfo
***
***
***
************************************************************************
*
BUGCHECK_STR: 0xC5_D0000002
CURRENT_IRQL: 2
FAULTING_IP:
nt!ExAllocatePoolWithTag+83f
808933b7 897004 mov dword ptr [eax+4],esi
DEFAULT_BUCKET_ID: DRIVER_FAULT
PROCESS_NAME: OurService.exe
TRAP_FRAME: ba84bbfc – (.trap 0xffffffffba84bbfc) ErrCode = 00000002
eax=00000103 ebx=808aeae0 ecx=808b4180 edx=00000045 esi=808aed30
edi=81c8e488
eip=808933b7 esp=ba84bc70 ebp=ba84bcac iopl=0 nv up ei pl nz na
po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
efl=00010202
nt!ExAllocatePoolWithTag+0x83f:
808933b7 897004 mov dword ptr [eax+4],esi
ds:0023:00000107=???
Resetting default scope
LAST_CONTROL_TRANSFER: from 80826967 to 80871f20
STACK_TEXT:
ba84b7f8 80826967 00000003 00000000 00000000
nt!RtlpBreakWithStatusInstruction
ba84b844 8082786b 00000003 00000107 808933b7
nt!KiBugCheckDebugBreak+0x19
ba84bbdc 8088c963 0000000a 00000107 d0000002 nt!KeBugCheck2+0x5e1
ba84bbdc 808933b7 0000000a 00000107 d0000002 nt!KiTrap0E+0x2a7
ba84bcac 8087ed00 00000008 00000000 20206f49
nt!ExAllocatePoolWithTag+0x83f
ba84bcd0 808f1c0e 8196bd88 0000021a 20206f49
nt!ExAllocatePoolWithQuotaTag+0x5a
ba84bd48 8088978c 00000174 0013f150 0018c5a0
nt!NtQueryVolumeInformationFile+0x382
ba84bd48 7c8285ec 00000174 0013f150 0018c5a0 nt!KiFastCallEntry+0xfc
0013f10c 7c82772b 77e4b71e 00000174 0013f150 ntdll!KiFastSystemCallRet
0013f110 77e4b71e 00000174 0013f150 0018c5a0
ntdll!NtQueryVolumeInformationFile+0xc
0013f1a0 77e43b68 7ffdec00 001b0940 00000206
kernel32!GetVolumeInformationW+0x237
0013f220 110c4de2 0018a634 001842dc 00000103
kernel32!GetVolumeInformationA+0xf0
WARNING: Stack unwind information not available. Following frames may be
wrong.
0013f334 110b9a79 00182610 0013f770 73649cec
OurDLL!DllCanUnloadNow+0x80354
0013f8bc 0041847d 00182610 0013fb6c 0013fc3c
OurDLL!DllCanUnloadNow+0x74feb
0013fb60 735c1fb3 0015f868 0013fb7c 004044d6 OurService+0x1847d
0013fb7c 735c22b4 004044d6 0013fc38 00000002
MSVBVM60!tagAPRINTER::QueryInterface+0x193
0013fb94 735c239a 0015f8d4 0013fc78 0013fc38
MSVBVM60!CTL::QueryInterface+0x97
0013fc9c 735c28e7 00e913a4 00e9034c 00e85af8
MSVBVM60!CTL::QueryInterface+0x17d
0013fcc0 7362bd94 00e913a4 00000000 00000000
MSVBVM60!CTL::InternalRelease+0x29
0013fcd8 735cd0c6 00e913a4 00010056 00000113
MSVBVM60!CVBApplication::LoadUnload+0xc5
0013fd00 735cf855 00e913a4 00010056 00000113
MSVBVM60!MainHwndCreate+0x72
0013fd5c 7739b6e3 00010056 00000113 00010056 MSVBVM60!ShowMethShow+0xde
0013fd88 7739b874 735cf626 00010056 00000113
USER32!InternalCallWinProc+0x28
0013fe00 7739ba92 00000000 735cf626 00010056
USER32!UserCallWinProcCheckWow+0x151
0013fe68 773a16e5 0013fe90 00000001 0013feb8
USER32!DispatchMessageWorker+0x327
0013fe78 7357a4a3 0013fe90 ffffffff 00e8373c USER32!DispatchMessageA+0xf
0013feb8 7357a41a ffffffff 00e83764 00e80000
MSVBVM60!CLIENT::vftable'+0xb 0013fefc 7357a2f8 00e83834 ffffffff 000004cc MSVBVM60!FORM::
vftable’+0xa
0013ff18 7357a2c3 00e83760 00e83834 ffffffff
MSVBVM60!CTLDOC::vftable'+0x8 0013ff3c 7357361c ffffffff 00000000 00000000 MSVBVM60!CTLMENU::
vftable’+0x13
0013ffb8 00402222 00402aa0 77e6f23b 00000000
MSVBVM60!_CDIR_vtbl::`vftable’+0x144
0013fff0 00000000 00402218 00000000 78746341 OurService+0x2222
STACK_COMMAND: kb
FOLLOWUP_IP:
nt!ExAllocatePoolWithTag+83f
808933b7 897004 mov dword ptr [eax+4],esi
SYMBOL_STACK_INDEX: 4
SYMBOL_NAME: nt!ExAllocatePoolWithTag+83f
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: nt
IMAGE_NAME: ntkrpamp.exe
DEBUG_FLR_IMAGE_TIMESTAMP: 45ec0a19
FAILURE_BUCKET_ID: 0xC5_D0000002_VRF_nt!ExAllocatePoolWithTag+83f
BUCKET_ID: 0xC5_D0000002_VRF_nt!ExAllocatePoolWithTag+83f