Comprobaciones varias

La opción Comprobaciones varias del comprobador de controladores supervisa el controlador para detectar errores comunes que hacen que el controlador o el sistema se bloqueen, como liberar memoria que todavía contiene objetos kernel activos.

En concreto, la opción Comprobaciones varias busca el siguiente comportamiento de controlador incorrecto:

  • Elementos de trabajo activos en memoria libre. El controlador llama a ExFreePool para liberar un bloque de grupo que contiene elementos de trabajo que se ponen en cola mediante IoQueueWorkItem.

  • Recursos activos en memoria libre. El controlador llama a ExFreePool para liberar un bloque de grupo que contiene estructuras ERESOURCE activas. El controlador debe llamar a ExDeleteResource para eliminar objetos ERESOURCE antes de llamar a ExFreePool.

  • Listas de lookaside activas en memoria libre. El controlador llama a ExFreePool para liberar un bloque de grupo que todavía contiene listas activas de apariencia (NPAGED_LOOKASIDE_LIST o estructuras PAGED_LOOKASIDE_LIST . El controlador debe llamar a ExDeleteNPagedLookasideList o ExDeletePagedLookasideList para eliminar las listas de lookaside antes de llamar a ExFreePool.

  • Problemas de registro de Instrumental de administración de Windows (WMI) y seguimiento de eventos para Windows (ETW). Estos problemas detectados por el Comprobador de controladores incluyen:

    • Controlador que intenta descargar sin anular el registro de su devolución de llamada WMI.

    • Controlador que intenta eliminar un objeto de dispositivo que no se ha anulado el registro de WMI.

    • Controlador que intenta descargar sin anular el registro de sus proveedores de modo kernel de ETW.

    • Controlador que intenta anular el registro de un proveedor que ya no está registrado.

  • El kernel controla los errores. (Windows Vista y versiones posteriores) Al habilitar la opción Comprobaciones varias, también se habilitará el seguimiento del seguimiento del proceso del sistema para ayudar a investigar fugas de identificadores de kernel y comprobación de errores 0x93: INVALID_KERNEL_HANDLE. Con el seguimiento de identificador habilitado, el kernel recopilará seguimientos de pila para las operaciones recientes de apertura y cierre de identificadores. Los seguimientos de pila se pueden mostrar en el depurador de kernel mediante la extensión !htrace debugger. Para obtener más información sobre !htrace, vea la documentación herramientas de depuración para Windows.

  • Identificador del modo de usuario con acceso al modo kernel A partir de Windows 7, al seleccionar la opción Comprobaciones varias, el Comprobador de controladores también comprueba las llamadas a ObReferenceObjectByHandle. No se puede pasar un identificador en modo de usuario con acceso al modo kernel. Si se produce esta operación, el Comprobador de controladores emite la comprobación de errores 0xC4, con un valor de parámetro 1 de 0xF6.

  • UserMode espera a los objetos de sincronización asignados en la pila del kernel

    A partir de Windows 7, el Comprobador de controladores puede detectar formas adicionales de que los controladores pueden usar incorrectamente los mecanismos de sincronización multithreading que proporciona el sistema operativo.

    La asignación de objetos de sincronización, como estructuras KEVENT, como variables locales en la pila del kernel es una práctica común. Mientras se carga un proceso en memoria, las pilas de kernel de sus subprocesos nunca se recortan del espacio de trabajo o se paginan en el disco. Asignar objetos de sincronización en dicha memoria no paginable es correcto.

    Sin embargo, cuando los controladores llaman a las API, como KeWaitForSingleObject o KeWaitForMultipleObjects , deben especificar el valor KernelMode para el parámetro WaitMode de la API. Cuando todos los subprocesos de un proceso están esperando en modo UserMode , ese proceso se puede intercambiar al disco. Por lo tanto, si un controlador especificó UserMode como parámetro WaitMode , el sistema operativo puede intercambiar el proceso actual siempre y cuando todos los demás subprocesos del mismo proceso también esperen como UserMode. El intercambio de un proceso completo al disco incluye la paginación de sus pilas de kernel. Esperar un objeto de sincronización que el sistema operativo ha intercambiado es incorrecto. En algún momento, un subproceso debe aparecer y indicar el objeto de sincronización. La señalización de un objeto de sincronización implica que el kernel de Windows manipule el objeto en IRQL = DISPATCH_LEVEL o superior. Al tocar la memoria paginada o intercambiada en DISPATCH_LEVEL o superior, se produce un bloqueo del sistema.

    A partir de Windows 7, al seleccionar la opción Comprobaciones varias, el Comprobador de controladores comprueba que los objetos de sincronización que usa el controlador comprobado para esperar en UserMode no se asignan en la pila de kernels del subproceso actual. Cuando el Comprobador de controladores detecta una espera incorrecta, emite un 0xC4 de comprobación de errores: DRIVER_VERIFIER_DETECTED_VIOLATION, con un valor de parámetro 1 de 0x123.

  • Referencias de identificador de kernel incorrectas

    Cada proceso de Windows tiene una tabla de identificadores. Puede ver la tabla de identificadores como una matriz de entradas de identificador. Cada valor de identificador válido hace referencia a una entrada válida en esta matriz.

    Un identificador de kernel como identificador válido para la tabla de identificadores del proceso del sistema. Un identificador de usuario como identificador válido para cualquier proceso, excepto el proceso del sistema.

    En Windows 7, el comprobador de controladores detecta intentos de hacer referencia a los valores de identificador del kernel que son incorrectos. Estos defectos del controlador se notifican como una comprobación de errores 0x93: INVALID_KERNEL_HANDLE si la opción Comprobaciones varias del comprobador del controlador está habilitada. Normalmente, este tipo de referencia de identificador incorrecto significa que el controlador ya ha cerrado ese identificador, pero está intentando seguir usándolo. Este tipo de defecto puede dar lugar a problemas imprevisibles para el sistema, ya que otro controlador no relacionado podría haber reutilizado el valor de identificador al que se hace referencia.

    Si un controlador de kernel ha cerrado recientemente un identificador de kernel y, posteriormente, hace referencia al identificador cerrado, driver Verifier fuerza la comprobación de errores como se ha descrito anteriormente. En este caso, la salida de la extensión del depurador !htrace proporciona el seguimiento de la pila para la ruta de acceso del código que cerró este identificador. Use la dirección del proceso del sistema como parámetro para !htrace. Para buscar la dirección del proceso del sistema, use el comando !process 4 0 .

    A partir de Windows 7, el Comprobador de controladores agrega una comprobación a ObReferenceObjectByHandle. Ahora está prohibido pasar un identificador de espacio de usuario con acceso KernelMode. Si se detecta esta combinación, el comprobador del controlador emite la comprobación de errores 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION, con un valor de parámetro 1 de 0xF6.

Activación de esta opción

Puede activar la opción Comprobaciones varias para uno o varios controladores mediante el Administrador de comprobadores de controladores o la línea de comandos Verifier.exe. Para obtener más información, vea Seleccionar opciones del comprobador de controladores.

  • En la línea de comandos

    En la línea de comandos, la opción Comprobaciones varias se representa mediante bit 11 (0x800). Para activar comprobaciones varias, use un valor de marca de 0x800 o agregue 0x800 al valor de marca. Por ejemplo:

    verifier /flags 0x800 /driver MyDriver.sys
    

    La opción estará activa después del siguiente arranque.

    En Windows Vista y versiones posteriores de Windows, también puedes activar y desactivar comprobaciones varias sin reiniciar el equipo agregando el parámetro /volatile al comando. Por ejemplo:

    verifier /volatile /flags 0x800 /adddriver MyDriver.sys
    

    Esta configuración es efectiva inmediatamente, pero se pierde al apagar o reiniciar el equipo. Para obtener más información, consulte Uso de la configuración volátil.

    La opción Comprobaciones varias también se incluye en la configuración estándar. Por ejemplo:

    verifier  /standard /driver MyDriver.sys
    
  • Uso del Administrador de comprobadores de controladores

    1. Inicie el Administrador de comprobadores de controladores. Escriba Comprobador en una ventana del símbolo del sistema.

    2. Seleccione Crear configuración personalizada (para desarrolladores de código) y, a continuación, haga clic en Siguiente.

    3. Seleccione Seleccionar configuración individual en una lista completa.

    4. Seleccione Comprobaciones varias.

    La característica Comprobaciones varias también se incluye en la configuración estándar. Para usar esta característica, en el Administrador de comprobadores de controladores, haga clic en Crear configuración estándar.

Ver los resultados

Para ver los resultados de la opción Comprobaciones varias, use la extensión !comprobador en el depurador de kernel. (Para obtener información sobre !comprobador, consulte la documentación herramientas de depuración para Windows ).

En el ejemplo siguiente, la opción Comprobaciones varias detectó una estructura ERESOURCE activa en la memoria que el controlador estaba intentando liberar, lo que da lugar a la comprobación de errores 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION. La pantalla comprobación de errores 0xC4 incluye la dirección del ERESOURCE y la memoria afectada.

1: kd> !verifier 1

Verify Level 800 ... enabled options are:
 Miscellaneous checks enabled

Summary of All Verifier Statistics

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

Pool Allocations Attempted             0x1
Pool Allocations Succeeded             0x1
Pool Allocations Succeeded SpecialPool 0x0
Pool Allocations With NO TAG           0x0
Pool Allocations Failed                0x0
Resource Allocations Failed Deliberately   0x0

Current paged pool allocations         0x0 for 00000000 bytes
Peak paged pool allocations            0x0 for 00000000 bytes
Current nonpaged pool allocations      0x0 for 00000000 bytes
Peak nonpaged pool allocations         0x0 for 00000000 bytes

Driver Verification List

Entry     State           NonPagedPool   PagedPool   Module

8459ca50 Loaded           00000000       00000000    buggy.sys



*** Fatal System Error: 0x000000c4
 (0x000000D2,0x9655D4A8,0x9655D468,0x000000B0)


        0xD2 : Freeing pool allocation that contains active ERESOURCE.
               2 -  ERESOURCE address.
               3 -  Pool allocation start address.
               4 -  Pool allocation size.

Para investigar la asignación del grupo, use la extensión del depurador !pool con la dirección inicial de la asignación del grupo, 9655D468. (La marca 2 muestra información de encabezado solo para el grupo que contiene la dirección especificada. Se suprime la información de encabezado de otros grupos).

1: kd> !pool 9655d468  2
Pool page 9655d468 region is Paged pool
*9655d468 size:   b0 previous size:    8  (Allocated) *Bug_

Para buscar información sobre ERESOURCE, use la extensión del depurador !locks (!kdext*.locks) con la dirección de la estructura.

1: kd> !locks 0x9655D4A8     <<<<<- ERESOURCE @0x9655D4A8 lives inside the pool block being freed

Resource @ 0x9655d4a8    Available
1 total locks

También puede usar el comando kb debugger para mostrar un seguimiento de pila de las llamadas que provocaron el error. En el ejemplo siguiente se muestra la pila, incluida la llamada a ExFreePoolWithTag que interceptó el comprobador del controlador.

1: kd> kb
ChildEBP RetAddr  Args to Child
92f6374c 82c2c95a 00000003 92f68cdc 00000000 nt!RtlpBreakWithStatusInstruction
92f6379c 82c2d345 00000003 9655d468 000000c4 nt!KiBugCheckDebugBreak+0x1c
92f63b48 82c2c804 000000c4 000000d2 9655d4a8 nt!KeBugCheck2+0x5a9
92f63b6c 82e73bae 000000c4 000000d2 9655d4a8 nt!KeBugCheckEx+0x1e
92f63b88 82e78c32 9655d4a8 9655d468 000000b0 nt!VerifierBugCheckIfAppropriate+0x3c
92f63ba4 82ca7dcb 9655d468 000000b0 00000000 nt!VfCheckForResource+0x52
92f63bc8 82e7fb2d 000000b0 00000190 9655d470 nt!ExpCheckForResource+0x21
92f63be4 82e6dc6c 9655d470 92f63c18 89b6c58c nt!ExFreePoolSanityChecks+0x1fb
92f63bf0 89b6c58c 9655d470 00000000 89b74194 nt!VerifierExFreePoolWithTag+0x28
92f63c00 89b6c0f6 846550c8 846550c8 846e2200 buggy!MmTestProbeLockForEverStress+0x2e
92f63c18 82e6c5f1 846e2200 846550c8 85362e30 buggy!TdDeviceControl+0xc4
92f63c38 82c1fd81 82d4d148 846550c8 846e2200 nt!IovCallDriver+0x251
92f63c4c 82d4d148 85362e30 846550c8 84655138 nt!IofCallDriver+0x1b
92f63c6c 82d4df9e 846e2200 85362e30 00000000 nt!IopSynchronousServiceTail+0x1e6
92f63d00 82d527be 00000001 846550c8 00000000 nt!IopXxxControlFile+0x684
92f63d34 82cb9efc 0000004c 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
92f63d34 6a22b204 0000004c 00000000 00000000 nt!KiFastCallEntry+0x12c