Completing a failed Create in post callback

CurrentByteOffset is special because it’s updated by the file system on on
each (successful) synchronous read and write. It also is updated as a result
of IRP_MJ_SET_INFORMATION/FilePositionInformation.

You should also sync some other fields in PostCreate:

UserFileObject->DeletePending = LowerFileObject->DeletePending;
UserFileObject->ReadAccess = LowerFileObject->ReadAccess;
UserFileObject->WriteAccess = LowerFileObject->WriteAccess;
UserFileObject->DeleteAccess = LowerFileObject->DeleteAccess;
UserFileObject->SharedRead = LowerFileObject->SharedRead;
UserFileObject->SharedWrite = LowerFileObject->SharedWrite;
UserFileObject->SharedDelete = LowerFileObject->SharedDelete;

Sometimes higher filters look at these fields to check for data access. Note
that they shouldn’t change after PostCreate (though some filters will muck
with them for their own twisted reasons).

-scott
OSR
@OSRDrivers

Thanks Scott. All seems OK except a problem I have hit with renames: both the parent FO (C:\Windows\System32\drivers\etc) and target FO (C:\Windows\System32\drivers\etc\hosts) are being ‘shadowed’ because the user is a standard user and MoveFileW requires FILE_ADD_FILE access for the parent and DELETE for the file itself. I positioned FileSpy below my driver and this is the output:

Process Request IRP Flags FileObject FO Flags Path Status More info

1 MoveHostsBak.exe IRP_MJ_CREATE 00000884 FFFFFA803422D610 00000002 C:\Windows\System32\drivers\etc\hosts STATUS_ACCESS_DENIED FILE_OPEN CreOpts: 00200020 Access: 00110080 Share: 00000007 Attrib: 0
2 MoveHostsBak.exe IRP_MJ_CREATE 00000884 FFFFFA8034B0BD60 00000002 C:\Windows\System32\drivers\etc\hosts STATUS_SUCCESS FILE_OPEN CreOpts: 00200020 Access: 00110080 Share: 00000007 Attrib: 0 Result: FILE_OPENED
3 MoveHostsBak.exe IRP_MJ_QUERY_INFORMATION 00060870 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_SUCCESS FileAttributeTagInformation
4 MoveHostsBak.exe IRP_MJ_QUERY_INFORMATION 00000010 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_BUFFER_OVERFLOW FileNameInformation
5 MoveHostsBak.exe IRP_MJ_QUERY_INFORMATION 00000010 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_SUCCESS FileNameInformation
6 MoveHostsBak.exe IRP_MJ_QUERY_INFORMATION 00000000 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_SUCCESS FileBasicInformation Attrib: 00000020
7 MoveHostsBak.exe IRP_MJ_CREATE 00000884 FFFFFA8031213730 00000000 C:\Windows\System32\drivers\etc STATUS_ACCESS_DENIED FILE_OPEN CreOpts: 0 Access: 00100002 Share: 00000003 Attrib: 0
8 MoveHostsBak.exe IRP_MJ_CREATE 00000884 FFFFFA8031696670 00000000 C:\Windows\System32\drivers\etc STATUS_SUCCESS FILE_OPEN CreOpts: 0 Access: 00100002 Share: 00000003 Attrib: 0 Result: FILE_OPENED
9 MoveHostsBak.exe IRP_MJ_QUERY_INFORMATION 00000000 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_SUCCESS 00000036
10 MoveHostsBak.exe IRP_MJ_SET_INFORMATION 00060830 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_ACCESS_DENIED FileRenameInformation
11 MoveHostsBak.exe IRP_MJ_CLEANUP 00000404 FFFFFA8031696670 00040000 C:\Windows\System32\drivers\etc STATUS_SUCCESS
12 MoveHostsBak.exe IRP_MJ_CLEANUP 00000404 FFFFFA8034B0BD60 00040042 C:\Windows\System32\drivers\etc\hosts STATUS_SUCCESS

You can see the file and its parent being shadowed in #2 and #8 respectively (FFFFFA803422D610 is shadowed by FFFFFA8034B0BD60 and FFFFFA8031213730 is shadowed by FFFFFA8031696670)
In my driver I see #8 come through with the path […]etc\hosts.bak and the SL_OPEN_TARGET_DIRECTORY flag set which I believe is what I should expect and I pass it to FltCreateFileEx in this form.
In my IRP_MJ_SET_INFORMATION pre-handler, I replace Data->Iopb->TargetFileObject with its ‘lower’ FO and Data->Iopb->Parameters.SetFileInformation.ParentOfTarget with its ‘lower’ FO then FltSetCallbackDataDirty.
The root directory in the rename info is NULL.

The result in #10 is that I still get access denied, even though my parent and child objects were successfully created and swapped in when the FileRenameInformation came through.

So my question is why is the rename still returning access denied when the file objects appear to have been successfully created and swapped over?
Is there another check below my driver that maybe causing this? Do I need to impersonate? Or is there something about the FileRenameInformation that I don’t understand?

Thanks again,

Ian

Nothing obvious to me, if you’re performing equivalent opens and swapping the file object it should “just work.”

Can you reproduce this over FAT? That makes life easier because you can just look up where the error is coming from. If not, NTFS has status debugging that will at least help pinpoint the check that’s failing. Which version of the OS is running on the target?

Thanks - I saw your post too. It’s Windows 7 and when I turn on the NTFS debugging it breaks here

Ntfs!NtfsStatusDebug+0x99
Ntfs!NtfsCheckIndexForAddOrDelete+0x124
Ntfs!NtfsSetRenameInfo+0x145a
Ntfs!NtfsCommonSetInformation+0x7d5
Ntfs!NtfsFsdSetInformation+0x124
fltmgr!FltpLegacyProcessingAfterPreCallbacksCompleted+0x24f
fltmgr!FltpDispatch+0xcf

and it looks like the underlying access check is performed by SeAccessCheckWithHint (called by TxfAccessCheck) CheckIndexForAddOrDelete suggests that it’s checking access to the parent directory. Is there any way of finding out what the parameters are for these functions? The prototype for SeAccessCheck is out there, but not the newer ones.

I’m not sure I can reproduce the issue on FAT because I’m fixing up an ACCESS_DENIED.

Is there a way to get more logging from NTFS or SeAccessCheckWithHint so I can see which permissions it thinks I don’t have?

I’ve had a bit more of a look and NtfsCheckIndexForAddOrDelete ends up calling SepAccessCheck:

nt!SepAccessCheck+5f
nt!SeAccessCheckWithHint+178 (perf)
Ntfs!TxfAccessCheck+123
Ntfs!NtfsCheckIndexForAddOrDelete+e7
Ntfs!NtfsSetRenameInfo+145a

The parameters appear to contain an SD and a Token. The SD is from the parent directory which is OK but the Token looks like its from the standard user who I am trying to allow access to. Why would the filesystem need to perform another access check when access to the two file objects has already been checked and granted?