https://git.reactos.org/?p=reactos.git;a=commitdiff;h=47b48520b511842e9e9b74f9e59277ae4710c92f
commit 47b48520b511842e9e9b74f9e59277ae4710c92f Author: Pierre Schweitzer <pie...@reactos.org> AuthorDate: Sun Jan 6 12:49:57 2019 +0100 Commit: Pierre Schweitzer <pie...@reactos.org> CommitDate: Sun Jan 6 12:49:57 2019 +0100 [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. --- ntoskrnl/kdbg/kdb_cli.c | 5 +- ntoskrnl/mm/ARM3/expool.c | 184 ++++++++++++++++++++++++++++++++++++++++++---- ntoskrnl/ps/process.c | 114 ---------------------------- 3 files changed, 172 insertions(+), 131 deletions(-) diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index ef97693414..6b7ee2752b 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -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 *****************************************************************/ diff --git a/ntoskrnl/mm/ARM3/expool.c b/ntoskrnl/mm/ARM3/expool.c index b321b52044..e03645387a 100644 --- a/ntoskrnl/mm/ARM3/expool.c +++ b/ntoskrnl/mm/ARM3/expool.c @@ -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, 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, Mask); + ExpKdbgExtPoolFindPagedPool(TAG_IRP, 0xFFFFFFFF, ExpKdbgExtIrpFindPrint, &FindCtxt); } return TRUE; diff --git a/ntoskrnl/ps/process.c b/ntoskrnl/ps/process.c index 3554d601c1..179fd1d8fa 100644 --- a/ntoskrnl/ps/process.c +++ b/ntoskrnl/ps/process.c @@ -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 */