[NTOSKRNL] Reimplement !irpfind using !poolfind helpers

This allows avoiding one of the previous implementation limits:
leaked IRP not queued to a thread are now totally visible since
we look directly in the memory pool.
This commit is contained in:
Pierre Schweitzer 2019-01-06 12:49:57 +01:00
parent 12e579567c
commit 47b48520b5
No known key found for this signature in database
GPG key ID: 7545556C3D585B0B
3 changed files with 172 additions and 131 deletions

View file

@ -96,8 +96,7 @@ BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtPoolFind(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]);
BOOLEAN PspKdbgIrpFind(ULONG Argc, PCHAR Argv[]);
BOOLEAN ExpKdbgExtIrpFind(ULONG Argc, PCHAR Argv[]);
#ifdef __ROS_DWARF__
static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]);
@ -194,7 +193,7 @@ static const struct
{ "!poolfind", "!poolfind Tag [Pool]", "Search for pool tag allocations.", ExpKdbgExtPoolFind },
{ "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache },
{ "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites },
{ "!irpfind", "!irpfind [criteria data]", "Lists IRPs potentially matching criteria", PspKdbgIrpFind },
{ "!irpfind", "!irpfind [Pool [Restart Address [criteria data]]]", "Lists IRPs potentially matching criteria", ExpKdbgExtIrpFind },
};
/* FUNCTIONS *****************************************************************/

View file

@ -3156,7 +3156,9 @@ static
VOID
ExpKdbgExtPoolFindPagedPool(
ULONG Tag,
ULONG Mask)
ULONG Mask,
VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
PVOID CallbackContext)
{
ULONG i = 0;
PPOOL_HEADER Entry;
@ -3210,11 +3212,18 @@ ExpKdbgExtPoolFindPagedPool(
if ((Entry->PoolTag & Mask) == (Tag & Mask))
{
/* Print the line */
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
Entry, Entry->BlockSize, Entry->PreviousSize,
Entry->PoolType ? "(Allocated)" : "(Free) ",
(PCHAR)&Entry->PoolTag);
if (FoundCallback != NULL)
{
FoundCallback(Entry, CallbackContext);
}
else
{
/* Print the line */
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
Entry, Entry->BlockSize, Entry->PreviousSize,
Entry->PoolType ? "(Allocated)" : "(Free) ",
(PCHAR)&Entry->PoolTag);
}
}
}
}
@ -3228,7 +3237,9 @@ static
VOID
ExpKdbgExtPoolFindNonPagedPool(
ULONG Tag,
ULONG Mask)
ULONG Mask,
VOID (NTAPI* FoundCallback)(PPOOL_HEADER, PVOID),
PVOID CallbackContext)
{
PPOOL_HEADER Entry;
PVOID BaseVa;
@ -3270,11 +3281,18 @@ ExpKdbgExtPoolFindNonPagedPool(
if ((Entry->PoolTag & Mask) == (Tag & Mask))
{
/* Print the line */
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
Entry, Entry->BlockSize, Entry->PreviousSize,
Entry->PoolType ? "(Allocated)" : "(Free) ",
(PCHAR)&Entry->PoolTag);
if (FoundCallback != NULL)
{
FoundCallback(Entry, CallbackContext);
}
else
{
/* Print the line */
KdbpPrint("%p size: %4d previous size: %4d %s %.4s\n",
Entry, Entry->BlockSize, Entry->PreviousSize,
Entry->PoolType ? "(Allocated)" : "(Free) ",
(PCHAR)&Entry->PoolTag);
}
}
}
}
@ -3318,11 +3336,149 @@ ExpKdbgExtPoolFind(
if (PoolType == NonPagedPool)
{
ExpKdbgExtPoolFindNonPagedPool(Tag, Mask);
ExpKdbgExtPoolFindNonPagedPool(Tag, Mask, NULL, NULL);
}
else if (PoolType == PagedPool)
{
ExpKdbgExtPoolFindPagedPool(Tag, Mask);
ExpKdbgExtPoolFindPagedPool(Tag, Mask, NULL, NULL);
}
return TRUE;
}
typedef struct _IRP_FIND_CTXT
{
ULONG_PTR RestartAddress;
ULONG_PTR SData;
ULONG Criteria;
} IRP_FIND_CTXT, *PIRP_FIND_CTXT;
VOID
NTAPI
ExpKdbgExtIrpFindPrint(
PPOOL_HEADER Entry,
PVOID Context)
{
PIRP Irp;
PIRP_FIND_CTXT FindCtxt = Context;
PIO_STACK_LOCATION IoStack = NULL;
PUNICODE_STRING DriverName;
ULONG_PTR SData = FindCtxt->SData;
ULONG Criteria = FindCtxt->Criteria;
/* Free entry, ignore */
if (Entry->PoolType == 0)
{
return;
}
/* Get the IRP */
Irp = (PIRP)POOL_FREE_BLOCK(Entry);
/* Bail out if not matching restart address */
if ((ULONG_PTR)Irp < FindCtxt->RestartAddress)
{
return;
}
/* Avoid bogus IRP stack locations */
if (Irp->CurrentLocation <= Irp->StackCount + 1)
{
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* Get associated driver */
if (IoStack->DeviceObject && IoStack->DeviceObject->DriverObject)
DriverName = &IoStack->DeviceObject->DriverObject->DriverName;
else
DriverName = NULL;
}
/* Display if: no data, no criteria or if criteria matches data */
if (SData == 0 || Criteria == 0 ||
(Criteria & 0x1 && IoStack && SData == (ULONG_PTR)IoStack->DeviceObject) ||
(Criteria & 0x2 && SData == (ULONG_PTR)Irp->Tail.Overlay.OriginalFileObject) ||
(Criteria & 0x4 && Irp->MdlAddress && SData == (ULONG_PTR)Irp->MdlAddress->Process) ||
(Criteria & 0x8 && SData == (ULONG_PTR)Irp->Tail.Overlay.Thread) ||
(Criteria & 0x10 && SData == (ULONG_PTR)Irp->UserEvent))
{
KdbpPrint("%p Thread %p current stack belongs to %wZ\n", Irp, Irp->Tail.Overlay.Thread, DriverName);
}
}
BOOLEAN
ExpKdbgExtIrpFind(
ULONG Argc,
PCHAR Argv[])
{
ULONG PoolType = NonPagedPool;
IRP_FIND_CTXT FindCtxt;
/* Pool type */
if (Argc > 1)
{
PoolType = strtoul(Argv[1], NULL, 0);
if (PoolType > 1)
{
KdbpPrint("Only (non) paged pool are supported\n");
return TRUE;
}
}
RtlZeroMemory(&FindCtxt, sizeof(IRP_FIND_CTXT));
/* Restart address */
if (Argc > 2)
{
if (!KdbpGetHexNumber(Argv[2], &FindCtxt.RestartAddress))
{
KdbpPrint("Invalid parameter: %s\n", Argv[0]);
FindCtxt.RestartAddress = 0;
}
}
if (Argc > 4)
{
if (!KdbpGetHexNumber(Argv[4], &FindCtxt.SData))
{
FindCtxt.SData = 0;
}
else
{
if (strcmp(Argv[3], "device") == 0)
{
FindCtxt.Criteria = 0x1;
}
else if (strcmp(Argv[3], "fileobject") == 0)
{
FindCtxt.Criteria = 0x2;
}
else if (strcmp(Argv[3], "mdlprocess") == 0)
{
FindCtxt.Criteria = 0x4;
}
else if (strcmp(Argv[3], "thread") == 0)
{
FindCtxt.Criteria = 0x8;
}
else if (strcmp(Argv[3], "userevent") == 0)
{
FindCtxt.Criteria = 0x10;
}
else if (strcmp(Argv[3], "arg") == 0)
{
FindCtxt.Criteria = 0x1f;
}
}
}
if (PoolType == NonPagedPool)
{
ExpKdbgExtPoolFindNonPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt);
}
else if (PoolType == PagedPool)
{
ExpKdbgExtPoolFindPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt);
}
return TRUE;

View file

@ -1615,118 +1615,4 @@ NtOpenProcess(OUT PHANDLE ProcessHandle,
return Status;
}
#if DBG && defined(KDBG)
BOOLEAN
PspKdbgIrpFind(
ULONG Argc,
PCHAR Argv[])
{
PLIST_ENTRY PsEntry, TdEntry, IrpEntry;
PEPROCESS Process = NULL;
PETHREAD Thread = NULL;
PIRP Irp = NULL;
PIO_STACK_LOCATION IoStack = NULL;
PUNICODE_STRING DriverName;
ULONG_PTR SData = 0;
ULONG Criteria = 0;
/*
* FIXME: To improve, badly
* This should just be a wrapper over !poolfind
* As a hack, here we just browse all the queued IRPs
* and return them
* If that's not *that* wrong, it makes sure that leaked
* IRPs are invisible!
* We also don't care about pool type, nor address start
*/
/* Gets the criteria and its data */
if (Argc > 2)
{
if (!KdbpGetHexNumber(Argv[2], &SData))
{
SData = 0;
}
else
{
if (strcmp(Argv[1], "device") == 0)
{
Criteria = 0x1;
}
else if (strcmp(Argv[1], "fileobject") == 0)
{
Criteria = 0x2;
}
else if (strcmp(Argv[1], "mdlprocess") == 0)
{
Criteria = 0x4;
}
else if (strcmp(Argv[1], "thread") == 0)
{
Criteria = 0x8;
}
else if (strcmp(Argv[1], "userevent") == 0)
{
Criteria = 0x10;
}
else if (strcmp(Argv[1], "arg") == 0)
{
Criteria = 0x1f;
}
}
}
PsEntry = PsActiveProcessHead.Flink;
/* Loop the process list */
while (PsEntry != &PsActiveProcessHead)
{
/* Get the process */
Process = CONTAINING_RECORD(PsEntry, EPROCESS, ActiveProcessLinks);
/* Loop the thread list */
TdEntry = Process->ThreadListHead.Flink;
while (TdEntry != &Process->ThreadListHead)
{
/* Get the thread */
Thread = CONTAINING_RECORD(TdEntry, ETHREAD, ThreadListEntry);
/* Loop the IRP list */
IrpEntry = Thread->IrpList.Flink;
while (IrpEntry != &Thread->IrpList)
{
/* Get the IRP and its current stack */
Irp = CONTAINING_RECORD(IrpEntry, IRP, ThreadListEntry);
IoStack = IoGetCurrentIrpStackLocation(Irp);
/* Get associated driver */
if (IoStack->DeviceObject && IoStack->DeviceObject->DriverObject)
DriverName = &IoStack->DeviceObject->DriverObject->DriverName;
else
DriverName = NULL;
/* Display if: no data, no criteria or if criteria matches data */
if (SData == 0 || Criteria == 0 ||
(Criteria & 0x1 && SData == (ULONG_PTR)IoStack->DeviceObject) ||
(Criteria & 0x2 && SData == (ULONG_PTR)Irp->Tail.Overlay.OriginalFileObject) ||
(Criteria & 0x4 && Irp->MdlAddress && SData == (ULONG_PTR)Irp->MdlAddress->Process) ||
(Criteria & 0x8 && SData == (ULONG_PTR)Irp->Tail.Overlay.Thread) ||
(Criteria & 0x10 && SData == (ULONG_PTR)Irp->UserEvent))
{
KdbpPrint("%p Thread %p current stack belongs to %wZ\n", Irp, Thread, DriverName);
}
IrpEntry = IrpEntry->Flink;
}
TdEntry = TdEntry->Flink;
}
PsEntry = PsEntry->Flink;
}
return TRUE;
}
#endif // DBG && KDBG
/* EOF */