Compartilhar via


Verificações diversas

A opção Verificações Diversas do Verificador de Driver monitora o driver em busca de erros comuns que fazem com que o driver ou o sistema falhe, como liberar 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 chama ExFreePool para liberar um bloco de pool que contém itens de trabalho que foram enfileirados usando IoQueueWorkItem.

  • Recursos ativos na 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 (estruturas 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 retorno de chamada WMI.

    • Um driver que tenta excluir um objeto de dispositivo que não foi cancelado 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.

  • Erros de identificador de 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 para ajudar na investigação de vazamentos de identificador de kernel e 0x93 de Verificação de Bugs: INVALID_KERNEL_HANDLE. Com o rastreamento de identificador habilitado, o kernel coletará rastreamentos de pilha para operações recentes de abertura e fechamento do identificador. Os rastreamentos de pilha podem ser exibidos no depurador de kernel usando a extensão do depurador !htrace . Para obter mais informações sobre o !htrace, consulte a documentação Ferramentas de Depuração para Windows.

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

  • UserMode Wait for Synchronization Objects Allocated on the Kernel Stack

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

    Alocar objetos de sincronização, como estruturas KEVENT, como variáveis locais na pilha de kernel é uma prática comum. Enquanto um processo é carregado na memória, as pilhas de kernel de seus threads nunca são cortadas do conjunto de trabalho ou paginada para o disco. A alocação de objetos de sincronização em tal memória não locá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 qualificado para ser trocado para o disco. Portanto, se um driver especificar UserMode como o parâmetro WaitMode , o sistema operacional poderá trocar o processo atual, desde que todos os outros threads no mesmo processo também sejam aguardados como UserMode. Trocar um processo inteiro pelo disco inclui paginar suas pilhas de kernel. Aguardar um objeto de sincronização que o sistema operacional tenha trocado 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 a memória paginada ou trocada em DISPATCH_LEVEL ou superior resulta em uma falha 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 no UserMode não estão alocados na pilha de kernel do thread atual. Quando o Verificador de Driver detecta uma espera incorreta, ele emite uma 0xC4 de Verificação de Bugs: DRIVER_VERIFIER_DETECTED_VIOLATION, com um valor de parâmetro 1 de 0x123.

  • Referências incorretas do identificador de kernel

    Cada processo do Windows tem uma tabela de identificadores. Você pode exibir a tabela de identificador 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 como 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 0x93 de Verificação de Bugs: INVALID_KERNEL_HANDLE se a opção Verificações Diversas do Verificador de Driver estiver habilitada. Normalmente, esse tipo de referência incorreta de identificador significa que o driver já fechou esse identificador, mas está tentando continuar a usá-lo. Esse tipo de defeito pode resultar em problemas imprevisíveis para o sistema porque o valor do identificador 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, faz referência ao identificador fechado, o Verificador de Driver força o bug marcar conforme descrito anteriormente. Nesse caso, a saída da extensão do depurador !htrace fornece o rastreamento de pilha 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 marcar a ObReferenceObjectByHandle. Agora é proibido passar um identificador de espaço do usuário com acesso KernelMode. Se essa combinação for detectada, o Verificador de Driver emitirá 0xC4 de Verificação de Bugs: 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 Selecionando 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 é efetiva imediatamente, mas é perdida quando você desliga ou reinicializa o computador. Para obter detalhes, consulte Usando 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 de 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 o verificador !, consulte a documentação ferramentas de depuração para Windows .)

No exemplo a seguir, a opção Verificações Diversas detectou uma estrutura ERESOURCE ativa na memória que o driver estava tentando liberar, resultando em 0xC4 de Verificação de Bugs: DRIVER_VERIFIER_DETECTED_VIOLATION. A exibição 0xC4 de Verificação de Bugs inclui 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 Driver.

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