Skip to content

Commit a311abb

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

File tree

1 file changed

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

1 file changed

+107
-20
lines changed

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

Lines changed: 107 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,106 @@ 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+
ULONGLONG PrevMftIndex = -1;
396+
PNTFS_MFT_RECORD MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
397+
if (!MftRecord)
398+
return NULL;
399+
400+
while (AttrListRecord < AttrListRecordEnd)
401+
{
402+
ULONGLONG MftIndex = AttrListRecord->BaseFileRef & 0xFFFFFFFFFFFF;
403+
ULONG AttrType = AttrListRecord->Type;
404+
405+
if (AttrType == NTFS_ATTR_TYPE_END)
406+
break;
407+
408+
TRACE("Recursion = %u, AttrListRecord->Type = 0x%x\n", Recursion, AttrType);
409+
410+
if (AttrType == Type &&
411+
AttrListRecord->NameLength == NameLength)
412+
{
413+
PWCHAR AttrListName;
414+
415+
AttrListName = (PWCHAR)((PCHAR)AttrListRecord + AttrListRecord->NameOffset);
416+
if (RtlEqualMemory(AttrListName, Name, NameLength << 1))
417+
{
418+
PNTFS_ATTR_CONTEXT Context;
419+
PNTFS_ATTR_RECORD AttrRecord;
420+
PNTFS_ATTR_RECORD AttrRecordEnd;
421+
422+
if (PrevMftIndex != MftIndex)
423+
{
424+
PrevMftIndex = MftIndex;
425+
if (!NtfsReadMftRecord(Volume, MftIndex, MftRecord))
426+
goto skip;
427+
}
428+
429+
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
430+
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
431+
432+
Context = NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, NTFS_MAX_ATTRIBUTE_LIST_RECURSION);
433+
if (Context)
434+
{
435+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
436+
return Context;
437+
}
438+
}
439+
}
440+
441+
skip:
442+
if (AttrListRecord->RecLength == 0)
443+
break;
444+
AttrListRecord = (PNTFS_ATTR_LIST_ATTR)((PCHAR)AttrListRecord + AttrListRecord->RecLength);
445+
}
446+
447+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
448+
return NULL;
449+
}
450+
451+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(
452+
PNTFS_VOLUME_INFO Volume,
453+
PNTFS_ATTR_RECORD AttrRecord,
454+
PNTFS_ATTR_RECORD AttrRecordEnd,
455+
ULONG Type,
456+
const WCHAR *Name,
457+
ULONG NameLength,
458+
ULONG Recursion)
375459
{
376460
while (AttrRecord < AttrRecordEnd)
377461
{
378462
if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
379463
break;
380464

381-
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
465+
TRACE("Recursion = %u, AttrRecord->Type = 0x%x\n", Recursion, AttrRecord->Type);
466+
467+
/* Limit the $ATTRIBUTE_LIST recursion or else infinity loop */
468+
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < NTFS_MAX_ATTRIBUTE_LIST_RECURSION)
382469
{
383470
PNTFS_ATTR_CONTEXT Context;
384471
PNTFS_ATTR_CONTEXT ListContext;
385472
PVOID ListBuffer;
386473
ULONGLONG ListSize;
387-
PNTFS_ATTR_RECORD ListAttrRecord;
388-
PNTFS_ATTR_RECORD ListAttrRecordEnd;
474+
PNTFS_ATTR_LIST_ATTR ListAttrRecord;
475+
PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
389476

390477
ListContext = NtfsPrepareAttributeContext(AttrRecord);
391478

@@ -401,13 +488,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401488
continue;
402489
}
403490

404-
ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
405-
ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
491+
ListAttrRecord = (PNTFS_ATTR_LIST_ATTR)ListBuffer;
492+
ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR)((PCHAR)ListBuffer + ListSize);
406493

407494
if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
408495
{
409-
Context = NtfsFindAttributeHelper(Volume, ListAttrRecord, ListAttrRecordEnd,
410-
Type, Name, NameLength);
496+
Context = NtfsFindAttributeHelperList(Volume, ListAttrRecord, ListAttrRecordEnd,
497+
Type, Name, NameLength, Recursion + 1);
411498

412499
NtfsReleaseAttributeContext(ListContext);
413500
FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
@@ -417,23 +504,22 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
417504
}
418505
}
419506

420-
if (AttrRecord->Type == Type)
507+
if (AttrRecord->Type == Type &&
508+
AttrRecord->NameLength == NameLength &&
509+
NtfsGetAttributeSize(AttrRecord) != 0)
421510
{
422-
if (AttrRecord->NameLength == NameLength)
423-
{
424-
PWCHAR AttrName;
511+
PWCHAR AttrName;
425512

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-
}
513+
AttrName = (PWCHAR)((PCHAR)AttrRecord + AttrRecord->NameOffset);
514+
if (RtlEqualMemory(AttrName, Name, NameLength << 1))
515+
{
516+
/* Found it, fill up the context and return. */
517+
return NtfsPrepareAttributeContext(AttrRecord);
432518
}
433519
}
434520

435521
if (AttrRecord->Length == 0)
436-
return NULL;
522+
break;
437523
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
438524
}
439525

@@ -451,7 +537,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
451537
for (NameLength = 0; Name[NameLength] != 0; NameLength++)
452538
;
453539

454-
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength);
540+
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, 0);
455541
}
456542

457543
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
@@ -519,6 +605,7 @@ static BOOLEAN NtfsCompareFileName(PCHAR FileName, PNTFS_INDEX_ENTRY IndexEntry)
519605
EntryFileNameLength = IndexEntry->FileName.FileNameLength;
520606

521607
#if DBG
608+
TRACE("%s ", FileName);
522609
NtfsPrintFile(IndexEntry);
523610
#endif
524611

0 commit comments

Comments
 (0)