Criando drivers de Kernel-Mode confiáveis

Os drivers compõem uma porcentagem significativa do código total que é executado no modo kernel. Um driver de modo kernel é, na verdade, um componente do sistema operacional. Portanto, os drivers confiáveis e seguros contribuem significativamente para a confiabilidade geral do sistema operacional. Para criar um driver confiável no modo kernel, siga estas diretrizes:

  • Proteger objetos de dispositivo corretamente.

    O acesso do usuário aos drivers e dispositivos de um sistema é controlado por descritores de segurança que o sistema atribui a objetos de dispositivo. Na maioria das vezes, o sistema define parâmetros de segurança do dispositivo quando um dispositivo é instalado. Para obter mais informações, consulte Criando instalações de dispositivo seguro. Às vezes, é apropriado que um driver tenha um papel no controle do acesso ao dispositivo. Para obter mais informações, consulte Protegendo objetos de dispositivo.

  • Valide os objetos do dispositivo corretamente.

    Se um driver criar vários tipos de objetos de dispositivo, ele deverá marcar qual tipo ele recebe em cada IRP. Para obter mais informações, consulte Falha ao validar objetos de dispositivo.

  • Use funções de "cadeia de caracteres segura".

    Ao manipular cadeias de caracteres, um driver deve usar funções de cadeia de caracteres seguras em vez das funções de cadeia de caracteres fornecidas com bibliotecas de runtime de linguagem C/C++. Para obter mais informações, consulte Usando funções de cadeia de caracteres seguras.

  • Validar identificadores de objeto.

    Os drivers que recebem identificadores de objeto como entrada devem verificar se os identificadores são válidos, podem ser acessados e são do tipo esperado. Para obter mais informações sobre como usar identificadores de objeto, consulte os seguintes tópicos:

    Gerenciamento de Objetos

    Falha ao validar identificadores de objeto

  • Suporte a vários processadores corretamente.

    Nunca suponha que o driver seja executado somente em sistemas de processador único. Para obter informações sobre técnicas de programação que você pode usar para garantir que o driver funcione corretamente em sistemas multiprocessadores, consulte os seguintes tópicos:

    Técnicas de sincronização

    Erros em um ambiente multiprocessador

  • Manipule o estado do driver corretamente.

    É importante sempre verificar se o driver está no estado em que você pressupõe que ele esteja. Por exemplo, se o driver receber um IRP, ele já está atendendo um IRP do mesmo tipo? Se o driver não marcar para essa situação, o primeiro IRP poderá ser perdido. Para obter mais informações, consulte Falha ao verificar o estado de um driver.

  • Validar valores de entrada IRP.

    É essencial, tanto de uma perspectiva de confiabilidade quanto de segurança, validar todos os valores associados a um IRP, como endereços de buffer e comprimentos. Os tópicos a seguir fornecem informações sobre como validar valores de entrada IRP:

    DispatchReadWrite usando E/S em buffer

    Erros de E/S em buffer

    DispatchReadWrite usando E/S Direta

    Erros de E/S Direta

    Problemas de segurança para códigos de controle de E/S

    Erros ao referenciar endereços de User-Space

  • Manipule a pilha de E/S corretamente.

    Ao passar IRPs para baixo na pilha do driver, é importante que os drivers chamem IoSkipCurrentIrpStackLocation ou IoCopyCurrentIrpStackLocationToNext para configurar o local da pilha de E/S do próximo driver. Não escreva código que copie diretamente um local de pilha de E/S para o próximo.

  • Manipule as operações de conclusão do IRP corretamente.

    Um driver nunca deve concluir um IRP com um valor status de STATUS_SUCCESS a menos que ele realmente dê suporte e processe o IRP. Para obter informações sobre as maneiras corretas de lidar com as operações de conclusão do IRP, consulte Concluindo IRPs.

  • Manipule as operações de cancelamento de IRP corretamente.

    As operações de cancelamento podem ser difíceis de codificar corretamente porque normalmente são executadas de forma assíncrona. Problemas no código que manipula operações de cancelamento podem passar despercebidos por um longo tempo, pois esse código normalmente não é executado com frequência em um sistema em execução.

    Certifique-se de ler e entender todas as informações fornecidas em Cancelar IRPs. Preste atenção especial à sincronização de cancelamento de IRP e pontos a serem considerados ao cancelar IRPs.

    Uma maneira de evitar os problemas de sincronização associados às operações de cancelamento é implementar uma fila IRP segura para cancelamento. Uma fila IRP com segurança de cancelamento é uma fila gerenciada por driver que foi introduzida para o Windows XP e versões posteriores do sistema operacional, mas também é compatível com versões anteriores.

  • Manipule as operações de limpeza e fechamento do IRP corretamente.

    Certifique-se de entender a diferença entre solicitações de IRP_MJ_CLEANUP e IRP_MJ_CLOSE . As solicitações de limpeza chegam depois que um aplicativo fecha todos os identificadores em um objeto de arquivo, mas às vezes antes de todas as solicitações de E/S terem sido concluídas. As solicitações de fechamento chegam depois que todas as solicitações de E/S para o objeto de arquivo foram concluídas ou canceladas. Para obter mais informações, consulte estes tópicos:

    Rotinas DispatchCreate, DispatchClose e DispatchCreateClose

    Rotinas dispatchCleanup

    Erros ao lidar com operações de limpeza e fechamento

Para obter mais informações sobre como lidar com IRPs corretamente, consulte Erros adicionais na manipulação de IRPs.

Usando o Verificador de Driver

O Verificador de Driver é a ferramenta mais importante que você pode usar para garantir a confiabilidade do driver. O Verificador de Driver pode marcar para uma variedade de problemas comuns de driver, incluindo alguns dos discutidos nesta seção. No entanto, o uso do Verificador de Driver não substitui o design de software cuidadoso e atencioso.