Hello,
I have a very sporadic crash (I’ve seen it about 5 times in two months) and
I can’t recreate it. The crash is caused by an unhandled exception as code
in RtlNextUnicodePrefix attempts to reference a null pointer. If anyone out
there has internal implementation knowledge of the RtlGenericTablePackage
and can help me unravel what has happened here, I would be most
appreciative!
In the dissassembly below, EAX contains a
RtlGenericTable.LastNextEntry.NextPrefixTree. This pointer is NULL.
Evidently, the routine does not expect this pointer to be null.
805012f4 8b4608 mov eax,[esi+0x8] //move
GenericTable.LastNextEntry into eax
805012f7 83c00c add eax,0xc //poing eax at
LastNextEntry.RtlSplayLinks
805012fa 8b08 mov ecx,[eax]
805012fc 3bc8 cmp ecx,eax
805012fe 7404 jz ntoskrnl!RtlNextUnicodePrefix+0x3a
(80501304)
80501300 8bc1 mov eax,ecx
80501302 ebf6 jmp ntoskrnl!RtlNextUnicodePrefix+0x30
(805012fa)
80501304 8b40f8 mov eax,[eax-0x8] //point eax at
LastNextEntry.NextPrefixTree
80501307 6683780200 cmp word ptr [eax+0x2],0x0
//LastNextEntry.NextPrefixTree is NULL (BOOM!)
Here is the stack dumps involved:
kd> kv
ChildEBP RetAddr Args to Child
ed4dd7fc 80453390 ed4dd824 8045e1ef ed4dd82c
ntoskrnl!PspUnhandledExceptionInSystemThread+0x18 (FPO: [1,0,0])
ed4ddddc 804671c2 ed504e2a 00000000 00000000
ntoskrnl!PspSystemThreadStartup+0x5e (FPO: [Non-Fpo])
00000000 00000000 00000000 00000000 00000000 ntoskrnl!KiThreadStartup+0x16
kd> dd ed4dd824
ed4dd824 ed4ddcac ed4dd904 ed4dd850 8046765b
ed4dd834 ed4ddcac ed4dddcc ed4dd904 ed4dd8c8
ed4dd844 ed4ddc80 8046766f ed4dddcc ed4dd8d8
ed4dd854 8045a14e ed4ddcac ed4dddcc ed4dd904
ed4dd864 ed4dd8c8 8045e1a4 ed4ddcac ed4ddd00
ed4dd874 00000000 8046b200 ed4dd800 00000000
ed4dd884 e26914f0 ed4dd8dc 8049b8c5 02000000
ed4dd894 00000000 e26914f0 ed4dd8cc 00000002
kd> .cxr ed4dd904
eax=00000000 ebx=8199bfa4 ecx=e12b3c64 edx=e26b98e4 esi=8199bfa4
edi=e12b3c58
eip=80501307 esp=ed4ddd74 ebp=805012ca iopl=0 nv up ei pl zr na po
nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000
efl=00010246
ntoskrnl!RtlNextUnicodePrefix+3d:
80501307 6683780200 cmp word ptr [eax+0x2],0x0
kd> kv
*** Stack trace for last set context - .thread resets it
ChildEBP RetAddr Args to Child
ed4ddd74 ed507dbc 8199bfa4 00000000 8199bfc8
ntoskrnl!RtlNextUnicodePrefix+0x3d (FPO: [2,0,1])
ed4ddd90 ed504e91 8199bf00 00000000 00000000 FileSent!FsTrimPrefixTable+0x26
(FPO: [EBP 0xed50b840] [1,0,4])
ed4ddda8 8045336a 00000000 00000000 00000000 FileSent!FsWorkerThread+0x67
(FPO: [EBP 0xed4ddddc] [1,0,4])
ed4ddddc 804671c2 ed504e2a 00000000 00000000
ntoskrnl!PspSystemThreadStartup+0x69 (FPO: [Non-Fpo])
00000000 00000000 00000000 00000000 00000000 ntoskrnl!KiThreadStartup+0x16
The crash occurs in FsTrimPrefixTable, so naturally I am suspicious of that
function. This function loops through the table every so often, and removes
prefixes that have not been accessed for a while. The problem does not seem
to be one of synchronization, as there is clearly no memory corruption
(there is no variation in the crash). One thing that I am doing that seems
a bit dubious, is I am deleting the prefixes while enumerating the list with
RtlNextUnicodePrefix.
However, after running for days under heavy stress with driver verifier, the
code never breaks. The crash ONLY occurs when the system first starts. Is
there anything obviously wrong with this code??? In not, can anyone guess
how my prefix table got into this state?
void FsTrimPrefixTable(PFSENT_FILTER_EXTENSION pExt)
{
PUNICODE_PREFIX_TABLE_ENTRY pEntry;
PFSENT_PREFIX_TABLE_ENTRY pFsEntry;
BOOLEAN bLocked = FALSE;
SAFE_LOCK(&pExt->Hdr.Lock, &bLocked);
for (pEntry = RtlNextUnicodePrefix (&pExt->PrefixTable, TRUE);
pEntry != NULL;
pEntry = RtlNextUnicodePrefix(&pExt->PrefixTable, FALSE))
{
pFsEntry = CONTAINING_RECORD(pEntry, FSENT_PREFIX_TABLE_ENTRY,
Entry);
//if the accessed or static bit is not set, remove the entry
if (!(FsIsPrefixAccessedBitSet(pFsEntry) ||
FsIsPrefixStaticBitSet(pFsEntry)))
{
if (pFsEntry->Id.QuadPart != FSENT_BAD_ID && pFsEntry->pRefFo)
{
ObDereferenceObject(pFsEntry->pRefFo);
}
RtlRemoveUnicodePrefix(&pExt->PrefixTable, pEntry);
ExFreePool(pFsEntry);
}
else
{
FsClearPrefixAccessedBit(pFsEntry);
}
}
SAFE_UNLOCK(&pExt->Hdr.Lock, &bLocked);
}
Here is a dump of the UNICODE_PREFIX_TABLE:
kd> dd 8199bfa4
8199bfa4 00000800 e138f0f8 e12b3c58 8199bfb0
8199bfb4 8199bfb0 0000c79f 00000004 0030002e
8199bfc4 e26697c8 ed50b8e0 ed50b8e0 0000000d
8199bfd4 8199be40 00000000 00000000 00000000
8199bfe4 00000000 844c8460 00000000 00000000
8199bff4 00000000 00000000 00000000 00000000
8199c004 00000000 00000000 00000000 00000000
8199c014 00000000 00000000 00000000 00000000
And a dump of PrefixTable.LastNextEntry:
kd> dd e12b3c58
e12b3c58 00020803 00000000 e26b98d8 e12b3c64
e12b3c68 00000000 00000000 e12b3c74 000e000c
e12b3c78 e12b3c7c 0077005c 006e0069 0074006e
e12b3c88 00720000 006c006f 00650053 00300074
e12b3c98 00310030 00000201 05028203 67727453
e12b3ca8 575c3a43 544e4e49 00000000 00000220
e12b3cb8 00000101 05000000 00000012 00000201
e12b3cc8 05000000 00000020 00000220 00000101
Thanks,
Joel
You are currently subscribed to ntfsd as: $subst(‘Recip.EmailAddr’)
To unsubscribe send a blank email to leave-ntfsd-$subst(‘Recip.MemberIDChar’)@lists.osr.com