Skip to content

Commit 1f0329e

Browse files
committed
[FREELDR] Fix AttributeList parsing on NTFS driver
1 parent 6dd0406 commit 1f0329e

File tree

1 file changed

+103
-20
lines changed
  • boot/freeldr/freeldr/lib/fs

1 file changed

+103
-20
lines changed

boot/freeldr/freeldr/lib/fs/ntfs.c

Lines changed: 103 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ DBG_DEFAULT_CHANNEL(FILESYSTEM);
3939
#define TAG_NTFS_VOLUME 'VftN'
4040
#define TAG_NTFS_DATA 'DftN'
4141

42+
#define NTFS_MAX_ATTRIBUTE_LIST_RECURSION 8
43+
4244
typedef struct _NTFS_VOLUME_INFO
4345
{
4446
NTFS_BOOTSECTOR BootSector;
@@ -371,21 +373,101 @@ static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Cont
371373
return AlreadyRead;
372374
}
373375

374-
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength)
376+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(
377+
PNTFS_VOLUME_INFO Volume,
378+
PNTFS_ATTR_RECORD AttrRecord,
379+
PNTFS_ATTR_RECORD AttrRecordEnd,
380+
ULONG Type,
381+
const WCHAR *Name,
382+
ULONG NameLength,
383+
ULONG Recursion);
384+
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer);
385+
386+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelperList(
387+
PNTFS_VOLUME_INFO Volume,
388+
PNTFS_ATTR_LIST_ATTR AttrListRecord,
389+
PNTFS_ATTR_LIST_ATTR AttrListRecordEnd,
390+
ULONG Type,
391+
const WCHAR *Name,
392+
ULONG NameLength,
393+
ULONG Recursion)
394+
{
395+
PNTFS_MFT_RECORD MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
396+
if (!MftRecord)
397+
return NULL;
398+
399+
while (AttrListRecord < AttrListRecordEnd)
400+
{
401+
ULONGLONG MftIndex = AttrListRecord->BaseFileRef & 0xFFFFFFFFFFFF;
402+
ULONG AttrType = AttrListRecord->Type;
403+
404+
if (AttrType == NTFS_ATTR_TYPE_END)
405+
break;
406+
407+
TRACE("Recursion = %u, AttrListRecord->Type = 0x%x\n", Recursion, AttrType);
408+
409+
if (AttrType == Type &&
410+
AttrListRecord->NameLength == NameLength)
411+
{
412+
PWCHAR AttrListName;
413+
414+
AttrListName = (PWCHAR)((PCHAR)AttrListRecord + AttrListRecord->NameOffset);
415+
if (RtlEqualMemory(AttrListName, Name, NameLength << 1))
416+
{
417+
PNTFS_ATTR_CONTEXT Context;
418+
PNTFS_ATTR_RECORD AttrRecord;
419+
PNTFS_ATTR_RECORD AttrRecordEnd;
420+
421+
if (!NtfsReadMftRecord(Volume, MftIndex, MftRecord))
422+
goto skip;
423+
424+
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
425+
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
426+
427+
Context = NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, NTFS_MAX_ATTRIBUTE_LIST_RECURSION);
428+
if (Context)
429+
{
430+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
431+
return Context;
432+
}
433+
}
434+
}
435+
436+
skip:
437+
if (AttrListRecord->RecLength == 0)
438+
break;
439+
AttrListRecord = (PNTFS_ATTR_LIST_ATTR)((PCHAR)AttrListRecord + AttrListRecord->RecLength);
440+
}
441+
442+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
443+
return NULL;
444+
}
445+
446+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(
447+
PNTFS_VOLUME_INFO Volume,
448+
PNTFS_ATTR_RECORD AttrRecord,
449+
PNTFS_ATTR_RECORD AttrRecordEnd,
450+
ULONG Type,
451+
const WCHAR *Name,
452+
ULONG NameLength,
453+
ULONG Recursion)
375454
{
376455
while (AttrRecord < AttrRecordEnd)
377456
{
378457
if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
379458
break;
380459

381-
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
460+
TRACE("Recursion = %u, AttrRecord->Type = 0x%x\n", Recursion, AttrRecord->Type);
461+
462+
/* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
463+
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < NTFS_MAX_ATTRIBUTE_LIST_RECURSION)
382464
{
383465
PNTFS_ATTR_CONTEXT Context;
384466
PNTFS_ATTR_CONTEXT ListContext;
385467
PVOID ListBuffer;
386468
ULONGLONG ListSize;
387-
PNTFS_ATTR_RECORD ListAttrRecord;
388-
PNTFS_ATTR_RECORD ListAttrRecordEnd;
469+
PNTFS_ATTR_LIST_ATTR ListAttrRecord;
470+
PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
389471

390472
ListContext = NtfsPrepareAttributeContext(AttrRecord);
391473

@@ -401,13 +483,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401483
continue;
402484
}
403485

404-
ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
405-
ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
486+
ListAttrRecord = (PNTFS_ATTR_LIST_ATTR)ListBuffer;
487+
ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR)((PCHAR)ListBuffer + ListSize);
406488

407489
if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
408490
{
409-
Context = NtfsFindAttributeHelper(Volume, ListAttrRecord, ListAttrRecordEnd,
410-
Type, Name, NameLength);
491+
Context = NtfsFindAttributeHelperList(Volume, ListAttrRecord, ListAttrRecordEnd,
492+
Type, Name, NameLength, Recursion + 1);
411493

412494
NtfsReleaseAttributeContext(ListContext);
413495
FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
@@ -417,23 +499,22 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
417499
}
418500
}
419501

420-
if (AttrRecord->Type == Type)
502+
if (AttrRecord->Type == Type &&
503+
AttrRecord->NameLength == NameLength &&
504+
NtfsGetAttributeSize(AttrRecord) != 0)
421505
{
422-
if (AttrRecord->NameLength == NameLength)
423-
{
424-
PWCHAR AttrName;
506+
PWCHAR AttrName;
425507

426-
AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
427-
if (RtlEqualMemory(AttrName, Name, NameLength << 1))
428-
{
429-
/* Found it, fill up the context and return. */
430-
return NtfsPrepareAttributeContext(AttrRecord);
431-
}
508+
AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
509+
if (RtlEqualMemory(AttrName, Name, NameLength << 1))
510+
{
511+
/* Found it, fill up the context and return. */
512+
return NtfsPrepareAttributeContext(AttrRecord);
432513
}
433514
}
434515

435516
if (AttrRecord->Length == 0)
436-
return NULL;
517+
break;
437518
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
438519
}
439520

@@ -451,7 +532,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
451532
for (NameLength = 0; Name[NameLength] != 0; NameLength++)
452533
;
453534

454-
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength);
535+
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, 0);
455536
}
456537

457538
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
@@ -592,6 +673,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
592673
while (IndexEntry < IndexEntryEnd &&
593674
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
594675
{
676+
TRACE("%s ", FileName);
595677
if (NtfsCompareFileName(FileName, IndexEntry))
596678
{
597679
*OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
@@ -675,6 +757,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
675757
while (IndexEntry < IndexEntryEnd &&
676758
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
677759
{
760+
TRACE("%s ", FileName);
678761
if (NtfsCompareFileName(FileName, IndexEntry))
679762
{
680763
TRACE("File found\n");

0 commit comments

Comments
 (0)