2

Using the NT native function NtCreateFile it's possible to open a file by id using the FILE_OPEN_BY_FILE_ID create option. However, in doing so the DELETE access flag appears to be ignored. If I set it the file will open fine but any attempt to delete or rename the file will fail (e.g. by settings FILE_DELETE_ON_CLOSE or using the FILE_RENAME_INFORMATION class with NtSetInformationFile).

Is it impossible to delete a file opened this way? Is there some other way to delete a file by id instead of name?

ChrisD
  • 3,378
  • 3
  • 35
  • 40
  • hmm.. i just test myself - really file not deleted and `STATUS_INVALID_PARAMETER` on `FileRenameInformation` - so i mistake from begin. now look for this in more details. – RbMm Oct 13 '19 at 14:28
  • yes, i completely mistake. ntfs really not allow raname or delete file which opened by id – RbMm Oct 13 '19 at 14:38
  • 1
    i think you can ask this question here - https://community.osr.com/categories/ntfsd - the best forum for such topic – RbMm Oct 13 '19 at 14:59

2 Answers2

3

In addition to RbMm's answer, I found a blog post by Alex Carp, Some Limitations Using Files Opened By ID, that explains the rationale for this.

Unfortunately the semantics for files opened by ID are a bit different from the semantics of the same files if they would have been opened by name. The file name namespace for example allows multiple names for a file (hardlinks) while the ID namespace does not. The different semantics of the different namespaces can make it so that some operations don't make sense.

For example because NTFS allows multiple names for a file if the file is opened by ID and an operation that changes the namespace is attempted, which name should be affected? To make this very clear, if file \Foo\f.txt and file \Bar\b.txt are hardlinks to the same file and I open the file by ID and I try to rename it, which name should change? How about if I try a delete?

In short deleting a file in NTFS' model actually means removing a reference (aka a name) to a file. It's only once all references to it are deleted that, as a side effect, the file itself can be deleted. Much like reference counting in many programming languages.

There could hypothetically be an operation that takes a file ID and deletes all references as well as the file but this would be a very different operation and potentially tricky (e.g. it would need to perform permission checks on all affected file names, wait for all relevant handles to close, prevent new file names referencing the file being deleted, etc). So in that respect it's unsurprising that it doesn't exist.

Community
  • 1
  • 1
ChrisD
  • 3,378
  • 3
  • 35
  • 40
  • 1
    Permission for removing all links shouldn't be an issue. If the handle has delete access, this must have been granted by the security descriptor on the file and not from delete-child access on a particular link's parent directory. Also, there's a single set of file attributes with regard to the readonly attribute. OTOH, the share mode isn't common, so handling that would have to be all or nothing. If, due to existing opens, the share mode on any of the links doesn't share delete access, the operation has to fail as a sharing violation. – Eryk Sun May 16 '20 at 12:36
2

i look for ntfs-4 source code and view say next code in NtfsSetRenameInfo

//
//  Do a quick check that the caller is allowed to do the rename.
//  The opener must have opened the main data stream by name and this can't be
//  a system file.
//

if (!FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE ) ||
    (Lcb == NULL) ||
    (NtfsSegmentNumber( &Fcb->FileReference ) < FIRST_USER_FILE_NUMBER)) {

    DebugTrace( -1, Dbg, ("NtfsSetRenameInfo:  Exit -> %08lx\n", STATUS_INVALID_PARAMETER) );
    return STATUS_INVALID_PARAMETER;
}

the same situation for FileDispositionInformation and FILE_DELETE_ON_CLOSE option (1)

    if (FlagOn( Ccb->Flags, CCB_FLAG_DELETE_ON_CLOSE )) {

        if (FlagOn( Ccb->Flags, CCB_FLAG_OPEN_AS_FILE )) {

so ntfs by some reason not allow rename or delete file if CCB_FLAG_OPEN_AS_FILE not set on file. (it not set when file opened by id)

RbMm
  • 31,280
  • 3
  • 35
  • 56