From d6dc1fd2310ed67891edc27a49aacc2eb11220f3 Mon Sep 17 00:00:00 2001 From: Pierre Schweitzer Date: Tue, 1 Jan 2019 21:58:18 +0100 Subject: [PATCH] [NTOSKRNL] Add a raw implementation of !irpfind in kdbg This is far from perfect, and totally doesn't match the WinDBG way of doing it. Instead of browsing pool to find matching 'IRP' tags, we just browse all the processes to find the queued IRP. This requires the IRPs to be queued, obviously, and will make us miss the leaked IRPs, for instance. Proper way to do it would be to implement !poolfind and then rely on its implementation to find our IRPs. Perhaps later ;-) --- ntoskrnl/kdbg/kdb_cli.c | 3 ++ ntoskrnl/ps/process.c | 115 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 118 insertions(+) diff --git a/ntoskrnl/kdbg/kdb_cli.c b/ntoskrnl/kdbg/kdb_cli.c index 3fce1977d96..37ad987b799 100644 --- a/ntoskrnl/kdbg/kdb_cli.c +++ b/ntoskrnl/kdbg/kdb_cli.c @@ -96,6 +96,8 @@ BOOLEAN ExpKdbgExtPoolUsed(ULONG Argc, PCHAR Argv[]); BOOLEAN ExpKdbgExtFileCache(ULONG Argc, PCHAR Argv[]); BOOLEAN ExpKdbgExtDefWrites(ULONG Argc, PCHAR Argv[]); +BOOLEAN PspKdbgIrpFind(ULONG Argc, PCHAR Argv[]); + #ifdef __ROS_DWARF__ static BOOLEAN KdbpCmdPrintStruct(ULONG Argc, PCHAR Argv[]); #endif @@ -190,6 +192,7 @@ static const struct { "!poolused", "!poolused [Flags [Tag]]", "Display pool usage.", ExpKdbgExtPoolUsed }, { "!filecache", "!filecache", "Display cache usage.", ExpKdbgExtFileCache }, { "!defwrites", "!defwrites", "Display cache write values.", ExpKdbgExtDefWrites }, + { "!irpfind", "!irpfind [criteria data]", "Lists IRPs potentially matching criteria", PspKdbgIrpFind }, }; /* FUNCTIONS *****************************************************************/ diff --git a/ntoskrnl/ps/process.c b/ntoskrnl/ps/process.c index c6962762e3c..3554d601c19 100644 --- a/ntoskrnl/ps/process.c +++ b/ntoskrnl/ps/process.c @@ -1614,4 +1614,119 @@ NtOpenProcess(OUT PHANDLE ProcessHandle, /* Return status */ 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 */