Skip to content

Commit 6960b17

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

File tree

1 file changed

+106
-48
lines changed
  • boot/freeldr/freeldr/lib/fs

1 file changed

+106
-48
lines changed

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

Lines changed: 106 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -371,21 +371,113 @@ 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 BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
375+
{
376+
USHORT *USA;
377+
USHORT USANumber;
378+
USHORT USACount;
379+
USHORT *Block;
380+
381+
USA = (USHORT*)((PCHAR)Record + Record->USAOffset);
382+
USANumber = *(USA++);
383+
USACount = Record->USACount - 1; /* Exclude the USA Number. */
384+
Block = (USHORT*)((PCHAR)Record + Volume->BootSector.BytesPerSector - 2);
385+
386+
while (USACount)
387+
{
388+
if (*Block != USANumber)
389+
return FALSE;
390+
*Block = *(USA++);
391+
Block = (USHORT*)((PCHAR)Block + Volume->BootSector.BytesPerSector);
392+
USACount--;
393+
}
394+
395+
return TRUE;
396+
}
397+
398+
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
399+
{
400+
ULONGLONG BytesRead;
401+
402+
BytesRead = NtfsReadAttribute(Volume, Volume->MFTContext, MFTIndex * Volume->MftRecordSize, (PCHAR)Buffer, Volume->MftRecordSize);
403+
if (BytesRead != Volume->MftRecordSize)
404+
return FALSE;
405+
406+
/* Apply update sequence array fixups. */
407+
return NtfsFixupRecord(Volume, (PNTFS_RECORD)Buffer);
408+
}
409+
410+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG Recursion);
411+
412+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelperList(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_LIST_ATTR AttrListRecord, PNTFS_ATTR_LIST_ATTR AttrListRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG Recursion)
413+
{
414+
PNTFS_MFT_RECORD MftRecord = FrLdrTempAlloc(Volume->MftRecordSize, TAG_NTFS_MFT);
415+
if (!MftRecord)
416+
return NULL;
417+
418+
while (AttrListRecord < AttrListRecordEnd)
419+
{
420+
ULONGLONG MftIndex = AttrListRecord->BaseFileRef & 0xFFFFFFFFFFFF;
421+
ULONG AttrType = AttrListRecord->Type;
422+
423+
if (AttrType == NTFS_ATTR_TYPE_END)
424+
break;
425+
426+
TRACE("Recursion = %u, AttrListRecord->Type = 0x%x\n", Recursion, AttrListRecord->Type);
427+
428+
if (AttrListRecord->Type == Type && AttrListRecord->NameLength == NameLength)
429+
{
430+
PWCHAR AttrListName;
431+
432+
AttrListName = (PWCHAR)((PCHAR)AttrListRecord + AttrListRecord->NameOffset);
433+
if (RtlEqualMemory(AttrListName, Name, NameLength << 1))
434+
{
435+
PNTFS_ATTR_CONTEXT Context;
436+
PNTFS_ATTR_RECORD AttrRecord;
437+
PNTFS_ATTR_RECORD AttrRecordEnd;
438+
439+
if (!NtfsReadMftRecord(Volume, MftIndex, MftRecord))
440+
goto skip;
441+
442+
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
443+
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->BytesInUse);
444+
445+
Context = NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, Recursion + 1);
446+
if (Context)
447+
{
448+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
449+
return Context;
450+
}
451+
}
452+
}
453+
454+
skip:
455+
if (AttrListRecord->RecLength == 0)
456+
break;
457+
AttrListRecord = (PNTFS_ATTR_LIST_ATTR)((PCHAR)AttrListRecord + AttrListRecord->RecLength);
458+
}
459+
460+
FrLdrTempFree(MftRecord, TAG_NTFS_MFT);
461+
return NULL;
462+
}
463+
464+
static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTFS_ATTR_RECORD AttrRecord, PNTFS_ATTR_RECORD AttrRecordEnd, ULONG Type, const WCHAR *Name, ULONG NameLength, ULONG Recursion)
375465
{
376466
while (AttrRecord < AttrRecordEnd)
377467
{
378468
if (AttrRecord->Type == NTFS_ATTR_TYPE_END)
379469
break;
380470

381-
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST)
471+
TRACE("Recursion = %u, AttrRecord->Type = 0x%x\n", Recursion, AttrRecord->Type);
472+
473+
if (AttrRecord->Type == NTFS_ATTR_TYPE_ATTRIBUTE_LIST && Recursion < 8)
382474
{
383475
PNTFS_ATTR_CONTEXT Context;
384476
PNTFS_ATTR_CONTEXT ListContext;
385477
PVOID ListBuffer;
386478
ULONGLONG ListSize;
387-
PNTFS_ATTR_RECORD ListAttrRecord;
388-
PNTFS_ATTR_RECORD ListAttrRecordEnd;
479+
PNTFS_ATTR_LIST_ATTR ListAttrRecord;
480+
PNTFS_ATTR_LIST_ATTR ListAttrRecordEnd;
389481

390482
ListContext = NtfsPrepareAttributeContext(AttrRecord);
391483

@@ -401,13 +493,13 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
401493
continue;
402494
}
403495

404-
ListAttrRecord = (PNTFS_ATTR_RECORD)ListBuffer;
405-
ListAttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)ListBuffer + ListSize);
496+
ListAttrRecord = (PNTFS_ATTR_LIST_ATTR)ListBuffer;
497+
ListAttrRecordEnd = (PNTFS_ATTR_LIST_ATTR)((PCHAR)ListBuffer + ListSize);
406498

407499
if (NtfsReadAttribute(Volume, ListContext, 0, ListBuffer, (ULONG)ListSize) == ListSize)
408500
{
409-
Context = NtfsFindAttributeHelper(Volume, ListAttrRecord, ListAttrRecordEnd,
410-
Type, Name, NameLength);
501+
Context = NtfsFindAttributeHelperList(Volume, ListAttrRecord, ListAttrRecordEnd,
502+
Type, Name, NameLength, Recursion + 1);
411503

412504
NtfsReleaseAttributeContext(ListContext);
413505
FrLdrTempFree(ListBuffer, TAG_NTFS_LIST);
@@ -419,7 +511,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
419511

420512
if (AttrRecord->Type == Type)
421513
{
422-
if (AttrRecord->NameLength == NameLength)
514+
if (AttrRecord->NameLength == NameLength && NtfsGetAttributeSize(AttrRecord) != 0)
423515
{
424516
PWCHAR AttrName;
425517

@@ -433,7 +525,7 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttributeHelper(PNTFS_VOLUME_INFO Volume, PNTF
433525
}
434526

435527
if (AttrRecord->Length == 0)
436-
return NULL;
528+
break;
437529
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)AttrRecord + AttrRecord->Length);
438530
}
439531

@@ -447,47 +539,11 @@ static PNTFS_ATTR_CONTEXT NtfsFindAttribute(PNTFS_VOLUME_INFO Volume, PNTFS_MFT_
447539
ULONG NameLength;
448540

449541
AttrRecord = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->AttributesOffset);
450-
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + Volume->MftRecordSize);
542+
AttrRecordEnd = (PNTFS_ATTR_RECORD)((PCHAR)MftRecord + MftRecord->BytesInUse);
451543
for (NameLength = 0; Name[NameLength] != 0; NameLength++)
452544
;
453545

454-
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength);
455-
}
456-
457-
static BOOLEAN NtfsFixupRecord(PNTFS_VOLUME_INFO Volume, PNTFS_RECORD Record)
458-
{
459-
USHORT *USA;
460-
USHORT USANumber;
461-
USHORT USACount;
462-
USHORT *Block;
463-
464-
USA = (USHORT*)((PCHAR)Record + Record->USAOffset);
465-
USANumber = *(USA++);
466-
USACount = Record->USACount - 1; /* Exclude the USA Number. */
467-
Block = (USHORT*)((PCHAR)Record + Volume->BootSector.BytesPerSector - 2);
468-
469-
while (USACount)
470-
{
471-
if (*Block != USANumber)
472-
return FALSE;
473-
*Block = *(USA++);
474-
Block = (USHORT*)((PCHAR)Block + Volume->BootSector.BytesPerSector);
475-
USACount--;
476-
}
477-
478-
return TRUE;
479-
}
480-
481-
static BOOLEAN NtfsReadMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, PNTFS_MFT_RECORD Buffer)
482-
{
483-
ULONGLONG BytesRead;
484-
485-
BytesRead = NtfsReadAttribute(Volume, Volume->MFTContext, MFTIndex * Volume->MftRecordSize, (PCHAR)Buffer, Volume->MftRecordSize);
486-
if (BytesRead != Volume->MftRecordSize)
487-
return FALSE;
488-
489-
/* Apply update sequence array fixups. */
490-
return NtfsFixupRecord(Volume, (PNTFS_RECORD)Buffer);
546+
return NtfsFindAttributeHelper(Volume, AttrRecord, AttrRecordEnd, Type, Name, NameLength, 0);
491547
}
492548

493549
#if DBG
@@ -592,6 +648,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
592648
while (IndexEntry < IndexEntryEnd &&
593649
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
594650
{
651+
TRACE("%s ", FileName);
595652
if (NtfsCompareFileName(FileName, IndexEntry))
596653
{
597654
*OutMFTIndex = (IndexEntry->Data.Directory.IndexedFile & NTFS_MFT_MASK);
@@ -675,6 +732,7 @@ static BOOLEAN NtfsFindMftRecord(PNTFS_VOLUME_INFO Volume, ULONGLONG MFTIndex, P
675732
while (IndexEntry < IndexEntryEnd &&
676733
!(IndexEntry->Flags & NTFS_INDEX_ENTRY_END))
677734
{
735+
TRACE("%s ", FileName);
678736
if (NtfsCompareFileName(FileName, IndexEntry))
679737
{
680738
TRACE("File found\n");

0 commit comments

Comments
 (0)