Поделиться через


Проверки безопасности IRP_MJ_DIRECTORY_CONTROL

Безопасность учитывается при обработке определенных операций управления каталогами, в частности операций, связанных с уведомлениями об изменениях. Проблема безопасности заключается в том, что уведомление об изменении каталога может возвращать сведения о конкретных измененных файлах. Если у пользователя нет прав на прохождение пути к каталогу, сведения об изменении не могут быть возвращены пользователю. В противном случае у пользователя теперь есть механизм для получения дополнительных сведений о каталоге, который не должен иметь пользователь.

Поддержка уведомления об изменении каталога библиотекой времени выполнения файловой системы позволяет файловой системе указать функцию обратного вызова для выполнения обхода проверка перед возвратом уведомления об изменении каталога. Эта функция обратного вызова принимает большое количество параметров. Для обеспечения безопасности важны следующие три параметра.

  • NotifyContext — это контекст каталога, в котором активно уведомление об изменениях. Это будет параметр FsContext , который передается в вызов FsRtlNotifyFullChangeDirectory.

  • TargetContext — это контекст измененного файла. Это будет параметр TargetContext , передаваемый файловой системой при вызове FsRtlNotifyFilterReportChange.

  • SubjectContext — это контекст безопасности потока, запрашивающего уведомление об изменении каталога. Это контекст безопасности субъекта, фиксируемый файловой системой во время вызова уведомления об изменении каталога в FsRtlNotifyFullChangeDirectory.

При изменении файловая система указывает на это библиотеке времени выполнения файловой системы. Затем библиотека времени выполнения файловой системы вызовет функцию обратного вызова, предоставляемую файловой системой, чтобы убедиться, что вызывающему объекту могут быть предоставлены сведения об изменении. Обратите внимание, что файловой системе требуется зарегистрировать функцию обратного вызова, только если для вызывающего требуется проверка. Это происходит, если у вызывающего объекта не включена функция SeChangeNotifyPrivilege, как указано в TOKEN_HAS_TRAVERSE_PRIVILEGE в маркере безопасности вызывающего объекта.

Внутри функции обратного вызова файловая система должна выполнить обход проверка из каталога, указанного параметром NotifyContext, в измененный файл, заданный параметром TargetContext. Пример подпрограммы, приведенный ниже, выполняет такое проверка.

BOOLEAN
FsdNotifyTraverseCheck (
    IN PDIRECTORY_CONTEXT OriginalDirectoryContext,
    IN PFILE_CONTEXT ModifiedDirectoryContext,
    IN PSECURITY_SUBJECT_CONTEXT SubjectContext
    )
{
  BOOLEAN AccessGranted = TRUE;
  PFILE_CONTEXT CurrentDirectoryContext;
  ACCESS_MASK GrantedAccess;
  NTSTATUS Status;
  PPRIVILEGE_SET Privileges = NULL;
  PFILE_CONTEXT TopDirectory;

  //
  //  Nothing to do if there is no file context.
  //
  if (ModifiedDirectoryContext == NULL) {

    return TRUE;
  }

  //
  // If the directory that changed is the original directory,
  // we can return , since the caller has access.
  // Note that the directory  context is unique to the specific
  // open instance, while the modified directory context
  // represents the per-file/directory context.
  // How these data structures work in your file system will vary.
  //
  if (OriginalDirectoryContext->FileContext == ModifiedDirectoryContext) {
    return TRUE;
  }

  //
  // Lock the subject context.
  //
  SeLockSubjectContext(SubjectContext);

  for( TopDirectory = OriginalDirectoryContext->FileContext,
          CurrentDirectoryContext = ModifiedDirectoryContext;
          CurrentDirectoryContext == TopDirectory || !AccessGranted;
          CurrentDirectoryContext = CurrentDirectoryContext->ParentDirectory) {
    //
    // Ensure we have the current security descriptor loaded for
    // this directory.
    //
    FsdLoadSecurity( NULL, CurrentDirectoryContext);

    //
    // Perform traverse check.
    //
    AccessGranted = SeAccessCheck(
            CurrentDirectoryContext->SecurityDescriptor,
            SubjectContext,
            TRUE,
            FILE_TRAVERSE,
            0,
            &Privileges,
            IoGetFileObjectGenericMapping(),
            UserMode,
            &GrantedAccess,
            &Status);

    //
    // At this point, exit the loop if access was not granted,
    // or if the parent directory is the same as where the change
    // notification was made.
    //

  }

  //
  // Unlock subject context.
  //
  SeUnlockSubjectContext(SubjectContext);

  return AccessGranted;
}

Эта подпрограмма, скорее всего, существенно отличается для файловых систем, которые кэшируют сведения о безопасности или имеют различные структуры данных для отслеживания файлов и каталогов (например, файлы, использующие структуру для отслеживания связей между файлами и каталогами). Файловые системы, поддерживающие ссылки, не рассматриваются в этом примере в попытке упростить пример.