Compartilhar via


Verificações diversas

A opção Verificações Diversas do Verificador de Driver monitora o driver em busca de erros comuns que causam a falha do driver ou do sistema, como a liberação de memória que ainda contém objetos kernel ativos.

Especificamente, a opção Verificações Diversas procura o seguinte comportamento inadequado do driver:

  • Itens de trabalho ativos na memória liberada. O driver invoca ExFreePool para liberar um bloco de pool que contém itens de trabalho que foram enfileirados através do uso de IoQueueWorkItem.

  • Recursos ativos em memória liberada. O driver chama ExFreePool para liberar um bloco de pool que contém estruturas ERESOURCE ativas. O driver deve chamar ExDeleteResource para excluir objetos ERESOURCE antes de chamar ExFreePool.

  • Listas lookaside ativas na memória liberada. O driver chama ExFreePool para liberar um bloco de pool que ainda contém listas lookaside ativas (NPAGED_LOOKASIDE_LIST ou PAGED_LOOKASIDE_LIST). O driver deve chamar ExDeleteNPagedLookasideList ou ExDeletePagedLookasideList para excluir as listas lookaside antes de chamar ExFreePool.

  • Problemas de registro da WMI (Instrumentação de Gerenciamento do Windows) e do ETW (Rastreamento de Eventos para Windows). Esses problemas detectados pelo Verificador de Driver incluem:

    • Um driver que tenta descarregar sem cancelar o registro de seu callback WMI.

    • Um driver que tenta excluir um objeto de dispositivo que não foi desregistrado do WMI.

    • Um driver que tenta descarregar sem cancelar o registro de seus provedores de modo kernel ETW.

    • Um driver que tenta cancelar o registro de um provedor que já não foi registrado.

  • Tratamento de erros do kernel. (Windows Vista e versões posteriores) Habilitar a opção Verificações Diversas também habilitará o rastreamento de identificador para o processo do sistema, facilitando a investigação de vazamentos de identificadores de kernel e Verificação de Bug 0x93: INVALID_KERNEL_HANDLE. Com o rastreamento de identificador habilitado, o kernel coletará rastreamentos de pilha para operações de abertura e fechamento de identificador recentes. Os rastreamentos de pilha podem ser exibidos no depurador do kernel usando a extensão do depurador !htrace. Para obter mais informações sobre !htrace, consulte a documentação das Ferramentas de Depuração para Windows.

  • Identificador do modo de usuário com acesso ao modo kernel A partir do Windows 7, ao selecionar a opção Verificações Diversas, o Verificador de Driver também verifica as chamadas para ObReferenceObjectByHandle. Você não pode passar um identificador de modo de usuário com acesso ao modo kernel. Se tal operação ocorrer, o Verificador de Driver emitirá o Código de Erro 0xC4, com um valor do parâmetro 1 de 0xF6.

  • Modo Usuário Espera por Objetos de Sincronização Alocados na Pilha do Kernel

    A partir do Windows 7, o Verificador de Driver pode detectar maneiras adicionais de os drivers usarem incorretamente os mecanismos de sincronização multithreading que o sistema operacional fornece.

    Alocar objetos de sincronização, como as estruturas KEVENT, como variáveis locais na pilha do kernel é uma prática comum. Enquanto um processo é carregado na memória, as pilhas do kernel de seus threads nunca são cortadas do conjunto de trabalho ou paginadas para o disco. A alocação de objetos de sincronização em tal memória não pageável está correta.

    No entanto, quando os drivers chamam APIs como KeWaitForSingleObject ou KeWaitForMultipleObjects para aguardar um objeto alocado na pilha, eles devem especificar o valor KernelMode para o parâmetro WaitMode da API. Quando todos os threads de um processo estão aguardando no modo UserMode, esse processo se torna elegível para ser substituído para o disco. Portanto, se um driver especificou UserMode como o parâmetro WaitMode, o sistema operacional poderá substituir o processo atual, desde que todos os outros threads no mesmo processo também esperem como UserMode. A troca de todo um processo para o disco inclui paginar suas pilhas de kernel. Esperar por um objeto de sincronização que o sistema operacional tenha removido ou substituído está incorreto. Em algum momento, um thread deve aparecer e sinalizar o objeto de sincronização. Sinalizar um objeto de sincronização envolve o kernel do Windows manipulando o objeto em IRQL = DISPATCH_LEVEL ou superior. Tocar na memória paginada para fora ou acessar memória no nível de DISPATCH ou superior resulta em um travamento do sistema.

    A partir do Windows 7, quando você seleciona a opção Verificações Diversas, o Verificador de Driver verifica se os objetos de sincronização que o driver verificado usa para aguardar em UserMode não são alocados na pilha de kernel da thread atual. Quando o Verificador de Driver detecta uma espera incorreta no sistema, ele emite uma Verificação de Erro 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION, com um valor de parâmetro 1 de 0x123.

  • Referências incorretas do identificador de kernel

    Cada processo do Windows possui uma tabela de controle. Você pode exibir a tabela de identificadores como uma matriz de entradas de identificador. Cada valor de identificador válido refere-se a uma entrada válida nesta matriz.

    Um identificador de kernel é um identificador válido para a tabela de identificadores do processo do sistema. Um identificador de usuário como um identificador válido para qualquer processo, exceto o processo do Sistema.

    No Windows 7, o Verificador de Driver detecta tentativas de referenciar valores de identificador de kernel incorretos. Esses defeitos de driver são relatados como uma Verificação de Bug 0x93: INVALID_KERNEL_HANDLE se a opção Verificação de Diversidade do Verificador de Driver estiver habilitada. Normalmente, esse tipo de referência de identificador incorreta significa que o driver já fechou esse identificador, mas tenta usá-lo novamente. Esse tipo de defeito pode resultar em problemas imprevisíveis para o sistema, pois o valor do handle que está sendo referenciado pode já ter sido reutilizado por outro driver não relacionado.

    Se um driver de kernel fechou recentemente um identificador de kernel e, posteriormente, referencia o identificador fechado, o Verificador de Driver forçará a verificação de erros, como descrito anteriormente. Nesse caso, a saída da extensão de depuração !htrace fornece o rastreamento de stack para o caminho de código que fechou esse identificador. Use o endereço do processo do sistema como um parâmetro para !htrace. Para localizar o endereço do processo do sistema, use o comando !process 4 0 .

    A partir do Windows 7, o Verificador de Driver adiciona uma verificação a ObReferenceObjectByHandle. Agora é proibido passar uma alça de espaço do usuário com acesso modo Kernel. Se essa combinação for detectada, o Verificador de Driver emitirá Verificação de Bugs 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION, com um valor de parâmetro 1 de 0xF6.

Ativando essa opção

Você pode ativar a opção Verificações Diversas para um ou mais drivers usando o Gerenciador de Verificador de Driver ou a linha de comando Verifier.exe. Para obter detalhes, consulte Selecionar opções do Verificador de Driver.

  • Na linha de comando

    Na linha de comando, a opção Verificações Diversas é representada pelo Bit 11 (0x800). Para ativar Verificações Diversas, use um valor de sinalizador de 0x800 ou adicione 0x800 ao valor do sinalizador. Por exemplo:

    verifier /flags 0x800 /driver MyDriver.sys
    

    A opção estará ativa após a próxima inicialização.

    No Windows Vista e versões posteriores do Windows, você também pode ativar e desativar Verificações Diversas sem reinicializar o computador adicionando o parâmetro /volatile ao comando. Por exemplo:

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

    Essa configuração é efetivada imediatamente, mas é perdida quando você desliga ou reinicializa o computador. Para obter detalhes, consulte Como usar configurações voláteis.

    A opção Verificações Diversas também está incluída nas configurações padrão. Por exemplo:

    verifier  /standard /driver MyDriver.sys
    
  • Usando o Gerenciador de Verificador de Driver

    1. Iniciar o Gerenciador de Verificador de Driver. Digite Verificador em uma janela do Prompt de Comando.

    2. Selecione Criar configurações personalizadas (para desenvolvedores de código) e clique em Avançar.

    3. Selecione Selecionar configurações individuais em uma lista completa.

    4. Selecione Verificações Diversas.

    O recurso Verificações Diversas também está incluído nas configurações padrão. Para usar esse recurso, no Gerenciador do Verificador de Driver, clique em Criar Configurações Padrão.

Exibindo os resultados

Para exibir os resultados da opção Verificações Diversas, use a extensão !verifier no depurador de kernel. (Para obter informações sobre !verifier, consulte a documentação das Ferramentas de Depuração para Windows .)

No exemplo a seguir, a opção Miscellaneous Checks detectou uma estrutura ERESOURCE ativa na memória que o driver estava tentando liberar, resultando em Bug Check 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION. A Verificação de Erros com código 0xC4 exibe o endereço do ERESOURCE e a memória afetada.

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 a alocação do pool, use a extensão do depurador !pool com o endereço inicial da alocação do pool, 9655D468. (O sinalizador 2 exibe informações de cabeçalho somente para o pool que contém o endereço especificado. As informações de cabeçalho para outros pools são suprimidas.)

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

Para encontrar informações sobre o ERESOURCE, use a extensão do depurador !locks (!kdext*.locks) com o endereço da estrutura.

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

Resource @ 0x9655d4a8    Available
1 total locks

Você também pode usar o comando kb depurador para exibir um rastreamento de pilha das chamadas que levaram à falha. O exemplo a seguir mostra a pilha, incluindo a chamada para ExFreePoolWithTag interceptada pelo Verificador de Drivers.

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