https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4d3df0da50b99f8f86844…
commit 4d3df0da50b99f8f868449d262b88ffe2ac1d789
Author: Sylvain Deverre <deverre.sylv(a)gmail.com>
AuthorDate: Thu Aug 8 22:09:13 2019 +0200
Commit: Colin Finck <colin(a)reactos.org>
CommitDate: Fri Aug 16 11:08:29 2019 +0200
[NTFS] Correctly find attributes stored in another file record in MFT (and referenced
in data stream)
---
drivers/filesystems/ntfs/attrib.c | 93 ++++++++++++++++++++++++++++-----------
drivers/filesystems/ntfs/mft.c | 56 +++++++++++++++++++++++
drivers/filesystems/ntfs/ntfs.h | 25 ++++++++++-
3 files changed, 147 insertions(+), 27 deletions(-)
diff --git a/drivers/filesystems/ntfs/attrib.c b/drivers/filesystems/ntfs/attrib.c
index 1a04b763a2a..006465ce975 100644
--- a/drivers/filesystems/ntfs/attrib.c
+++ b/drivers/filesystems/ntfs/attrib.c
@@ -1258,7 +1258,74 @@ InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context)
}
ReleaseAttributeContext(ListContext);
- Context->NonResidentEnd = (PNTFS_ATTR_RECORD)((PCHAR)Context->NonResidentStart
+ ListSize);
+ Context->NonResidentEnd =
(PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentStart + ListSize);
+ return STATUS_SUCCESS;
+}
+
+static
+PNTFS_ATTRIBUTE_LIST_ITEM
+InternalGetNextAttributeListItem(PFIND_ATTR_CONTXT Context)
+{
+ PNTFS_ATTRIBUTE_LIST_ITEM NextItem;
+
+ if (Context->NonResidentCur == (PVOID)-1)
+ {
+ return NULL;
+ }
+
+ if (Context->NonResidentCur == NULL || Context->NonResidentCur->Type ==
AttributeEnd)
+ {
+ Context->NonResidentCur = (PVOID)-1;
+ return NULL;
+ }
+
+ if (Context->NonResidentCur->Length == 0)
+ {
+ DPRINT1("Broken length list entry length !");
+ Context->NonResidentCur = (PVOID)-1;
+ return NULL;
+ }
+
+ NextItem = (PNTFS_ATTRIBUTE_LIST_ITEM)((PCHAR)Context->NonResidentCur +
Context->NonResidentCur->Length);
+ if (NextItem->Length == 0 || NextItem->Type == AttributeEnd)
+ {
+ Context->NonResidentCur = (PVOID)-1;
+ return NULL;
+ }
+
+ if (NextItem < Context->NonResidentStart || NextItem >
Context->NonResidentEnd)
+ {
+ Context->NonResidentCur = (PVOID)-1;
+ return NULL;
+ }
+
+ Context->NonResidentCur = NextItem;
+ return NextItem;
+}
+
+NTSTATUS
+FindFirstAttributeListItem(PFIND_ATTR_CONTXT Context,
+ PNTFS_ATTRIBUTE_LIST_ITEM *Item)
+{
+ if (Context->NonResidentStart == NULL || Context->NonResidentStart->Type ==
AttributeEnd)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ Context->NonResidentCur = Context->NonResidentStart;
+ *Item = Context->NonResidentCur;
+ return STATUS_SUCCESS;
+}
+
+NTSTATUS
+FindNextAttributeListItem(PFIND_ATTR_CONTXT Context,
+ PNTFS_ATTRIBUTE_LIST_ITEM *Item)
+{
+ *Item = InternalGetNextAttributeListItem(Context);
+ if (*Item == NULL)
+ {
+ return STATUS_UNSUCCESSFUL;
+ }
return STATUS_SUCCESS;
}
@@ -1308,30 +1375,6 @@ InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
return NULL;
}
- if (Context->CurrAttr < Context->NonResidentStart ||
- Context->CurrAttr >= Context->NonResidentEnd)
- {
- Context->CurrAttr = Context->NonResidentStart;
- }
- else if (Context->CurrAttr->Length != 0)
- {
- NextAttribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr +
Context->CurrAttr->Length);
- Context->Offset += ((ULONG_PTR)NextAttribute -
(ULONG_PTR)Context->CurrAttr);
- Context->CurrAttr = NextAttribute;
- }
- else
- {
- DPRINT1("Broken length!\n");
- Context->CurrAttr = (PVOID)-1;
- return NULL;
- }
-
- if (Context->CurrAttr < Context->NonResidentEnd &&
- Context->CurrAttr->Type != AttributeEnd)
- {
- return Context->CurrAttr;
- }
-
Context->CurrAttr = (PVOID)-1;
return NULL;
}
diff --git a/drivers/filesystems/ntfs/mft.c b/drivers/filesystems/ntfs/mft.c
index f03074cdfda..e1411f0ac96 100644
--- a/drivers/filesystems/ntfs/mft.c
+++ b/drivers/filesystems/ntfs/mft.c
@@ -140,6 +140,7 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
NTSTATUS Status;
FIND_ATTR_CONTXT Context;
PNTFS_ATTR_RECORD Attribute;
+ PNTFS_ATTRIBUTE_LIST_ITEM AttrListItem;
DPRINT("FindAttribute(%p, %p, 0x%x, %S, %lu, %p, %p)\n", Vcb, MftRecord,
Type, Name, NameLength, AttrCtx, Offset);
@@ -184,6 +185,61 @@ FindAttribute(PDEVICE_EXTENSION Vcb,
Status = FindNextAttribute(&Context, &Attribute);
}
+ /* No attribute found, check if it is referenced in another file record */
+ Status = FindFirstAttributeListItem(&Context, &AttrListItem);
+ while (NT_SUCCESS(Status))
+ {
+ if (AttrListItem->Type == Type && AttrListItem->NameLength ==
NameLength)
+ {
+ if (NameLength != 0)
+ {
+ PWCHAR AttrName;
+
+ AttrName = (PWCHAR)((PCHAR)AttrListItem + AttrListItem->NameOffset);
+ DPRINT("%.*S, %.*S\n", AttrListItem->NameLength, AttrName,
NameLength, Name);
+ if (RtlCompareMemory(AttrName, Name, NameLength * sizeof(WCHAR)) ==
(NameLength * sizeof(WCHAR)))
+ {
+ Found = TRUE;
+ }
+ }
+ else
+ {
+ Found = TRUE;
+ }
+
+ if (Found == TRUE)
+ {
+ /* Get the MFT Index of attribute */
+ ULONGLONG MftIndex;
+ PFILE_RECORD_HEADER RemoteHdr;
+
+ MftIndex = AttrListItem->MFTIndex & NTFS_MFT_MASK;
+ RemoteHdr =
ExAllocateFromNPagedLookasideList(&Vcb->FileRecLookasideList);
+
+ if (RemoteHdr == NULL)
+ {
+ FindCloseAttribute(&Context);
+ return STATUS_INSUFFICIENT_RESOURCES;
+ }
+
+ /* Check we are not reading ourselves */
+ if (MftRecord->MFTRecordNumber == MftIndex)
+ {
+ DPRINT1("Attribute list references missing attribute to this
file entry !");
+ ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList,
RemoteHdr);
+ FindCloseAttribute(&Context);
+ return STATUS_OBJECT_NAME_NOT_FOUND;
+ }
+ /* Read the new file record */
+ ReadFileRecord(Vcb, MftIndex, RemoteHdr);
+ Status = FindAttribute(Vcb, RemoteHdr, Type, Name, NameLength, AttrCtx,
Offset);
+ ExFreeToNPagedLookasideList(&Vcb->FileRecLookasideList,
RemoteHdr);
+ FindCloseAttribute(&Context);
+ return Status;
+ }
+ }
+ Status = FindNextAttributeListItem(&Context, &AttrListItem);
+ }
FindCloseAttribute(&Context);
return STATUS_OBJECT_NAME_NOT_FOUND;
}
diff --git a/drivers/filesystems/ntfs/ntfs.h b/drivers/filesystems/ntfs/ntfs.h
index c50a077e1c1..aa85b810883 100644
--- a/drivers/filesystems/ntfs/ntfs.h
+++ b/drivers/filesystems/ntfs/ntfs.h
@@ -300,6 +300,17 @@ typedef struct
};
} NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD;
+typedef struct
+{
+ ULONG Type;
+ USHORT Length;
+ UCHAR NameLength;
+ UCHAR NameOffset;
+ ULONGLONG StartingVCN;
+ ULONGLONG MFTIndex;
+ USHORT Instance;
+} NTFS_ATTRIBUTE_LIST_ITEM, *PNTFS_ATTRIBUTE_LIST_ITEM;
+
// The beginning and length of an attribute record are always aligned to an 8-byte
boundary,
// relative to the beginning of the file record.
#define ATTR_RECORD_ALIGNMENT 8
@@ -486,6 +497,7 @@ typedef struct _NTFS_ATTR_CONTEXT
ULONGLONG CacheRunCurrentOffset;
LARGE_MCB DataRunsMCB;
ULONGLONG FileMFTIndex;
+ ULONGLONG FileOwnerMFTIndex; /* If attribute list attribute, reference the
original file */
PNTFS_ATTR_RECORD pRecord;
} NTFS_ATTR_CONTEXT, *PNTFS_ATTR_CONTEXT;
@@ -534,8 +546,9 @@ typedef struct _FIND_ATTR_CONTXT
PNTFS_ATTR_RECORD FirstAttr;
PNTFS_ATTR_RECORD CurrAttr;
PNTFS_ATTR_RECORD LastAttr;
- PNTFS_ATTR_RECORD NonResidentStart;
- PNTFS_ATTR_RECORD NonResidentEnd;
+ PNTFS_ATTRIBUTE_LIST_ITEM NonResidentStart;
+ PNTFS_ATTRIBUTE_LIST_ITEM NonResidentEnd;
+ PNTFS_ATTRIBUTE_LIST_ITEM NonResidentCur;
ULONG Offset;
} FIND_ATTR_CONTXT, *PFIND_ATTR_CONTXT;
@@ -659,6 +672,14 @@ PFILENAME_ATTRIBUTE
GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb,
PFILE_RECORD_HEADER FileRecord);
+NTSTATUS
+FindFirstAttributeListItem(PFIND_ATTR_CONTXT Context,
+ PNTFS_ATTRIBUTE_LIST_ITEM *Item);
+
+NTSTATUS
+FindNextAttributeListItem(PFIND_ATTR_CONTXT Context,
+ PNTFS_ATTRIBUTE_LIST_ITEM *Item);
+
NTSTATUS
FindFirstAttribute(PFIND_ATTR_CONTXT Context,
PDEVICE_EXTENSION Vcb,