Condividi tramite


Debug di perdite di memoria - DRIVER_VERIFIER_DETECTED_VIOLATION (C4): 0x62

Driver Verifier genera 0xC4 controllo bug: DRIVER_VERIFIER_DETECTED_VIOLATION con un valore di parametro 1 di 0x62 quando un driver scarica senza prima liberare tutte le allocazioni del pool. Le allocazioni di memoria non aggiornate (dette anche perdite di memoria) sono una causa comune delle prestazioni del sistema operativo ridotte. Questi possono frammentarsi i pool di sistema e alla fine causare arresti anomali del sistema.

Quando si dispone di un debugger del kernel connesso a un computer di test che esegue Driver Verifier, se Driver Verifier rileva una violazione, Windows si interrompe nel debugger e visualizza una breve descrizione dell'errore.

>Debug delle perdite di memoria durante lo scaricamento del driver

Usare !analyze per visualizzare informazioni sul controllo dei bug

Come per qualsiasi controllo di bug che si verifica, una volta ottenuto il controllo del debugger, il primo passaggio migliore consiste nell'eseguire il comando !analyze -v .

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.

Un controllo bug 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION con un valore di parametro 1 (Arg1) di 0x62 viene descritto come segue:

DRIVER_VERIFIER_DETECTED_VIOLATION (C4) Arg1 Arg2 Arg3 Arg4 Cause Driver Verifier flags 0x62 Nome del driver. Numero totale riservato di allocazioni non liberate, inclusi pool di paging e non di paging. Il driver viene scaricato senza prima liberare le allocazioni del pool. In Windows 8.1, questo controllo dei bug si verificherà anche se il driver viene scaricato senza prima liberare elementi di lavoro (IO_WORKITEM) allocati con IoAllocateWorkItem. Un controllo di bug con questo parametro si verifica solo quando l'opzione Monitoraggio pool è attiva. Specificare il rilevamento pool (verifica /flags 0x8). L'opzione Rilevamento pool è abilitata con flag standard (verifier /standard ).

Usare il comando di estensione !verifier 3 per scoprire le allocazioni del pool

Per questo particolare controllo dei bug, le informazioni fornite nel parametro 4 (Arg4) sono le più importanti. Arg4 mostra il numero di allocazioni che non sono state liberate. L'output del comando !analyze mostra anche il comando di estensione del debugger !verifier che è possibile usare per visualizzare le allocazioni. L'output completo del comando !verifier 3 MyDriver.sys è illustrato nell'esempio seguente:

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

Ad esempio, il driver, MyDriver.sys, ha due allocazioni di memoria e un elemento di lavoro di I/O che non sono stati liberati correttamente. Ogni elenco mostra l'indirizzo dell'allocazione corrente, le dimensioni, il tag del pool usato e l'indirizzo nel codice del driver in cui è stata effettuata la richiesta di allocazione. Se i simboli vengono caricati per il driver in questione, mostrerà anche il nome della funzione accanto all'indirizzo del chiamante.

Dei tag visualizzati, solo uno (per l'allocazione all'indirizzo 0x8645a000) è stato fornito dal driver stesso (mdrv). Il tag VMdl viene usato ogni volta che un driver verificato da Driver Verifier effettua chiamate IoAllocateMdl. Analogamente, il tag Vfwi viene usato ogni volta che un driver verificato da Driver Verifier effettua una richiesta per allocare un elemento di lavoro usando IoAllocateWorkItem.

Se sono presenti simboli, è possibile individuare la posizione in cui si sono verificate le allocazioni di memoria nei file di origine

Quando i simboli vengono caricati per il driver, se questi simboli contengono le informazioni sul numero di riga, è possibile usare il comando ln CallerAddress per visualizzare la riga in cui è stata effettuata la chiamata. Questo output mostrerà anche l'offset nella funzione che ha effettuato l'allocazione.

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

Esaminare il log per individuare le allocazioni di memoria

Driver Verifier mantiene anche un log circolare di tutte le allocazioni di memoria eseguite nello spazio kernel quando è abilitato il rilevamento del pool. Per impostazione predefinita, vengono mantenute le allocazioni più recenti di 65.536 (0x10000). Quando viene eseguita una nuova allocazione, l'allocazione meno recente nel log viene sovrascritta. Se le allocazioni sono state effettuate di recente prima dell'arresto anomalo, potrebbe essere possibile ottenere informazioni aggiuntive sull'allocazione rispetto a quanto illustrato in precedenza, in particolare l'indirizzo del thread e i frame dello stack del kernel al momento dell'allocazione.

È possibile accedere a questo log usando il comando !verifier 0x80 AddressOfPoolAllocation. Si noti che verranno elencate tutte le allocazioni e le liberazioni nel log per questo indirizzo specifico. Per annullare o arrestare la visualizzazione della cronologia dei log, usare i tasti di scelta rapida: CTRL+INTERR con WinDbg e CTRL+C con 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

Correzione delle perdite di memoria

Questo controllo dei bug del driver Verifier è progettato per impedire al driver di perdere memoria kernel. In ogni caso, la correzione corretta consiste nell'identificare eventuali percorsi di codice esistenti in cui gli oggetti allocati non vengono liberati e assicurarsi che vengano liberati correttamente.

Static Driver Verifier è uno strumento che analizza il codice sorgente del driver Windows e segnala i possibili problemi simulando l'esercizio di vari percorsi di codice. Static Driver Verifier è un'eccellente utilità in fase di sviluppo per identificare questi tipi di problemi.

Per altre tecniche che è possibile usare, inclusi gli scenari in cui Il driver Verifier non è coinvolto, vedere Ricerca di una perdita di memoria in modalità kernel.

Ricerca di una perdita di memoria in modalità kernel

Verifica driver statico

Debug di Windows

Gestione di un controllo dei bug quando è abilitata la verifica del driver