Nota
O acesso a esta página requer autorização. Podes tentar iniciar sessão ou mudar de diretório.
O acesso a esta página requer autorização. Podes tentar mudar de diretório.
O problema de E/S direta mais comum é não conseguir lidar corretamente com buffers de comprimento zero. Como o gerenciador de E/S não cria MDLs para transferências de comprimento zero, um buffer de comprimento zero resulta em um valor NULL em Irp-MdlAddress>.
Para mapear o espaço de endereço, os drivers devem usar MmGetSystemAddressForMdlSafe, que retorna NULL se o mapeamento falhar, como será se um driver passar um MdlAddressNULL. Os condutores devem sempre verificar se o retorno é NULL antes de tentar usar o endereço retornado.
A E/S direta envolve o mapeamento duplo do espaço de endereçamento do usuário para um buffer de endereços do sistema, para que dois endereços virtuais diferentes tenham o mesmo endereço físico. O mapeamento duplo tem as seguintes consequências, que às vezes podem causar problemas para os drivers:
O deslocamento para a página virtual do endereço do usuário torna-se o deslocamento para a página do sistema.
O acesso além do final desses buffers do sistema pode passar despercebido por longos períodos de tempo, dependendo da granularidade da página do mapeamento. A menos que o buffer de um chamador seja alocado perto do final de uma página, os dados gravados além do final do buffer aparecerão no buffer e o chamador não saberá que ocorreu qualquer erro. Se o fim do buffer coincidir com o final de uma página, os endereços virtuais do sistema além do final podem apontar para qualquer coisa ou podem ser inválidos. Tais problemas podem ser extremamente difíceis de encontrar.
Se o processo de chamada tiver outro thread que modifique o mapeamento da memória do usuário, o conteúdo do buffer do sistema será alterado quando o mapeamento de memória do usuário for alterado.
Nessa situação, usar o buffer do sistema para armazenar dados de rascunho pode causar problemas. Duas buscas do mesmo local de memória podem produzir valores diferentes.
O trecho de código a seguir recebe uma cadeia de caracteres em uma solicitação de E/S direta e, em seguida, tenta converter essa cadeia de caracteres em caracteres maiúsculos:
PWCHAR PortName = NULL; PortName = (PWCHAR)MmGetSystemAddressForMdlSafe(irp->MdlAddress, NormalPagePriority); // // Null-terminate the PortName so that RtlInitUnicodeString will not // be invalid. // PortName[Size / sizeof(WCHAR) - 1] = UNICODE_NULL; RtlInitUnicodeString(&AdapterName, PortName);Como o buffer pode não estar formado corretamente, o código tenta forçar um Unicode NULL como o último caractere de buffer. No entanto, se a memória física subjacente for duplamente mapeada em um endereço de modo usuário e modo kernel, outro fio de execução no processo poderá sobrescrever o buffer assim que essa operação de gravação for concluída.
Por outro lado, se o NULL não estiver presente, a chamada para RtlInitUnicodeString pode exceder o intervalo do buffer e possivelmente causar uma verificação de bug se ele estiver fora do mapeamento do sistema.
Se um driver criar e mapear o seu próprio MDL, deve garantir que aceda ao MDL apenas com o método para o qual realizou o 'probe'. Ou seja, quando o driver chama MmProbeAndLockPages, ele especifica um método de acesso (IoReadAccess, IoWriteAccess ou IoModifyAccess). Se o driver especificar IoReadAccess, ele não deverá tentar gravar posteriormente no buffer do sistema disponibilizado por MmGetSystemAddressForMdl ou MmGetSystemAddressForMdlSafe.