共用方式為


IRP_MJ_DIRECTORY_CONTROL的安全性檢查

處理特定目錄控制作業時,安全性是考慮事項,特別是處理變更通知的作業。 安全性考慮是目錄變更通知可能會傳回已變更之特定檔案的相關信息。 如果用戶沒有周遊目錄路徑的許可權,則無法將變更的相關信息傳回給使用者。 否則,用戶現在有一個機制可學習使用者不應該擁有之目錄的其他資訊。

支援檔案系統運行時間連結庫的目錄變更通知,可讓文件系統指定回呼函式,以在傳回目錄變更通知之前執行周遊檢查。 此回呼函式會採用大量的參數。 基於安全性考慮,下列三個參數很重要:

  • NotifyContext 是變更通知作用中之目錄的內容。 這會是傳入 FsRtlNotifyFullChangeDirectory 呼叫的 FsContext 參數。

  • TargetContext 是已變更之檔案的內容。 這會是文件系統在呼叫 FsRtlNotifyFilterReportChange 時所傳遞的 TargetContext 參數。

  • 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;
}

例如,對於快取安全性資訊的文件系統,或具有不同數據結構來追蹤檔案和目錄 (例如,使用 結構來追蹤檔案和目錄之間的連結的檔案,可能會有很大的不同) 。 嘗試簡化此範例時,不支援連結的文件系統不會列入考慮。