Skip to content

Commit 30d9cbc

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

File tree

1 file changed

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

1 file changed

+101
-20
lines changed

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

Lines changed: 101 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -371,21 +371,101 @@ 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 &&
408+
AttrListRecord->NameLength == NameLength)
409+
{
410+
PWCHAR AttrListName;
411+
412+
AttrListName = (PWCHAR)((PCHAR)AttrListRecord + AttrListRecord->NameOffset);
413+
if (RtlEqualMemory(AttrListName, Name, NameLength << 1))
414+
{
415+
PNTFS_ATTR_CONTEXT Context;
416+
PNTFS_ATTR_RECORD AttrRecord;
417+
PNTFS_ATTR_RECORD AttrRecordEnd;
418+
419+
if (!NtfsReadMftRecord(Volume, MftIndex, MftRecord))
420+
goto skip;
421+
422+
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
423+
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
424+
425+
Context = NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, Recursion + 1);
426+
if (Context)
427+
{
428+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
429+
return Context;
430+
}
431+
}
432+
}
433+
434+
skip:
435+
if (AttrListRecord->RecLength == 0)
436+
break;
437+
AttrListRecord = (PNTFS_ATTR_LIST_ATTR)((PCHAR)AttrListRecord + AttrListRecord->RecLength);
438+
}
439+
440+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
441+
return NULL;
442+
}
443+
444+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(
445+
PNTFS_VOLUME_INFO Volume,
446+
PNTFS_ATTR_RECORD AttrRecord,
447+
PNTFS_ATTR_RECORD AttrRecordEnd,
448+
ULONG Type,
449+
const WCHAR *Name,
450+
ULONG NameLength,
451+
ULONG Recursion)
375452
{
376453
while (AttrRecord < AttrRecordEnd)
377454
{
378455
if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
379456
break;
380457

381-
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
458+
TRACE("Recursion = %u, AttrRecord->Type = 0x%x\n", Recursion, AttrRecord->Type);
459+
460+
/* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
461+
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < 8)
382462
{
383463
PNTFS_ATTR_CONTEXT Context;
384464
PNTFS_ATTR_CONTEXT ListContext;
385465
PVOID ListBuffer;
386466
ULONGLONG ListSize;
387-
PNTFS_ATTR_RECORD ListAttrRecord;
388-
PNTFS_ATTR_RECORD ListAttrRecordEnd;
467+
PNTFS_ATTR_LIST_ATTR ListAttrRecord;
468+
PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
389469

390470
ListContext = NtfsPrepareAttributeContext(AttrRecord);
391471

@@ -401,13 +481,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401481
continue;
402482
}
403483

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

407487
if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
408488
{
409-
Context = NtfsFindAttributeHelper(Volume, ListAttrRecord, ListAttrRecordEnd,
410-
Type, Name, NameLength);
489+
Context = NtfsFindAttributeHelperList(Volume, ListAttrRecord, ListAttrRecordEnd,
490+
Type, Name, NameLength, Recursion + 1);
411491

412492
NtfsReleaseAttributeContext(ListContext);
413493
FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
@@ -417,23 +497,22 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
417497
}
418498
}
419499

420-
if (AttrRecord->Type == Type)
500+
if (AttrRecord->Type == Type &&
501+
AttrRecord->NameLength == NameLength &&
502+
NtfsGetAttributeSize(AttrRecord) != 0)
421503
{
422-
if (AttrRecord->NameLength == NameLength)
423-
{
424-
PWCHAR AttrName;
504+
PWCHAR AttrName;
425505

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-
}
506+
AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
507+
if (RtlEqualMemory(AttrName, Name, NameLength << 1))
508+
{
509+
/* Found it, fill up the context and return. */
510+
return NtfsPrepareAttributeContext(AttrRecord);
432511
}
433512
}
434513

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

@@ -451,7 +530,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
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)