- Implement NtfsGrabFCBFromTableById() and NtfsGetFCBForFileById(). These two are responsible for opening and retrieving a file open by ID.
- Modified NtfsMakeFCBFromDirEntry() so that it supports openings by ID which come with less information than normal openings.
- Modified NtfsGrabFCBFromTable() so that it doesn't return a FCB which would have been opened by ID.
- Modified NtfsOpenFile() so that it allows opening a file by ID using the two FCB helpers functions defined upper.
- Modified NtfsCreateFile() so that it can validate input in case of opening by ID.

To make it short, all this implements file opening by ID in NTFS driver. I made the choice to separate FCB which are coming from "normal" opening and these from ID opening.
The reason is that a file opening with ID has less information than a normal opening, and may fail on these information retreival. This is due to the fact that if opening by ID can virtual open all the files, because it ignores authorizations, traverses checks, in the end for retrieving the information, such checks can be done and fail.

I also left all this disabled so far, because it appears to regress NFI. I will investigate this.

CORE-8725

svn path=/trunk/; revision=65652
This commit is contained in:
Pierre Schweitzer 2014-12-14 21:18:47 +00:00
parent 6cea3c4018
commit 5a3af281d7
3 changed files with 165 additions and 44 deletions

View file

@ -80,6 +80,7 @@ NTSTATUS
NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
PFILE_OBJECT FileObject,
PWSTR FileName,
BOOLEAN OpenById,
PNTFS_FCB * FoundFCB)
{
PNTFS_FCB ParentFcb;
@ -87,55 +88,81 @@ NtfsOpenFile(PDEVICE_EXTENSION DeviceExt,
NTSTATUS Status;
PWSTR AbsFileName = NULL;
DPRINT1("NtfsOpenFile(%p, %p, %S, %p)\n", DeviceExt, FileObject, FileName, FoundFCB);
DPRINT1("NtfsOpenFile(%p, %p, %S, %u, %p)\n", DeviceExt, FileObject, (!OpenById ? FileName : NULL), OpenById, FoundFCB);
*FoundFCB = NULL;
if (FileObject->RelatedFileObject)
if (OpenById)
{
DPRINT("Converting relative filename to absolute filename\n");
ULONGLONG Id = (*(PULONGLONG)FileName) & NTFS_MFT_MASK;
Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
FileName,
&AbsFileName);
FileName = AbsFileName;
if (!NT_SUCCESS(Status))
DPRINT1("Will attempt to open by id: %I64x\n", Id);
Fcb = NtfsGrabFCBFromTableById(DeviceExt,
Id);
if (Fcb == NULL)
{
return Status;
}
Status = NtfsGetFCBForFileById(DeviceExt,
&Fcb,
Id);
if (!NT_SUCCESS (Status))
{
DPRINT("Could not make a new FCB, status: %x\n", Status);
return STATUS_UNSUCCESSFUL;
return Status;
}
Fcb->Flags |= FCB_IS_OPEN_BY_ID;
}
}
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
DPRINT("PathName to open: %S\n", FileName);
/* try first to find an existing FCB in memory */
DPRINT("Checking for existing FCB in memory\n");
Fcb = NtfsGrabFCBFromTable(DeviceExt,
FileName);
if (Fcb == NULL)
else
{
DPRINT("No existing FCB found, making a new one if file exists.\n");
Status = NtfsGetFCBForFile(DeviceExt,
&ParentFcb,
&Fcb,
FileName);
if (ParentFcb != NULL)
if (FileObject->RelatedFileObject)
{
NtfsReleaseFCB(DeviceExt,
ParentFcb);
DPRINT("Converting relative filename to absolute filename\n");
Status = NtfsMakeAbsoluteFilename(FileObject->RelatedFileObject,
FileName,
&AbsFileName);
FileName = AbsFileName;
if (!NT_SUCCESS(Status))
{
return Status;
}
return STATUS_UNSUCCESSFUL;
}
if (!NT_SUCCESS (Status))
//FIXME: Get cannonical path name (remove .'s, ..'s and extra separators)
DPRINT("PathName to open: %S\n", FileName);
/* try first to find an existing FCB in memory */
DPRINT("Checking for existing FCB in memory\n");
Fcb = NtfsGrabFCBFromTable(DeviceExt,
FileName);
if (Fcb == NULL)
{
DPRINT("Could not make a new FCB, status: %x\n", Status);
DPRINT("No existing FCB found, making a new one if file exists.\n");
Status = NtfsGetFCBForFile(DeviceExt,
&ParentFcb,
&Fcb,
FileName);
if (ParentFcb != NULL)
{
NtfsReleaseFCB(DeviceExt,
ParentFcb);
}
if (AbsFileName)
ExFreePool(AbsFileName);
if (!NT_SUCCESS (Status))
{
DPRINT("Could not make a new FCB, status: %x\n", Status);
return Status;
if (AbsFileName)
ExFreePool(AbsFileName);
return Status;
}
}
}
@ -201,6 +228,12 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
return STATUS_ACCESS_DENIED;
}
if ((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID &&
FileObject->FileName.Length != sizeof(ULONGLONG))
{
return STATUS_INVALID_PARAMETER;
}
/* This a open operation for the volume itself */
if (FileObject->FileName.Length == 0 &&
(FileObject->RelatedFileObject == NULL || FileObject->RelatedFileObject->FsContext2 != NULL))
@ -226,6 +259,7 @@ NtfsCreateFile(PDEVICE_OBJECT DeviceObject,
Status = NtfsOpenFile(DeviceExt,
FileObject,
FileObject->FileName.Buffer,
((RequestedOptions & FILE_OPEN_BY_FILE_ID) == FILE_OPEN_BY_FILE_ID),
&Fcb);
if (NT_SUCCESS(Status))

View file

@ -220,7 +220,8 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
DPRINT("Comparing '%S' and '%S'\n", FileName, Fcb->PathName);
if (_wcsicmp(FileName, Fcb->PathName) == 0)
if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) != FCB_IS_OPEN_BY_ID &&
_wcsicmp(FileName, Fcb->PathName) == 0)
{
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
@ -238,6 +239,38 @@ NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
}
PNTFS_FCB
NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
ULONGLONG Id)
{
KIRQL oldIrql;
PNTFS_FCB Fcb;
PLIST_ENTRY current_entry;
KeAcquireSpinLock(&Vcb->FcbListLock, &oldIrql);
current_entry = Vcb->FcbListHead.Flink;
while (current_entry != &Vcb->FcbListHead)
{
Fcb = CONTAINING_RECORD(current_entry, NTFS_FCB, FcbListEntry);
if ((Fcb->Flags & FCB_IS_OPEN_BY_ID) == FCB_IS_OPEN_BY_ID &&
Fcb->MFTIndex == Id)
{
Fcb->RefCount++;
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
return Fcb;
}
current_entry = current_entry->Flink;
}
KeReleaseSpinLock(&Vcb->FcbListLock, oldIrql);
return NULL;
}
NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb)
@ -410,18 +443,26 @@ NtfsMakeFCBFromDirEntry(PNTFS_VCB Vcb,
return STATUS_OBJECT_NAME_NOT_FOUND; // Not sure that's the best here
}
if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
if (DirectoryFCB && Name)
{
return STATUS_OBJECT_NAME_INVALID;
}
if (Name->Buffer[0] != 0 && wcslen(DirectoryFCB->PathName) +
sizeof(WCHAR) + Name->Length / sizeof(WCHAR) > MAX_PATH)
{
return STATUS_OBJECT_NAME_INVALID;
}
wcscpy(pathName, DirectoryFCB->PathName);
if (!NtfsFCBIsRoot(DirectoryFCB))
{
wcscat(pathName, L"\\");
wcscpy(pathName, DirectoryFCB->PathName);
if (!NtfsFCBIsRoot(DirectoryFCB))
{
wcscat(pathName, L"\\");
}
wcscat(pathName, Name->Buffer);
}
else
{
RtlCopyMemory(pathName, FileName->Name, FileName->NameLength * sizeof (WCHAR));
pathName[FileName->NameLength] = UNICODE_NULL;
}
wcscat(pathName, Name->Buffer);
rcFCB = NtfsCreateFCB(pathName, Vcb);
if (!rcFCB)
@ -654,6 +695,42 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
}
NTSTATUS
NtfsGetFCBForFileById(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB,
ULONGLONG Id)
{
NTSTATUS Status;
PFILE_RECORD_HEADER FileRecord;
FileRecord = ExAllocatePoolWithTag(NonPagedPool,
Vcb->NtfsInfo.BytesPerFileRecord,
TAG_NTFS);
if (FileRecord == NULL)
{
return STATUS_INSUFFICIENT_RESOURCES;
}
Status = ReadFileRecord(Vcb, Id, FileRecord);
if (!NT_SUCCESS(Status))
{
ExFreePoolWithTag(FileRecord, TAG_NTFS);
return Status;
}
if ((FileRecord->Flags & FRH_IN_USE) != FRH_IN_USE)
{
ExFreePoolWithTag(FileRecord, TAG_NTFS);
return STATUS_INVALID_PARAMETER;
}
Status = NtfsMakeFCBFromDirEntry(Vcb, NULL, NULL, FileRecord, Id, pFCB);
ExFreePoolWithTag(FileRecord, TAG_NTFS);
return Status;
}
NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb,
PNTFS_FCB pFCB,

View file

@ -416,6 +416,7 @@ typedef struct _NTFS_ATTR_CONTEXT
#define FCB_CACHE_INITIALIZED 0x0001
#define FCB_IS_VOLUME_STREAM 0x0002
#define FCB_IS_VOLUME 0x0004
#define FCB_IS_OPEN_BY_ID 0x0008
#define MAX_PATH 260
typedef struct _FCB
@ -599,6 +600,10 @@ PNTFS_FCB
NtfsGrabFCBFromTable(PNTFS_VCB Vcb,
PCWSTR FileName);
PNTFS_FCB
NtfsGrabFCBFromTableById(PNTFS_VCB Vcb,
ULONGLONG Id);
NTSTATUS
NtfsFCBInitializeCache(PNTFS_VCB Vcb,
PNTFS_FCB Fcb);
@ -620,6 +625,11 @@ NtfsGetFCBForFile(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB,
const PWSTR pFileName);
NTSTATUS
NtfsGetFCBForFileById(PNTFS_VCB Vcb,
PNTFS_FCB *pFCB,
ULONGLONG Id);
NTSTATUS
NtfsReadFCBAttribute(PNTFS_VCB Vcb,
PNTFS_FCB pFCB,