IoAllocateErrorLogEntry memory bug check

Hi All,
I have written a volume filter driver. The source includes the function
for logging the evente and errors to the event viewer. This function and the
driver works fine but somtimes the call to the logging function results into
a BugCheck 19, {20, 821be868, 821be928, a18000a}. The second parameter i.e.
the corrupt pool header 821be868 is the memory allocated by the call
IoAllocateErrorLogEntry. According to the BugCheck documentation the pool
header specified by the second parameter is already corrupt at the time of
access.
From the dump I can see that the BugCheck occurs when the memory allocated
by IoAllocateErrorLogEntry is tried to free.

f88a6c60 8088c76c 00000019 00000020 821be868 nt!KeBugCheckEx+0x1b
f88a6cc4 808ef23d 821be870 00000000 8089de90 nt!ExFreePoolWithTag+0x436
f88a6d80 8087a469 00000000 00000000 827a3b40 nt!IopErrorLogThread+0x3cd
f88a6dac 8094095c 00000000 00000000 00000000 nt!ExpWorkerThread+0xeb
f88a6ddc 8088757a 8087a37e 00000001 00000000 nt!PspSystemThreadStartup+0x2e
00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16

The following is the code for my logging function. In my function I am
specifying the dump data size 0,but still there is data displaying in my
property sheet for the events logged using this function.

Can anybody help me in this?

Thanks,
Giri.

void CjLogEvent(ULONG ErrorCode,PVOID pObject,USHORT NoOfParameters,…)
{
PCjDEVCOMMONHEADER pCommonHeader;
PIO_ERROR_LOG_PACKET pIoLogPacket;
va_list vpArguments;
PCHAR pFormatString;
PWCHAR pInsertionString,pSeprator;
CHAR Buffer[100];
NTSTATUS Status;

ENTRY(CJLogEvent);

ASSERT(pObject);

CjDbgPrint(DBG_FAILURE,(“\ncjDebug : EnrySize %d”,ERROR_LOG_MAXIMUM_SIZE

  • 1));

pIoLogPacket = IoAllocateErrorLogEntry(pObject,ERROR_LOG_MAXIMUM_SIZE -
1);
if (NULL == pIoLogPacket) {
CjDbgPrint(DBG_FAILURE,(“\ncjDebug : IoAllocateErrorLogEntry()
failed”));
return;
}

RtlZeroMemory(pIoLogPacket,sizeof(IO_ERROR_LOG_PACKET));
/* Initialize the relevant IoLogPacket fields */
pIoLogPacket->ErrorCode = ErrorCode;
pIoLogPacket->NumberOfStrings = NoOfParameters;
pIoLogPacket->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
pIoLogPacket->DumpDataSize = 0;

if (pObject == CjDriverGlobalParams.JournalDriver) {
pIoLogPacket->EventCategory = CAT_DRIVER;
}else{
/* Looks to be a Device Object created by Us. */
pCommonHeader =
(PCjDEVCOMMONHEADER)((PDEVICE_OBJECT)pObject)->DeviceExtension;
switch(pCommonHeader->DeviceType) {
case CjDEVVOLFILTER:
pIoLogPacket->EventCategory = CAT_VOL_FILTER;
break;
case CjDEVCONTROLLTER:
pIoLogPacket->EventCategory = CAT_CONTROLLER;
break;
default:
pIoLogPacket->EventCategory = CAT_DRIVER;
break;
}
}

/* If parameters are present then insert the values in the IoLogPacket
*/
if (NoOfParameters) {
/* Initialize the arguments store */
va_start(vpArguments,NoOfParameters);

pFormatString = va_arg(vpArguments,PCHAR);
pInsertionString = (PWCHAR)((PCHAR)pIoLogPacket +
sizeof(IO_ERROR_LOG_PACKET));

/* convert the printf formated string into a character array */
Status = RtlStringCbVPrintfA(Buffer,
sizeof(Buffer),
pFormatString,
vpArguments);
ASSERT(NT_SUCCESS(Status));

mbstowcs(pInsertionString,Buffer,sizeof(Buffer));

pSeprator = wcschr(pInsertionString,L’@‘);
while(pSeprator)
{
*pSeprator = L’\0’;
pSeprator = wcschr(pSeprator+1,L’@');
}
va_end(vpArguments);
}

IoWriteErrorLogEntry(pIoLogPacket);
LEAVE(CJLogEvent);
return;
}

I think you could be overflowing the error log entry that you allocated.

Why are you allocating the packet with one less byte than
ERROR_LOG_MAXIMUM_SIZE?

The size of your buffer array should be
ERROR_LOG_MAXIMUM_SIZE-sizeof(IO_ERROR_LOG_PACKET)-1 (since you have the
-1 there for the allocation you need to take it into account when
determining how many characters will fit in your insertion string). But
then since you are converting CHAR to WCHAR for your insertion string,
the size of your data is double what you think it is, so divide the
number of bytes for Buffer by the size of a wide characater
(ERROR_LOG_MAXIMUM_SIZE-sizeof(IO_LOG_PACKET)-1/sizeof(WCHAR)). That’s
how many characters your pInsertionString can hold so you shouldn’t put
more characters than that in Buffer.

Beverly

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Giri
Sent: Tuesday, August 08, 2006 5:19 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] IoAllocateErrorLogEntry memory bug check

Hi All,
I have written a volume filter driver. The source includes the
function for logging the evente and errors to the event viewer. This
function and the driver works fine but somtimes the call to the logging
function results into a BugCheck 19, {20, 821be868, 821be928, a18000a}.
The second parameter i.e. the corrupt pool header 821be868 is the memory
allocated by the call IoAllocateErrorLogEntry. According to the BugCheck
documentation the pool header specified by the second parameter is
already corrupt at the time of access.
From the dump I can see that the BugCheck occurs when the memory
allocated by IoAllocateErrorLogEntry is tried to free.

f88a6c60 8088c76c 00000019 00000020 821be868 nt!KeBugCheckEx+0x1b
f88a6cc4 808ef23d 821be870 00000000 8089de90 nt!ExFreePoolWithTag+0x436
f88a6d80 8087a469 00000000 00000000 827a3b40 nt!IopErrorLogThread+0x3cd
f88a6dac 8094095c 00000000 00000000 00000000 nt!ExpWorkerThread+0xeb
f88a6ddc 8088757a 8087a37e 00000001 00000000
nt!PspSystemThreadStartup+0x2e 00000000 00000000 00000000 00000000
00000000 nt!KiThreadStartup+0x16

The following is the code for my logging function. In my function I am
specifying the dump data size 0,but still there is data displaying in my
property sheet for the events logged using this function.

Can anybody help me in this?

Thanks,
Giri.

void CjLogEvent(ULONG ErrorCode,PVOID pObject,USHORT NoOfParameters,…)
{
PCjDEVCOMMONHEADER pCommonHeader;
PIO_ERROR_LOG_PACKET pIoLogPacket;
va_list vpArguments;
PCHAR pFormatString;
PWCHAR pInsertionString,pSeprator;
CHAR Buffer[100];
NTSTATUS Status;

ENTRY(CJLogEvent);

ASSERT(pObject);

CjDbgPrint(DBG_FAILURE,(“\ncjDebug : EnrySize
%d”,ERROR_LOG_MAXIMUM_SIZE - 1));

pIoLogPacket =
IoAllocateErrorLogEntry(pObject,ERROR_LOG_MAXIMUM_SIZE - 1);
if (NULL == pIoLogPacket) {
CjDbgPrint(DBG_FAILURE,(“\ncjDebug : IoAllocateErrorLogEntry()
failed”));
return;
}

RtlZeroMemory(pIoLogPacket,sizeof(IO_ERROR_LOG_PACKET));
/* Initialize the relevant IoLogPacket fields */
pIoLogPacket->ErrorCode = ErrorCode;
pIoLogPacket->NumberOfStrings = NoOfParameters;
pIoLogPacket->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
pIoLogPacket->DumpDataSize = 0;

if (pObject == CjDriverGlobalParams.JournalDriver) {
pIoLogPacket->EventCategory = CAT_DRIVER;
}else{
/* Looks to be a Device Object created by Us. */
pCommonHeader =
(PCjDEVCOMMONHEADER)((PDEVICE_OBJECT)pObject)->DeviceExtension;
switch(pCommonHeader->DeviceType) {
case CjDEVVOLFILTER:
pIoLogPacket->EventCategory = CAT_VOL_FILTER;
break;
case CjDEVCONTROLLTER:
pIoLogPacket->EventCategory = CAT_CONTROLLER;
break;
default:
pIoLogPacket->EventCategory = CAT_DRIVER;
break;
}
}

/* If parameters are present then insert the values in the
IoLogPacket */
if (NoOfParameters) {
/* Initialize the arguments store */
va_start(vpArguments,NoOfParameters);

pFormatString = va_arg(vpArguments,PCHAR);
pInsertionString = (PWCHAR)((PCHAR)pIoLogPacket +
sizeof(IO_ERROR_LOG_PACKET));

/* convert the printf formated string into a character array */
Status = RtlStringCbVPrintfA(Buffer,
sizeof(Buffer),
pFormatString,
vpArguments);
ASSERT(NT_SUCCESS(Status));

mbstowcs(pInsertionString,Buffer,sizeof(Buffer));

pSeprator = wcschr(pInsertionString,L’@‘);
while(pSeprator)
{
*pSeprator = L’\0’;
pSeprator = wcschr(pSeprator+1,L’@');
}
va_end(vpArguments);
}

IoWriteErrorLogEntry(pIoLogPacket);
LEAVE(CJLogEvent);
return;
}

— Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the
List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

I missed some oarentheses in my recommendation:

Buffer should be
(ERROR_LOG_MAXIMUM_SIZE-sizeof(IO_LOG_PACKET)-1)/sizeof(WCHAR) bytes
big.

Beverly

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Brown, Beverly
Sent: Tuesday, August 08, 2006 8:29 AM
To: Windows System Software Devs Interest List
Subject: RE: [ntdev] IoAllocateErrorLogEntry memory bug check

I think you could be overflowing the error log entry that you allocated.

Why are you allocating the packet with one less byte than
ERROR_LOG_MAXIMUM_SIZE?

The size of your buffer array should be
ERROR_LOG_MAXIMUM_SIZE-sizeof(IO_ERROR_LOG_PACKET)-1 (since you have the
-1 there for the allocation you need to take it into account when
determining how many characters will fit in your insertion string). But
then since you are converting CHAR to WCHAR for your insertion string,
the size of your data is double what you think it is, so divide the
number of bytes for Buffer by the size of a wide characater
(ERROR_LOG_MAXIMUM_SIZE-sizeof(IO_LOG_PACKET)-1/sizeof(WCHAR)). That’s
how many characters your pInsertionString can hold so you shouldn’t put
more characters than that in Buffer.

Beverly

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Giri
Sent: Tuesday, August 08, 2006 5:19 AM
To: Windows System Software Devs Interest List
Subject: [ntdev] IoAllocateErrorLogEntry memory bug check

Hi All,
I have written a volume filter driver. The source includes the
function for logging the evente and errors to the event viewer. This
function and the driver works fine but somtimes the call to the logging
function results into a BugCheck 19, {20, 821be868, 821be928, a18000a}.
The second parameter i.e. the corrupt pool header 821be868 is the memory
allocated by the call IoAllocateErrorLogEntry. According to the BugCheck
documentation the pool header specified by the second parameter is
already corrupt at the time of access.
From the dump I can see that the BugCheck occurs when the memory
allocated by IoAllocateErrorLogEntry is tried to free.

f88a6c60 8088c76c 00000019 00000020 821be868 nt!KeBugCheckEx+0x1b
f88a6cc4 808ef23d 821be870 00000000 8089de90 nt!ExFreePoolWithTag+0x436
f88a6d80 8087a469 00000000 00000000 827a3b40 nt!IopErrorLogThread+0x3cd
f88a6dac 8094095c 00000000 00000000 00000000 nt!ExpWorkerThread+0xeb
f88a6ddc 8088757a 8087a37e 00000001 00000000
nt!PspSystemThreadStartup+0x2e 00000000 00000000 00000000 00000000
00000000 nt!KiThreadStartup+0x16

The following is the code for my logging function. In my function I am
specifying the dump data size 0,but still there is data displaying in my
property sheet for the events logged using this function.

Can anybody help me in this?

Thanks,
Giri.

void CjLogEvent(ULONG ErrorCode,PVOID pObject,USHORT NoOfParameters,…)
{
PCjDEVCOMMONHEADER pCommonHeader;
PIO_ERROR_LOG_PACKET pIoLogPacket;
va_list vpArguments;
PCHAR pFormatString;
PWCHAR pInsertionString,pSeprator;
CHAR Buffer[100];
NTSTATUS Status;

ENTRY(CJLogEvent);

ASSERT(pObject);

CjDbgPrint(DBG_FAILURE,(“\ncjDebug : EnrySize
%d”,ERROR_LOG_MAXIMUM_SIZE - 1));

pIoLogPacket =
IoAllocateErrorLogEntry(pObject,ERROR_LOG_MAXIMUM_SIZE - 1);
if (NULL == pIoLogPacket) {
CjDbgPrint(DBG_FAILURE,(“\ncjDebug : IoAllocateErrorLogEntry()
failed”));
return;
}

RtlZeroMemory(pIoLogPacket,sizeof(IO_ERROR_LOG_PACKET));
/* Initialize the relevant IoLogPacket fields */
pIoLogPacket->ErrorCode = ErrorCode;
pIoLogPacket->NumberOfStrings = NoOfParameters;
pIoLogPacket->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
pIoLogPacket->DumpDataSize = 0;

if (pObject == CjDriverGlobalParams.JournalDriver) {
pIoLogPacket->EventCategory = CAT_DRIVER;
}else{
/* Looks to be a Device Object created by Us. */
pCommonHeader =
(PCjDEVCOMMONHEADER)((PDEVICE_OBJECT)pObject)->DeviceExtension;
switch(pCommonHeader->DeviceType) {
case CjDEVVOLFILTER:
pIoLogPacket->EventCategory = CAT_VOL_FILTER;
break;
case CjDEVCONTROLLTER:
pIoLogPacket->EventCategory = CAT_CONTROLLER;
break;
default:
pIoLogPacket->EventCategory = CAT_DRIVER;
break;
}
}

/* If parameters are present then insert the values in the
IoLogPacket */
if (NoOfParameters) {
/* Initialize the arguments store */
va_start(vpArguments,NoOfParameters);

pFormatString = va_arg(vpArguments,PCHAR);
pInsertionString = (PWCHAR)((PCHAR)pIoLogPacket +
sizeof(IO_ERROR_LOG_PACKET));

/* convert the printf formated string into a character array */
Status = RtlStringCbVPrintfA(Buffer,
sizeof(Buffer),
pFormatString,
vpArguments);
ASSERT(NT_SUCCESS(Status));

mbstowcs(pInsertionString,Buffer,sizeof(Buffer));

pSeprator = wcschr(pInsertionString,L’@‘);
while(pSeprator)
{
*pSeprator = L’\0’;
pSeprator = wcschr(pSeprator+1,L’@');
}
va_end(vpArguments);
}

IoWriteErrorLogEntry(pIoLogPacket);
LEAVE(CJLogEvent);
return;
}

— Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256 To unsubscribe, visit the
List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer


Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256

To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer

Maybe your insertion strings overflow ERROR_LOG_MAXIMUM_SIZE.

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

----- Original Message -----
From: “Giri”
To: “Windows System Software Devs Interest List”
Sent: Tuesday, August 08, 2006 1:19 PM
Subject: [ntdev] IoAllocateErrorLogEntry memory bug check

> Hi All,
> I have written a volume filter driver. The source includes the function
> for logging the evente and errors to the event viewer. This function and the
> driver works fine but somtimes the call to the logging function results into
> a BugCheck 19, {20, 821be868, 821be928, a18000a}. The second parameter i.e.
> the corrupt pool header 821be868 is the memory allocated by the call
> IoAllocateErrorLogEntry. According to the BugCheck documentation the pool
> header specified by the second parameter is already corrupt at the time of
> access.
> From the dump I can see that the BugCheck occurs when the memory allocated
> by IoAllocateErrorLogEntry is tried to free.
>
> f88a6c60 8088c76c 00000019 00000020 821be868 nt!KeBugCheckEx+0x1b
> f88a6cc4 808ef23d 821be870 00000000 8089de90 nt!ExFreePoolWithTag+0x436
> f88a6d80 8087a469 00000000 00000000 827a3b40 nt!IopErrorLogThread+0x3cd
> f88a6dac 8094095c 00000000 00000000 00000000 nt!ExpWorkerThread+0xeb
> f88a6ddc 8088757a 8087a37e 00000001 00000000 nt!PspSystemThreadStartup+0x2e
> 00000000 00000000 00000000 00000000 00000000 nt!KiThreadStartup+0x16
>
>
> The following is the code for my logging function. In my function I am
> specifying the dump data size 0,but still there is data displaying in my
> property sheet for the events logged using this function.
>
> Can anybody help me in this?
>
> Thanks,
> Giri.
>
> void CjLogEvent(ULONG ErrorCode,PVOID pObject,USHORT NoOfParameters,…)
> {
> PCjDEVCOMMONHEADER pCommonHeader;
> PIO_ERROR_LOG_PACKET pIoLogPacket;
> va_list vpArguments;
> PCHAR pFormatString;
> PWCHAR pInsertionString,pSeprator;
> CHAR Buffer[100];
> NTSTATUS Status;
>
> ENTRY(CJLogEvent);
>
> ASSERT(pObject);
>
> CjDbgPrint(DBG_FAILURE,(“\ncjDebug : EnrySize %d”,ERROR_LOG_MAXIMUM_SIZE
> - 1));
>
>
> pIoLogPacket = IoAllocateErrorLogEntry(pObject,ERROR_LOG_MAXIMUM_SIZE -
> 1);
> if (NULL == pIoLogPacket) {
> CjDbgPrint(DBG_FAILURE,(“\ncjDebug : IoAllocateErrorLogEntry()
> failed”));
> return;
> }
>
> RtlZeroMemory(pIoLogPacket,sizeof(IO_ERROR_LOG_PACKET));
> /* Initialize the relevant IoLogPacket fields /
> pIoLogPacket->ErrorCode = ErrorCode;
> pIoLogPacket->NumberOfStrings = NoOfParameters;
> pIoLogPacket->StringOffset = sizeof(IO_ERROR_LOG_PACKET);
> pIoLogPacket->DumpDataSize = 0;
>
> if (pObject == CjDriverGlobalParams.JournalDriver) {
> pIoLogPacket->EventCategory = CAT_DRIVER;
> }else{
> /
Looks to be a Device Object created by Us. /
> pCommonHeader =
> (PCjDEVCOMMONHEADER)((PDEVICE_OBJECT)pObject)->DeviceExtension;
> switch(pCommonHeader->DeviceType) {
> case CjDEVVOLFILTER:
> pIoLogPacket->EventCategory = CAT_VOL_FILTER;
> break;
> case CjDEVCONTROLLTER:
> pIoLogPacket->EventCategory = CAT_CONTROLLER;
> break;
> default:
> pIoLogPacket->EventCategory = CAT_DRIVER;
> break;
> }
> }
>
> /
If parameters are present then insert the values in the IoLogPacket
> /
> if (NoOfParameters) {
> /
Initialize the arguments store /
> va_start(vpArguments,NoOfParameters);
>
> pFormatString = va_arg(vpArguments,PCHAR);
> pInsertionString = (PWCHAR)((PCHAR)pIoLogPacket +
> sizeof(IO_ERROR_LOG_PACKET));
>
> /
convert the printf formated string into a character array */
> Status = RtlStringCbVPrintfA(Buffer,
> sizeof(Buffer),
> pFormatString,
> vpArguments);
> ASSERT(NT_SUCCESS(Status));
>
> mbstowcs(pInsertionString,Buffer,sizeof(Buffer));
>
> pSeprator = wcschr(pInsertionString,L’@‘);
> while(pSeprator)
> {
> *pSeprator = L’\0’;
> pSeprator = wcschr(pSeprator+1,L’@');
> }
> va_end(vpArguments);
> }
>
> IoWriteErrorLogEntry(pIoLogPacket);
> LEAVE(CJLogEvent);
> return;
> }
>
> —
> Questions? First check the Kernel Driver FAQ at
http://www.osronline.com/article.cfm?id=256
>
> To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer