检查IRP_MJ_CREATE的其他特殊情况

如果调用方没有 SeChangeNotifyPrivilege,则必须在文件系统内IRP_MJ_CREATE处理期间进行其他特殊情况处理。 例如,可以使用文件 ID 或对象 ID 打开的文件可能不允许调用方获取该文件的路径,因为调用方可能没有通过目录树结构访问对象的遍历权限。

你可能希望在文件系统中考虑的情况:

  • FILE_OPEN_BY_FILE_ID - 文件名不应提供给调用方。 由于此信息 (遍历权限) 仅在创建操作期间已知,在文件信息查询调用期间不可用,因此,文件系统必须在IRP_MJ_CREATE期间计算有关遍历权限的信息。

  • SL_OPEN_TARGET_DIRECTORY - 目标文件可能不存在,并且必须检查目录是否有权创建文件。 如果目标确实存在,则可能需要检查删除访问权限。 通常,删除访问检查是在IRP_MJ_SET_INFORMATION处理期间执行重命名操作时完成的。

  • FILE_SUPERSEDEFILE_OVERWRITE - 破坏性操作需要额外的访问权限,即使调用方未显式请求这些权限。 例如,文件系统可能需要 DELETE 访问权限才能执行取代操作。

  • FILE_CREATEFILE_OPEN_IFFILE_OVERWRITE_IF - 建设性操作需要访问在其中创建新对象的父目录。 这是包含目录(而不是对象本身)上的检查,因此类似于前面的代码示例。

  • SL_FORCE_ACCESS_CHECK — 如果在 I/O 堆栈位置中设置了此值,则必须执行检查,就像调用来自用户模式而不是内核模式一样。 因此,即使调用源自内核模式服务器,对安全监视器例程的调用也应指定 UserMode

  • 文件/目录删除 - 这可能基于文件的 ACL 状态 (例如,FILE_WRITE_DATA访问隐式允许删除;如果可以删除数据,则对文件) 具有有效的删除权限,以及目录的 ACL 状态 (FILE_DELETE_CHILD包含目录的权限,例如) 。

下面的代码示例演示了FILE_SUPERSEDE和FILE_OVERWRITE的特殊情况处理,这两种情况都表示调用方隐式需要其他访问权限,即使没有请求。

{
ULONG NewAccess = Supersede ? DELETE : FILE_WRITE_DATA;
ACCESS_MASK AddedAccess = 0;
PACCESS_MASK DesiredAccess = 
    &IrpSp->Paramters.Create.SecurityContext->DesiredAccess;

//
// If the caller does not have restore privilege, they must have write
// access to the EA and attributes for overwrite or supersede.
//
if (0 == (AccessState->Flags & TOKEN_HAS_RESTORE_PRIVILEGE)) {
    *DesiredAccess |= FILE_WRITE_EA | FILE_WRITE_ATTRIBUTES;

    //
    // Does the caller already have this access?
    //
    if (AccessState->PreviouslyGrantedAccess & NewAccess) {

        //
        // No - they need this as well
        //
        *DesiredAccess |= NewAccess;

    }

    //
    // Now check access using SeAccessCheck (omitted)
    //

}

此代码示例是文件系统策略优先位置的一个很好的示例。 调用方未请求 DELETE 访问权限或FILE_WRITE_DATA访问权限,但此类访问是基于文件系统语义执行的操作中固有的。