Skip to content

Commit d03a5f0

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

File tree

1 file changed

+93
-12
lines changed
  • boot/freeldr/freeldr/lib/fs

1 file changed

+93
-12
lines changed

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

Lines changed: 93 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -371,21 +371,100 @@ static ULONG NtfsReadAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_CONTEXT Cont
371371
return AlreadyRead;
372372
}
373373

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

381-
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
457+
TRACE("Recursion = %u, AttrRecord->Type = 0x%x\n", Recursion, AttrRecord->Type);
458+
459+
/* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
460+
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < 8)
382461
{
383462
PNTFS_ATTR_CONTEXT Context;
384463
PNTFS_ATTR_CONTEXT ListContext;
385464
PVOID ListBuffer;
386465
ULONGLONG ListSize;
387-
PNTFS_ATTR_RECORD ListAttrRecord;
388-
PNTFS_ATTR_RECORD ListAttrRecordEnd;
466+
PNTFS_ATTR_LIST_ATTR ListAttrRecord;
467+
PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
389468

390469
ListContext = NtfsPrepareAttributeContext(AttrRecord);
391470

@@ -401,13 +480,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401480
continue;
402481
}
403482

404-
ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
405-
ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
483+
ListAttrRecord = (PNTFS_ATTR_LIST_ATTR)ListBuffer;
484+
ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR)((PCHAR)ListBuffer + ListSize);
406485

407486
if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
408487
{
409-
Context = NtfsFindAttributeHelper(Volume, ListAttrRecord, ListAttrRecordEnd,
410-
Type, Name, NameLength);
488+
Context = NtfsFindAttributeHelperList(Volume, ListAttrRecord, ListAttrRecordEnd,
489+
Type, Name, NameLength, Recursion + 1);
411490

412491
NtfsReleaseAttributeContext(ListContext);
413492
FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
@@ -419,7 +498,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
419498

420499
if (AttrRecord->Type == Type)
421500
{
422-
if (AttrRecord->NameLength == NameLength)
501+
if (AttrRecord->NameLength == NameLength && NtfsGetAttributeSize(AttrRecord) != 0)
423502
{
424503
PWCHAR AttrName;
425504

@@ -433,7 +512,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
433512
}
434513

435514
if (AttrRecord->Length == 0)
436-
return NULL;
515+
break;
437516
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
438517
}
439518

@@ -447,11 +526,11 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
447526
ULONG NameLength;
448527

449528
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
450-
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
529+
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->BytesInUse);
451530
for (NameLength = 0; Name[NameLength] != 0; NameLength++)
452531
;
453532

454-
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength);
533+
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, 0);
455534
}
456535

457536
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
@@ -592,6 +671,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
592671
while (IndexEntry < IndexEntryEnd &&
593672
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
594673
{
674+
TRACE("%s ", FileName);
595675
if (NtfsCompareFileName(FileName, IndexEntry))
596676
{
597677
*OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
@@ -675,6 +755,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
675755
while (IndexEntry < IndexEntryEnd &&
676756
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
677757
{
758+
TRACE("%s ", FileName);
678759
if (NtfsCompareFileName(FileName, IndexEntry))
679760
{
680761
TRACE("File found\n");

0 commit comments

Comments
 (0)