Partilhar via


Controlos diversos

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

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 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 de lookaside ativas na memória liberada. O driver chama ExFreePool para liberar um bloco de pool que ainda contém listas de 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 Instrumentação de Gerenciamento do Windows (WMI) e do Rastreamento de Eventos para Windows (ETW). Tais problemas detetados pelo Verificador de Driver incluem:

    • Um driver que tenta descarregar sem cancelar o registo do seu callback WMI.

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

    • Um driver que tenta descarregar sem desregistrar os seus provedores ETW em modo kernel.

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

  • Erros de manipulação do kernel. (Windows Vista e versões posteriores) Ativar a opção Miscellaneous Checks também permitirá o rastreamento de handles para o processo do sistema, ajudando a investigar vazamentos de handles no kernel e Bug Check 0x93: INVALID_KERNEL_HANDLE. Com o rastreamento de alças ativado, o kernel coletará rastreamentos de pilha para operações recentes de abertura e fecho de alças. 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 de 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. Não é possível passar um identificador de modo de usuário com acesso ao modo kernel. Se tal operação ocorrer, o Verificador de Driver emitirá uma verificação de erro 0xC4, com um valor do parâmetro 1 de 0xF6.

  • UserMode Aguarde objetos de sincronização alocados na pilha do kernel

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

    A alocação de objetos de sincronização, tais como 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 nessa memória não paginá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 todas as threads de um processo estão em espera no modo UserMode, esse processo se torna elegível para ser transferido para o disco. Portanto, se um driver especificou UserMode como o parâmetro WaitMode , o sistema operacional pode trocar o processo atual, desde que todos os outros threads no mesmo processo estejam aguardando como UserMode também. Trocar um processo inteiro para o disco inclui paginar suas pilhas de kernel. Aguardar por um objeto de sincronização que o sistema operativo substituiu está incorreto. Em algum momento, um thread deve aparecer e sinalizar o objeto de sincronização. A sinalização de um objeto de sincronização envolve o kernel do Windows manipulando o objeto em IRQL = DISPATCH_LEVEL ou superior. Tocar na memória paginada ou descarregada em nível de DISPATCH_LEVEL ou superior provoca 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 do kernel do thread atual. Quando o Driver Verifier deteta uma espera incorreta, ele emite um Bug Check 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION, com um valor de parâmetro 1 de 0x123.

  • Referências incorretas do manipulador do kernel

    Cada processo do Windows tem uma tabela de handles. 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 é um identificador válido para a tabela de identificadores do processo do sistema. Um identificador de usuário como um identificador que é válido para qualquer processo, exceto o processo do sistema.

    No Windows 7, o Verificador de Driver deteta tentativas de fazer referência a valores de identificador do kernel que estão incorretos. Esses defeitos de driver são relatados como um Bug Check 0x93: INVALID_KERNEL_HANDLE se a opção Verificações Diversas do Driver Verifier estiver ativada. Normalmente, esse tipo de referência incorreta significa que o driver já fechou essa alça, mas ainda tenta usá-la. Esse tipo de defeito pode resultar em problemas imprevisíveis para o sistema porque o valor do handle que está a ser referenciado já pode ter sido reutilizado por outro driver não relacionado.

    Se um driver do kernel fechou recentemente um identificador do kernel e mais tarde faz referência ao identificador fechado, o Verificador de Driver força a verificação de bugs 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 este handle. Use o endereço do processo do sistema como um parâmetro para !htrace. Para encontrar 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 um identificador de espaço de usuário com acesso KernelMode. Se essa combinação for detetada, o Verificador de Driver emitirá Bug Check 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION, com um valor do parâmetro 1 de 0xF6.

Ativando esta opção

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

  • 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 entra em vigor imediatamente, mas é perdida quando você desliga ou reinicia o computador. Para obter detalhes, consulte Usando Configuração Volátil.

    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 Gestor do Verificador de Drivers

    1. Inicie o Driver Verifier Manager. Digite Verifier numa janela da Linha de Comandos.

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

    3. Selecione configurações individuais de 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 Verificadores de Driver, clique em Criar Configurações Padrão.

Visualizando os resultados

Para visualizar os resultados da opção Miscellaneous Checks, use a extensão !verifier no depurador do 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 detetou uma estrutura ERESOURCE ativa na memória que o driver estava a tentar libertar, resultando em Bug Check 0xC4: DRIVER_VERIFIER_DETECTED_VIOLATION. O ecrã de verificação de erros 0xC4 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, utilize a extensão do depurador !locks (!kdext*.locks) junto 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 que o Verificador de Driver intercetou.

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