Freigeben über


Debuggen von Speicherlecks – DRIVER_VERIFIER_DETECTED_VIOLATION (C4): 0x62

Driver Verifier generiert Fehlerüberprüfungs-0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION mit einem Parameter 1-Wert von 0x62, wenn ein Treiber entladen wird, ohne zuerst alle poolzuordnungen freizuweisen. Nicht synchronisierte Speicherzuweisungen (auch als Speicherlecks bezeichnet) sind eine häufige Ursache für eine verringerte Leistung des Betriebssystems. Diese können die Systempools fragmentieren und schließlich zu Systemabstürzen führen.

Wenn sie einen Kerneldebugger mit einem Testcomputer verbunden haben, auf dem Driver Verifier ausgeführt wird, bricht Windows in den Debugger auf und zeigt eine kurze Beschreibung des Fehlers an.

>Debuggen von Speicherlecks beim Entladen des Treibers

Verwenden von !analyze zum Anzeigen von Informationen zur Fehlerüberprüfung

Wie bei jeder Fehlerüberprüfung, die auftritt, besteht der beste erste Schritt darin, den Befehl "!analyze -v " auszuführen, sobald Sie die Kontrolle über den Debugger haben.

kd> !analyze -v
Connected to Windows 8 9600 x86 compatible target
Loading Kernel Symbols
.................................................................................
Loading User Symbols
.......................
Loading unloaded module list
........
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

DRIVER_VERIFIER_DETECTED_VIOLATION (c4)
A device driver attempting to corrupt the system has been caught.  This is
because the driver was specified in the registry as being suspect (by the
administrator) and the kernel has enabled substantial checking of this driver.
If the driver attempts to corrupt the system, bugchecks 0xC4, 0xC1 and 0xA will
be among the most commonly seen crashes.
Arguments:
Arg1: 00000062, A driver has forgotten to free its pool allocations prior to unloading.
Arg2: 9707712c, name of the driver having the issue.
Arg3: 9c1faf70, verifier internal structure with driver information.
Arg4: 00000003, total # of (paged+nonpaged) allocations that weren't freed.
    Type !verifier 3 drivername.sys for info on the allocations
    that were leaked that caused the bugcheck.

Eine Fehlerüberprüfung 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION mit einem Parameter 1 (Arg1)-Wert von 0x62 wird wie folgt beschrieben:

DRIVER_VERIFIER_DETECTED_VIOLATION (C4) Arg1 Arg2 Arg3 Arg3 Arg4 Cause Driver Verifier flags 0x62 Name des Treibers. Reservierte Gesamtanzahl von Zuordnungen, die nicht freigegeben wurden, einschließlich seitenseitiger und nicht seitenseitiger Pool. Der Fahrer wird entladen, ohne zuerst seine Poolzuweisungen frei zu geben. In Windows 8.1 tritt diese Fehlerüberprüfung auch auf, wenn der Treiber entladen wurde, ohne zuerst Arbeitsaufgaben (IO_WORKITEM) freizuweisen, die ihm IoAllocateWorkItem zugewiesen wurden. Eine Fehlerüberprüfung mit diesem Parameter tritt nur auf, wenn die Option "Poolnachverfolgung " aktiv ist. Geben Sie die Poolnachverfolgung an (Verifier /flags 0x8). Die Option "Poolnachverfolgung" ist mit Standardkennzeichnungen (Verifier /standard ) aktiviert.

Verwenden Sie den Erweiterungsbefehl "!verifier 3", um informationen zu den Poolzuweisungen zu erhalten.

Bei dieser speziellen Fehlerüberprüfung sind die informationen in Parameter 4 (Arg4) am wichtigsten. Arg4 zeigt die Anzahl der Zuordnungen an, die nicht freigegeben wurden. Die Ausgabe des Befehls "!analyse " zeigt auch den Erweiterungsbefehl "!verifier debugger" an, mit dem Sie anzeigen können, was diese Zuordnungen waren. Die vollständige Ausgabe von !verifier 3 MyDriver.sys Befehl wird im folgenden Beispiel gezeigt:

kd> !verifier 3 Mydriver.sys

Verify Flags Level 0x000209bb

  STANDARD FLAGS:
    [X] (0x00000000) Automatic Checks
    [X] (0x00000001) Special pool
    [X] (0x00000002) Force IRQL checking
    [X] (0x00000008) Pool tracking
    [X] (0x00000010) I/O verification
    [X] (0x00000020) Deadlock detection
    [X] (0x00000080) DMA checking
    [X] (0x00000100) Security checks
    [X] (0x00000800) Miscellaneous checks
    [X] (0x00020000) DDI compliance checking

  ADDITIONAL FLAGS:
    [ ] (0x00000004) Randomized low resources simulation
    [ ] (0x00000200) Force pending I/O requests
    [ ] (0x00000400) IRP logging
    [ ] (0x00002000) Invariant MDL checking for stack
    [ ] (0x00004000) Invariant MDL checking for driver
    [ ] (0x00008000) Power framework delay fuzzing
    [ ] (0x00040000) Systematic low resources simulation
    [ ] (0x00080000) DDI compliance checking (additional)
    [ ] (0x00200000) NDIS/WIFI verification
    [ ] (0x00800000) Kernel synchronization delay fuzzing
    [ ] (0x01000000) VM switch verification

    [X] Indicates flag is enabled


Summary of All Verifier Statistics

  RaiseIrqls           0x0
  AcquireSpinLocks     0x0
  Synch Executions     0x0
  Trims                0x0

  Pool Allocations Attempted             0x2db1a
  Pool Allocations Succeeded             0x2db1a
  Pool Allocations Succeeded SpecialPool 0x2db1a
  Pool Allocations With NO TAG           0x0
  Pool Allocations Failed                0x0

  Current paged pool allocations         0x0 for 00000000 bytes
  Peak paged pool allocations            0x0 for 00000000 bytes
  Current nonpaged pool allocations      0x3 for 00001058 bytes
  Peak nonpaged pool allocations         0x13 for 0004A4A0 bytes

## Driver Verification List


  MODULE: 0x84226b28 MyDriver.sys (Loaded)

    Pool Allocation Statistics: ( NonPagedPool / PagedPool )

      Current Pool Allocations: ( 0x00000003 / 0x00000000 )
      Current Pool Bytes:       ( 0x00001058 / 0x00000000 )
      Peak Pool Allocations:    ( 0x00000013 / 0x00000000 )
      Peak Pool Bytes:          ( 0x0004A4A0 / 0x00000000 )
      Contiguous Memory Bytes:       0x00000000
      Peak Contiguous Memory Bytes:  0x00000000

    Pool Allocations:

      Address     Length      Tag   Caller    
      ----------  ----------  ----  ----------
      0x982a8fe0  0x00000020  VMdl  0x9a3bf6ac  MyDriver!DeviceControlDispatch
      0x8645a000  0x00001008  mdrv  0x9a3bf687  MyDriver!DeviceControlDispatch
      0x9a836fd0  0x00000030  Vfwi  0x9a3bf6ed  MyDriver!GetNecessaryObjects

Beispielsweise verfügt der Treiber, MyDriver.sys, über zwei Speicherzuweisungen und eine E/A-Arbeitsaufgabe, die nicht ordnungsgemäß freigegeben wurde. Jede Auflistung zeigt die Adresse der aktuellen Zuordnung, die Größe, das verwendete Pooltag und die Adresse im Treibercode an, in dem die Anforderung für eine Zuordnung vorgenommen wurde. Wenn Symbole für den betreffenden Treiber geladen werden, wird auch der Name der Funktion neben der Anruferadresse angezeigt.

Von den angezeigten Tags wurde nur eine (für die Zuordnung an Adresse 0x8645a000) vom Treiber selbst (mdrv) bereitgestellt. Das Tag VMdl wird immer verwendet, wenn ein Treiber, der von Driver Verifier überprüft wird, IoAllocateMdl aufruft. Ebenso wird das Tag Vfwi verwendet, wenn ein treiber, der von Driver Verifier überprüft wird, eine Anforderung zum Zuweisen einer Arbeitsaufgabe mithilfe von IoAllocateWorkItem.

Wenn Sie über Symbole verfügen, können Sie in den Quelldateien die Speicherzuweisungen finden.

Wenn Symbole für den Treiber geladen werden, wenn diese Symbole die Zeilennummerninformationen enthalten, können Sie den Befehl "ln CallerAddress " verwenden, um die Zeile anzuzeigen, an der der Anruf getätigt wurde. Diese Ausgabe zeigt auch den Offset in der Funktion an, die die Zuordnung vorgenommen hat.

kd> ln 0x9a3bf6ac  
d:\coding\wdmdrivers\mydriver\handleioctl.c(50)+0x15
(9a3bf660)   MyDriver!DeviceControlDispatch+0x4c   |  (9a3bf6d0)   MyDriver!DeviceControlDispatch

kd> ln 0x9a3bf687  
d:\coding\wdmdrivers\mydriver\handleioctl.c(38)+0x12
(9a3bf660)   MyDriver!DeviceControlDispatch+0x27   |  (9a3bf6d0)   MyDriver!DeviceControlDispatch

kd> ln 0x9a3bf6ed  
d:\coding\wdmdrivers\mydriver\handleioctl.c(72)+0xa
(9a3bf6d0)   MyDriver!GetNecessaryObjects+0x1d   |  (9a3bf71c)   MyDriver!GetNecessaryObjects

Überprüfen des Protokolls auf Speicherzuweisungen

Die Treiberüberprüfung behält auch ein Zirkelprotokoll aller Speicherzuweisungen im Kernelbereich bei, wenn die Poolnachverfolgung aktiviert ist. Standardmäßig werden die letzten 65.536 (0x10000) Zuordnungen beibehalten. Da eine neue Zuordnung vorgenommen wird, wird die älteste Zuordnung im Protokoll überschrieben. Wenn die Zuordnungen vor kurzem vor dem Absturz vorgenommen wurden, kann es möglich sein, zusätzliche Informationen über die Zuordnung zu erhalten, als oben gezeigt, insbesondere die Threadadresse und die Frames des Kernelstapels zum Zeitpunkt der Zuordnung.

Auf dieses Protokoll kann über den Befehl "!verifier" 0x80 AddressOfPoolAllocation zugegriffen werden. Beachten Sie, dass dadurch alle Zuordnungen und Freigänge im Protokoll für diese bestimmte Adresse aufgeführt werden. Um die Anzeige des Protokollverlaufs abzubrechen oder zu beenden, verwenden Sie die Tastenkombinationen: STRG+UMBRUCH mit WinDbg und STRG+C mit KD.

kd> !verifier 0x80 0x982a8fe0

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x00010000 log entries, searching for address 0x982a8fe0.

# 

Pool block 982a8fe0, Size 00000020, Thread 9c158bc0
81b250cd nt!IovAllocateMdl+0x3d
8060e41d VerifierExt!IoAllocateMdl_internal_wrapper+0x35
81b29388 nt!VerifierIoAllocateMdl+0x22
9a3bf6ac MyDriver!DeviceControlDispatch+0x4c
9a3bf611 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
80611710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
81b3b635 nt!ViGenericDispatchHandler+0x2d
81b3b784 nt!ViGenericDeviceControl+0x18
81b24b4d nt!IovCallDriver+0x2cc
81703772 nt!IofCallDriver+0x62
8191165e nt!IopSynchronousServiceTail+0x16e
81915518 nt!IopXxxControlFile+0x3e8

kd> !verifier 0x80 0x8645a000

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x00010000 log entries, searching for address 0x8645a000.

# 

Pool block 8645a000, Size 00001000, Thread 9c158bc0
8060ee4f VerifierExt!ExAllocatePoolWithTagPriority_internal_wrapper+0x5b
81b2619e nt!VerifierExAllocatePoolWithTag+0x24
9a3bf687 MyDriver!DeviceControlDispatch+0x27
9a3bf611 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
80611710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
81b3b635 nt!ViGenericDispatchHandler+0x2d
81b3b784 nt!ViGenericDeviceControl+0x18
81b24b4d nt!IovCallDriver+0x2cc
81703772 nt!IofCallDriver+0x62
8191165e nt!IopSynchronousServiceTail+0x16e
81915518 nt!IopXxxControlFile+0x3e8
81914516 nt!NtDeviceIoControlFile+0x2a

kd> !verifier 0x80 0x9a836fd0  

Log of recent kernel pool Allocate and Free operations:

There are up to 0x10000 entries in the log.

Parsing 0x00010000 log entries, searching for address 0x9a836fd0.

# 

Pool block 9a836fd0, Size 00000030, Thread 88758740
8151713d nt!IovAllocateWorkItem+0x1b
84a133d9 VerifierExt!IoAllocateWorkItem_internal_wrapper+0x29
8151b3a7 nt!VerifierIoAllocateWorkItem+0x16
9a3bf6ed MyDriver!GetNecessaryObjects+0x1d
9a3bf620 MyDriver!NonPNPIRPDispatch0x51
9a3bf05a MyDriver!AllIRPDispatch+0x1a
84a16710 VerifierExt!xdv_IRP_MJ_DEVICE_CONTROL_wrapper+0xd0
8152d635 nt!ViGenericDispatchHandler+0x2d
8152d784 nt!ViGenericDeviceControl+0x18
81516b4d nt!IovCallDriver+0x2cc
810f5772 nt!IofCallDriver+0x62
8130365e nt!IopSynchronousServiceTail+0x16e
81307518 nt!IopXxxControlFile+0x3e8

Beheben von Speicherlecks

Diese Fehlerüberprüfung der Treiberüberprüfung wurde entwickelt, um zu verhindern, dass der Treiber den Kernelspeicher verleckt. In jedem Fall besteht die richtige Lösung darin, vorhandene Codepfade zu identifizieren, in denen die zugeordneten Objekte nicht freigegeben werden und sicherstellen, dass sie ordnungsgemäß freigegeben werden.

Static Driver Verifier ist ein Tool, mit dem Windows-Treiberquellcode überprüft und mögliche Probleme gemeldet wird, indem die Übung verschiedener Codepfade simuliert wird. Static Driver Verifier ist ein hervorragendes Entwicklungszeitprogramm, mit dem diese Arten von Problemen identifiziert werden können.

Weitere Techniken, die Sie verwenden können, einschließlich Szenarien, in denen die Treiberüberprüfung nicht beteiligt ist, finden Sie unter Suchen eines Kernelmodusspeicherlecks.

Suchen eines Kernelmodus-Speicherverlusts

Statische Treiberüberprüfung

Windows-Debuggen

Behandeln einer Fehlerüberprüfung, wenn die Treiberüberprüfung aktiviert ist