[NTOSKRNL] Reimplement !irpfind using !poolfind helpers
authorPierre Schweitzer <pierre@reactos.org>
Sun, 6 Jan 2019 11:49:57 +0000 (12:49 +0100)
committerPierre Schweitzer <pierre@reactos.org>
Sun, 6 Jan 2019 11:49:57 +0000 (12:49 +0100)
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
ntoskrnl/mm/ARM3/expool.c
ntoskrnl/ps/process.c

index ef97693..6b7ee27 100644 (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 *****************************************************************/
index b321b52..e036453 100644 (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, 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;
index 3554d60..179fd1d 100644 (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 */