檢查IRP_MJ_CREATE周遊許可權
其中一個主要考慮 IRP_MJ_CREATE 檢查是呼叫端是否具有 周遊 許可權,這是存取物件路徑的許可權。 也就是說,呼叫端可以存取 dirA/dirB/file之類的檔案物件,但無法存取該檔案物件路徑中目錄的內容, (dirA 和 dirA/dirB) 。
根據預設,Windows 會將周遊許可權授與所有使用者。 「User Right」 常數是 SeChangeNotifyPrivilege,其會對應至 ACCESS_MASK 中的 FILE_TRAVERSE。 身為安全性功能,系統管理員可以從使用者移除周遊許可權。
由於大部分呼叫端都有周遊許可權,因此檔案系統通常會在 IRP 安全性內容的 AccessState-Flags > 欄位中檢查此許可權,
BOOLEAN traverseCheck =
!(IrpContext->IrpSp->Parameters.Create.SecurityContext->AccessState->Flags
& TOKEN_HAS_TRAVERSE_PRIVILEGE);
檔案系統會使用 旗標 來追蹤作業進度中已授與哪些存取權限。 然後檔案系統可以先快速檢查存取狀態位,並避免存取檢查呼叫的費用,如果已授與存取權 (周遊Check = 0) 。
如果先前尚未授與周遊許可權,檔案系統必須在每個目錄上執行周遊檢查,並沿著開啟的檔案路徑執行周遊檢查。 在下面的部分程式碼片段中,周遊檢查是使用泛型常式來完成,通常用於大部分的安全性檢查:
{
// accessParams is passed to the file system and is normally based
// on the fields of the same name from the IRP.
// Only one thread can be looking at this data structure in memory
// at a time (and potentially changing it), so acquire a lock on it.
SeLockSubjectContext(
&accessParams.AccessState->SubjectSecurityContext);
// Check whether the desired access can be granted.
// For this example, assume desiredAccess = FILE_TRAVERSE
granted = SeAccessCheck( Fcb->SecurityDescriptor,
&AccessParams.AccessState->SubjectSecurityContext,
TRUE,
AccessParams.desiredAccess,
0,
&Privileges,
IoGetFileObjectGenericMapping(),
AccessParams.AccessMode,
&AccessParams.GrantedAccess,
&AccessParams.status );
// The file system uses AccessState to cache access privileges
// that have been granted thus far along the operation's code
// path. Update AccessState with the newly acquired Privileges.
if (Privileges != NULL) {
(void) SeAppendPrivileges(AccessParams.AccessState, Privileges );
SeFreePrivileges( Privileges );
Privileges = NULL;
}
if (granted) {
//
// The desired access was granted, so clear the
// granted bits from desiredAccess.
//
AccessParams.desiredAccess &=
~(AccessParams.GrantedAccess | MAXIMUM_ALLOWED);
if (!checkOnly) {
//
// The caller wants to modify the access state for this
// request
//
AccessParams.AccessState->PreviouslyGrantedAccess |=
AccessParams.GrantedAccess;
}
if (maxDesired) {
maxDelete =
(BOOLEAN)(AccessParams.AccessState->PreviouslyGrantedAccess &
DELETE);
maxReadAttr =
(BOOLEAN)(AccessParams.AccessState->PreviouslyGrantedAccess &
FILE_READ_ATTRIBUTES);
}
AccessParams.AccessState->RemainingDesiredAccess &=
~(AccessParams.GrantedAccess | MAXIMUM_ALLOWED);
}
// Release the lock on the security context
SeUnlockSubjectContext(&accessParams.AccessState->SubjectSecurityContext);
}
此函式會執行一般安全性檢查。 此函式必須處理下列問題:
它必須指定要用於檢查的正確安全性描述元。
它必須沿著安全性內容傳遞, (這些是執行作業的實體認證) 。
它必須根據安全性檢查的結果來更新存取狀態。
它必須考慮 MAXIMUM_ALLOWED 選項, (請參閱 ntifs.h) 。 MAXIMUM_ALLOWED 選項會指定檔案系統應該設定檔案系統 (讀取/寫入/刪除允許的最大存取權,例如) 。 非常少的應用程式會使用 MAXIMUM_ALLOWED 選項,因為 FASTFAT 檔案系統不支援此選項。 因為MAXIMUM_ALLOWED選項位不是 FASTFAT 檔案系統辨識的其中一個存取位,所以它會拒絕對指定檔案的存取要求。 嘗試在 FASTFAT 磁片區上開啟檔案且設定MAXIMUM_ALLOWED選項的應用程式,會發現要求失敗。 如需詳細資訊,請參閱 WDK 所包含之 FASTFAT 範例程式碼之 Acc hksup.c 原始程式檔中的 FatCheckFileAccess 函式。
請注意,針對簡單的周遊檢查,要求存取權會 FILE_TRAVERSE ,而安全性描述元會是呼叫端嘗試周遊的目錄,而不是從原始 IRP_MJ_CREATE IRP 要求存取。