建立處理
對於檔案系統,大部分有趣的安全性工作會在 處理IRP_MJ_CREATE 期間發生。 這是必須分析傳入要求、判斷呼叫端是否具有執行作業的適當許可權,以及適當地授與或拒絕作業的此步驟。 幸運的是,對於檔案系統開發人員,大部分決策機制都是在安全性參考監視器內實作。 因此,在大部分情況下,檔案系統只需要呼叫適當的安全性參考監視器常式,才能正確判斷存取權。 檔案系統無法視需要呼叫這些常式,並不當授與呼叫端的存取權時,就會發生檔案系統的風險。
對於標準檔案系統,例如 FAT 檔案系統,在IRP_MJ_CREATE過程中所做的檢查主要是語意檢查。 例如,FAT 檔案系統有許多檢查,以確保根據檔案或目錄的狀態允許IRP_MJ_CREATE處理。 FAT 檔案系統所做的這些檢查包括唯讀媒體的檢查 (例如,嘗試在唯讀媒體上執行破壞性「建立」作業,例如覆寫或取代,在唯讀媒體上不允許) 、共用存取檢查和 oplock 檢查。 此分析的其中一個最困難部分是瞭解一個層級 (檔案層級的作業,例如,因為不同層級資源的狀態 (磁片區層級,例如) ,所以可能不允許) 。 例如,如果另一個進程已獨佔鎖定磁片區,則檔案可能無法開啟。 檢查的常見案例包括:
檔案層級是否與磁片區層級狀態相容? 必須遵守磁片區層級鎖定。 因此,如果某個進程保留獨佔磁片區層級鎖定,則只有該進程內的執行緒可以開啟檔案。 不允許來自其他進程的執行緒開啟檔案。
檔案層級是否與媒體狀態相容? 某些「建立」作業會將檔案修改為「建立」作業的一部分。 這包括覆寫、取代,甚至更新檔案上的上次存取時間。 唯讀媒體不允許這些「建立」作業,而且上次存取時間不會更新。
磁片區層級是否與檔案層級狀態相容? 如果磁片區上有開啟的現有檔案,則不允許開啟獨佔磁片區。 這是新開發人員的常見問題,因為他們嘗試開啟磁片區併發現磁片區失敗。 當此失敗時,FSCTL_DISMOUNT_VOLUME可用來使開啟控制碼失效,並強制卸載,允許對新掛接的磁片區進行獨佔存取。
此外,檔案屬性必須相容。 無法開啟具有唯讀屬性的檔案以進行寫入存取。 請注意,擴充泛型許可權之後,應該檢查所需的存取權。 例如,FASTFAT 檔案系統內的這項檢查位於 FatCheckFileAccess 函式中, (從 WDK 包含) 的 fastfat 範例中看到 Acc hksup.c 原始程式檔。
下列程式碼範例是 FAT 語意特有的。 實作 DACL 的檔案系統也會使用安全性參考監視器常式 (SeAccessCheck執行額外的安全性檢查,例如.)
//
// 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 );
}
FASTFAT 所實作的更細微檢查是確保呼叫端所要求的存取權是 FAT 檔案系統在 Acchksup.c 的 fastfat) 範例中, (在 Acchksup.c 的 FatCheckFileAccess 函式中知道的存取權:
下列程式碼範例示範檔案系統安全性的重要概念。 檢查以確定傳遞至檔案系統的專案不會落在您預期的界限之外。 從安全性的觀點來看,保守且適當的方法是,如果您不知道存取要求,您應該拒絕該要求。
//
// 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 );
}
幸運的是,檔案系統在初始建立處理期間完成安全性檢查之後,I/O 管理員會執行後續的安全性檢查。 因此,例如,I/O 管理員可確保使用者模式應用程式不會對僅開啟以供讀取存取的檔案執行寫入作業。 事實上,檔案系統不應該嘗試對檔案物件強制執行唯讀語意,即使它只在IRP_MJ_WRITE分派常式期間開啟,也一樣。 這是因為記憶體管理員將特定檔案物件與指定的區段物件產生關聯的方式。 後續的寫入該區段將會以檔案物件上的IRP_MJ_WRITE作業的形式傳送,即使檔案已開啟唯讀也一樣。 換句話說,當檔案控制碼由 ObReferenceObjectByHandle轉換成 Nt 系統服務進入點的對應檔案物件時,就會強制執行存取。
檔案系統中還有兩個額外的位置,語意安全性檢查必須與「建立」處理類似:
重新命名或硬式連結處理期間。
處理檔案系統控制作業時。
後續各節將討論重新命名處理和檔案系統控制項處理。
請注意,這不是與「建立」處理相關的語意問題完整清單。 本節的目的是要注意檔案系統開發人員的這些問題。 必須識別特定檔案系統的所有語意問題、實作以符合特定語意,並經過測試以確保實作處理各種案例。