Unfortunately FAT doesn’t actually support security, so how FAT handles
these things will differ than how NTFS/ReFS do.
Note that FAT there is also additional enforcement of ACCESS_SYSTEM_SECURITY
around Supersede/Overwrite (see FatCheckSystemSecurityAccess). Something
else you want to make sure you don’t inadvertently allow the caller to
bypass.
(Are we having fun yet :))
-scott
OSR
@OSRDrivers
“Ged Murphy” wrote in message news:xxxxx@ntfsd…
Hi Scott,
Thanks for your reply, that’s really useful and I’d certainly overlooked a
few things.
-
Interesting, I must have missed that in my preliminary tests. Perhaps I
got something mixed up in the tests and that would explain the different
results I mentioned I was seeing in Win7 and Win8. I’ll take a look at that
area again.
-
That’s a good point. I do have some access checks in my actual code (not
in the code I posted), but they don’t take into account the read only issue
you pointed out. Looking at the FastFat code, most of the access checks
which MSDN specifies are required actually aren’t, for example :
“The CreateDisposition value FILE_SUPERSEDE requires that the caller have
DELETE access to an existing file object”
The FSD just removes them and adds them anyway
} else if (CreateDisposition == FILE_SUPERSEDE) {
SetFlag( AddedAccess,
DELETE & ~(*DesiredAccess) );
*DesiredAccess |= DELETE;
} else if ((CreateDisposition == FILE_OVERWRITE) ||
(CreateDisposition == FILE_OVERWRITE_IF)) {
SetFlag( AddedAccess,
(FILE_WRITE_DATA | FILE_WRITE_EA |
FILE_WRITE_ATTRIBUTES) & ~(*DesiredAccess) );
*DesiredAccess |= FILE_WRITE_DATA | FILE_WRITE_EA |
FILE_WRITE_ATTRIBUTES;
}
- I’m not currently running the HCK, admittedly I wasn’t aware of it. It
sounds really useful for this scenario though, thanks for the tip.
Additionally, I also have a decision to make about what to do with any other
streams which may be part of the file. If I want to copy how the NTFS driver
works more closely, I should consider deleting all the other streams which
aren’t ‘managed’. This is what the user may be expecting when they supply
one of those flags.
It seems I was a little premature in posting the code, especially as I’m
still in the process of writing tests. However Alex has kindly suggested I
do a write up for his blog once I’ve got everything nailed, so I’ll
hopefully be able to put something useful together once I’m happy with
everything.
Thanks,
Ged.
-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of Scott Noone
Sent: 06 June 2014 15:57
To: Windows File Systems Devs Interest List
Subject: Re:[ntfsd] file_overwrite deletes ads
A few observations:
- Supersede and Overwrite are not completely interchangeable. Supersede
replaces the attributes of the file where Overwrite preserves them. See the
FASTFAT source:
//
// Modify the attributes and time of the file, by first reading
// in the dirent for the file and then updating its attributes
// and time fields. Note that for supersede we replace the file
// attributes as opposed to adding to them.
//
…
if (CreateDisposition == FILE_SUPERSEDE) {
Dirent->Attributes = FileAttributes;
} else {
Dirent->Attributes |= FileAttributes;
}
They also require different access permissions (Supersede requires DELETE,
Overwrite requires WRITE)
-
You have potentially introduced an escalation of privilege with your
changes. It appears that if a user with Read Only access to a file opened
for Supersede your filter would demote the Supersede to an Open and then
truncate the file on the user’s behalf.
-
If you’re not running the IFS HCKs I highly suggest stopping now and
getting them set up. They’re annoying strict about dispositions, access
masks, and resulting behaviors (e.g. attributes preserved vs not preserved),
which is exactly what the kind of validation you want when you’re changing
things like this.
I suspect that the change in behavior that you’re introducing might also
cause the tests to fail, but at that point you have a business decision to
either knowingly not be eligible for logo or seek an exemption.
-scott
OSR
@OSRDrivers
“Ged Murphy” wrote in message
news:xxxxx@ntfsd…
I just thought I’d update this thread with some final information in case
anyone is searching for info on this in the future.
If I had a fancy blog like Alex (and the knowledge to go with it), I
probably would have put it there, but this will have to do J
It seems that contrary to what the docs say, FILE_SUPERSEDE doesn’t actually
replace the file, it just truncates it to zero. This means we can
effectively replicate the functionality of all three dispositions
(SUPERSEDE/OVERWRITE(_IF)) by resetting the file position and end of file
information. In doing this, the only difference (I can see) between using
the available disposition flags, or removing them and doing it yourself in
the post-op is that the flags will do the whole operation within the NTFS
driver, whereas doing it yourself will send two IRP_MJ_SET_INFORMATION irps
down the stack
One area I was concerned about was the change notifications. The FastFat
driver in the WDK samples shows that FILE_SUPERSEDE/OVERWRITE will invoke
the following filters FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE
From my testing, it seems that the NTFS on x86 Win7 seems to do the same,
however the NTFS driver on x64 Win8 only seems to invoke the
FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_SIZE flags (The
FILE_NOTIFY_CHANGE_LAST_WRITE flag is obviously only sent if the file wasn’t
already empty).
In sending the FilePositionInformation and FileEndOfFileInformation to the
FSD, we get exactly the same change notifications as we would do when using
the provided dispositions.
Finally, a bit of brief sample code to show what’s needed.
(note: this is test code and hasn’t been used in a production environment.
It may contain errors)
PreCreate
CreateDisposition = (UCHAR)(Data->Iopb->Parameters.Create.Options >> 24); if
(FileContext->ContainsStreams){ /* Check if the caller requested an
overwrite / if (CreateDisposition == FILE_SUPERSEDE ||
CreateDisposition == FILE_OVERWRITE || CreateDisposition ==
FILE_OVERWRITE_IF) { / * When a overwrite is done on a
primary stream, all the ADS’s that are linked * to that file are
deleted in the NTFS driver. * To fix this, we replace the overwrite
flags with corresponding open flags before * sending it to the FSD,
and we do the overwrite work ourselves in the PostCreate /
RemovedOverwriteFlags = TRUE; / Replace the disposition flag with
the corresponding open flags. SUPERSEDE and OVERWRITE_IF are synonymous /
TempCreateDisposition = (CreateDisposition == FILE_OVERWRITE) ? FILE_OPEN :
FILE_OPEN_IF; / Clear out the old disposition bits /
Data->Iopb->Parameters.Create.Options &= 0x00FFFFFF; / Set the
disposition which we’ll be sending to the FSD to stop the overwrite /
Data->Iopb->Parameters.Create.Options |= TempCreateDisposition << 24;
/ Mark that we have changed something /
FltSetCallbackDataDirty(Data); } / Request a post-op /
CallbackStatus = FLT_PREOP_SUCCESS_WITH_CALLBACK;} PostCreate / Check if
we removed any of the overwrite flags in the pre-op /if
(RemovedOverwriteFlags){ FILE_POSITION_INFORMATION FilePosition;
FILE_END_OF_FILE_INFORMATION EndOfFile; / * The FastFat driver in
the WDK shows that supersede/overwrite will invoke * the following
notify filters: * FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_ATTRIBUTES | FILE_NOTIFY_CHANGE_SIZE; * The NTFS
driver on 32bit Win7 seems to do the same, however the NTFS drvier on x64
Win8 only * seems to invoke the FILE_NOTIFY_CHANGE_LAST_WRITE |
FILE_NOTIFY_CHANGE_SIZE flags * (the FILE_NOTIFY_CHANGE_SIZE is only
sent it the file wasn’t empty) / / Set the file position to zero
/ FilePosition.CurrentByteOffset.QuadPart = 0; Status =
FltSetInformationFile(FltObjects->Instance,
FltObjects->FileObject, &FilePosition,
sizeof(FILE_POSITION_INFORMATION),
FilePositionInformation); if (!NT_SUCCESS(Status)) {
TRACE_ERROR(TraceHandle, “Failed to set the file position to zero : 0x%X”,
Status); return Status; } /* Set the end of file to zero */
EndOfFile.EndOfFile.QuadPart = 0; Status =
FltSetInformationFile(FltObjects->Instance,
FltObjects->FileObject, &EndOfFile,
sizeof(FILE_END_OF_FILE_INFORMATION),
FileEndOfFileInformation); if (!NT_SUCCESS(Status)) {
TRACE_ERROR(TraceHandle, “Failed to update the EOF : 0x%X”, Status);
return Status; }}
—
NTFSD is sponsored by OSR
OSR is hiring!! Info at http://www.osr.com/careers
For our schedule of debugging and file system seminars visit:
http://www.osr.com/seminars
To unsubscribe, visit the List Server section of OSR Online at
http://www.osronline.com/page.cfm?name=ListServer