Criar Processamento
Para um sistema de arquivos, a maior parte do trabalho de segurança interessante ocorre durante IRP_MJ_CREATE processamento. É essa etapa que deve analisar a solicitação de entrada, determinar se o chamador tem os direitos apropriados para executar a operação e conceder ou negar a operação conforme apropriado. Felizmente, para desenvolvedores do sistema de arquivos, a maior parte do mecanismo de decisão é implementada no Monitor de Referência de Segurança. Assim, na maioria dos casos, o sistema de arquivos precisa chamar apenas as rotinas apropriadas do Monitor de Referência de Segurança para determinar corretamente o acesso. O risco para um sistema de arquivos ocorre quando ele falha ao chamar essas rotinas conforme necessário e concede acesso inadequado a um chamador.
Para um sistema de arquivos padrão, como o sistema de arquivos FAT, as verificações feitas como parte de IRP_MJ_CREATE são principalmente verificações de semântica. Por exemplo, o sistema de arquivos FAT tem várias verificações para garantir que IRP_MJ_CREATE processamento seja permitido com base no estado do arquivo ou diretório. Essas verificações feitas pelo sistema de arquivos FAT incluem verificações de mídia somente leitura (por exemplo, tentativas de executar operações destrutivas de "criação", como substituição ou substituição, em mídia somente leitura não são permitidas), verificações de acesso de compartilhamento e verificações de oplock. Uma das partes mais difíceis dessa análise é perceber que uma operação em um nível (o nível do arquivo, por exemplo) pode de fato ser proibida devido ao estado de um recurso de nível diferente (o nível de volume, por exemplo). Por exemplo, um arquivo poderá não ser aberto se outro processo tiver bloqueado exclusivamente o volume. Casos comuns para marcar incluiriam:
O nível de arquivo aberto é compatível com o estado de nível de volume? O bloqueio no nível do volume deve ser obedecida. Portanto, se um processo mantiver um bloqueio de nível de volume exclusivo, somente os threads dentro desse processo poderão abrir arquivos. Threads de outros processos não devem ter permissão para abrir arquivos.
O nível de arquivo aberto é compatível com o estado de mídia? Determinadas operações "create" modificam o arquivo como parte da operação "create". Isso incluiria substituir, substituir e até mesmo atualizar a última hora de acesso no arquivo. Essas operações de "criação" não são permitidas na mídia somente leitura e a hora do último acesso não é atualizada.
O nível de volume aberto é compatível com o estado do nível do arquivo? Um volume exclusivo aberto não seria permitido se houver arquivos existentes abertos no volume. Esse é um problema comum para novos desenvolvedores porque eles tentam abrir o volume e descobrem que ele falha. Quando isso falha, FSCTL_DISMOUNT_VOLUME pode ser usado para invalidar identificadores abertos e forçar uma desmontagem, permitindo acesso exclusivo ao volume recém-montado.
Além disso, os atributos de arquivo devem ser compatíveis. Um arquivo com o atributo somente leitura não pode ser aberto para acesso de gravação. Observe que o acesso desejado deve ser verificado após a expansão dos direitos genéricos ser expandida. Por exemplo, esse marcar no sistema de arquivos FASTFAT está na função FatCheckFileAccess (consulte o arquivo de origem Acchksup.c dos exemplos de fastfat que o WDK contém).
O exemplo de código a seguir é específico para a semântica FAT. Um sistema de arquivos que implementa DACLs também faria uma marcar de segurança adicional usando as rotinas do Monitor de Referência de Segurança (SeAccessCheck, por exemplo.)
//
// check for a read-only Dirent
//
if (FlagOn(DirentAttributes, FAT_DIRENT_ATTR_READ_ONLY)) {
//
// Check the desired access for a read-only Dirent
// Don't allow
// WRITE, FILE_APPEND_DATA, FILE_ADD_FILE,
// FILE_ADD_SUBDIRECTORY, and FILE_DELETE_CHILD
//
if (FlagOn(*DesiredAccess, ~(DELETE |
READ_CONTROL |
WRITE_OWNER |
WRITE_DAC |
SYNCHRONIZE |
ACCESS_SYSTEM_SECURITY |
FILE_READ_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES |
FILE_EXECUTE |
FILE_LIST_DIRECTORY |
FILE_TRAVERSE))) {
DebugTrace(0, Dbg, "Cannot open readonly\n", 0);
try_return( Result = FALSE );
}
Uma marcar mais sutil implementada pelo FASTFAT é garantir que o acesso solicitado pelo chamador seja algo sobre o qual o sistema de arquivos FAT esteja ciente (na função FatCheckFileAccess em Acchksup.c do exemplo de fastfat que o WDK contém):
O exemplo de código a seguir demonstra um conceito importante para a segurança do sistema de arquivos. Verifique se o que é passado para o sistema de arquivos não está fora dos limites do esperado. A abordagem conservadora e adequada da perspectiva da segurança é que, se você não entender uma solicitação de acesso, deverá rejeitar essa solicitação.
//
// Check the desired access for the object.
// Reject what we do not understand.
// The model of file systems using ACLs is that
// they do not type the ACL to the object that the
// ACL is on.
// Permissions are not checked for consistency vs.
// the object type - dir/file.
//
if (FlagOn(*DesiredAccess, ~(DELETE |
READ_CONTROL |
WRITE_OWNER |
WRITE_DAC |
SYNCHRONIZE |
ACCESS_SYSTEM_SECURITY |
FILE_WRITE_DATA |
FILE_READ_EA |
FILE_WRITE_EA |
FILE_READ_ATTRIBUTES |
FILE_WRITE_ATTRIBUTES |
FILE_LIST_DIRECTORY |
FILE_TRAVERSE |
FILE_DELETE_CHILD |
FILE_APPEND_DATA))) {
DebugTrace(0, Dbg, "Cannot open object\n", 0);
try_return( Result = FALSE );
}
Felizmente para sistemas de arquivos, depois que o marcar de segurança tiver sido feito durante o processamento de criação inicial, as verificações de segurança subsequentes serão executadas pelo gerente de E/S. Assim, por exemplo, o gerenciador de E/S garante que os aplicativos de modo de usuário não executem uma operação de gravação em um arquivo que foi aberto apenas para acesso de leitura. Na verdade, um sistema de arquivos não deve tentar impor semântica somente leitura contra o objeto de arquivo, mesmo que ele tenha sido aberto apenas para acesso de leitura, durante a rotina de expedição IRP_MJ_WRITE. Isso ocorre devido à maneira como o gerenciador de memória associa um objeto de arquivo específico a um determinado objeto de seção. A gravação subsequente por meio dessa seção será enviada como operações de IRP_MJ_WRITE no objeto de arquivo, mesmo que o arquivo tenha sido aberto somente leitura. Em outras palavras, a imposição de acesso é feita quando um identificador de arquivo é convertido no objeto de arquivo correspondente em pontos de entrada de serviço do sistema Nt por ObReferenceObjectByHandle.
Há dois locais adicionais em um sistema de arquivos em que as verificações de segurança semânticas devem ser feitas de forma semelhante ao processamento "create":
Durante o processamento de renomeação ou vínculo rígido.
Ao processar operações de controle do sistema de arquivos.
O processamento de renomeação e o processamento do controle do sistema de arquivos são discutidos nas seções subsequentes.
Observe que essa não é uma lista exaustiva de problemas semânticos relacionados ao processamento "criar". A intenção desta seção é chamar a atenção para esses problemas para desenvolvedores do sistema de arquivos. Todos os problemas semânticos devem ser identificados para um sistema de arquivos específico, implementados para atender à semântica específica e testados para garantir que a implementação trate os vários casos.