2002-07-15 15:37:33 +00:00
|
|
|
/*
|
|
|
|
* ReactOS kernel
|
2003-01-17 18:51:13 +00:00
|
|
|
* Copyright (C) 2002,2003 ReactOS Team
|
2002-07-15 15:37:33 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
2008-03-08 21:45:51 +00:00
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
|
2002-07-15 15:37:33 +00:00
|
|
|
*
|
|
|
|
* COPYRIGHT: See COPYING in the top level directory
|
|
|
|
* PROJECT: ReactOS kernel
|
2008-02-10 11:20:29 +00:00
|
|
|
* FILE: drivers/filesystem/ntfs/attrib.c
|
2002-07-15 15:37:33 +00:00
|
|
|
* PURPOSE: NTFS filesystem driver
|
2014-11-02 22:56:38 +00:00
|
|
|
* PROGRAMMERS: Eric Kohl
|
|
|
|
* Valentin Verkhovsky
|
|
|
|
* Hervé Poussineau (hpoussin@reactos.org)
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
* Pierre Schweitzer (pierre@reactos.org)
|
2002-07-15 15:37:33 +00:00
|
|
|
*/
|
|
|
|
|
|
|
|
/* INCLUDES *****************************************************************/
|
|
|
|
|
2005-07-20 02:52:52 +00:00
|
|
|
#include "ntfs.h"
|
2003-08-07 11:47:33 +00:00
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
#define NDEBUG
|
2002-07-15 15:37:33 +00:00
|
|
|
#include <debug.h>
|
|
|
|
|
|
|
|
/* FUNCTIONS ****************************************************************/
|
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
PUCHAR
|
|
|
|
DecodeRun(PUCHAR DataRun,
|
|
|
|
LONGLONG *DataRunOffset,
|
|
|
|
ULONGLONG *DataRunLength)
|
2003-09-15 16:01:16 +00:00
|
|
|
{
|
2014-09-26 13:57:29 +00:00
|
|
|
UCHAR DataRunOffsetSize;
|
|
|
|
UCHAR DataRunLengthSize;
|
|
|
|
CHAR i;
|
|
|
|
|
|
|
|
DataRunOffsetSize = (*DataRun >> 4) & 0xF;
|
|
|
|
DataRunLengthSize = *DataRun & 0xF;
|
|
|
|
*DataRunOffset = 0;
|
|
|
|
*DataRunLength = 0;
|
|
|
|
DataRun++;
|
|
|
|
for (i = 0; i < DataRunLengthSize; i++)
|
|
|
|
{
|
|
|
|
*DataRunLength += ((ULONG64)*DataRun) << (i * 8);
|
|
|
|
DataRun++;
|
|
|
|
}
|
2003-09-15 16:01:16 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
/* NTFS 3+ sparse files */
|
|
|
|
if (DataRunOffsetSize == 0)
|
|
|
|
{
|
|
|
|
*DataRunOffset = -1;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
for (i = 0; i < DataRunOffsetSize - 1; i++)
|
|
|
|
{
|
|
|
|
*DataRunOffset += ((ULONG64)*DataRun) << (i * 8);
|
|
|
|
DataRun++;
|
|
|
|
}
|
|
|
|
/* The last byte contains sign so we must process it different way. */
|
|
|
|
*DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset;
|
|
|
|
}
|
2003-09-15 16:01:16 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
DPRINT("DataRunOffsetSize: %x\n", DataRunOffsetSize);
|
|
|
|
DPRINT("DataRunLengthSize: %x\n", DataRunLengthSize);
|
|
|
|
DPRINT("DataRunOffset: %x\n", *DataRunOffset);
|
|
|
|
DPRINT("DataRunLength: %x\n", *DataRunLength);
|
2003-09-15 16:01:16 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
return DataRun;
|
2003-09-15 16:01:16 +00:00
|
|
|
}
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
BOOLEAN
|
2014-09-26 13:57:29 +00:00
|
|
|
FindRun(PNTFS_ATTR_RECORD NresAttr,
|
2013-06-16 12:15:06 +00:00
|
|
|
ULONGLONG vcn,
|
|
|
|
PULONGLONG lcn,
|
|
|
|
PULONGLONG count)
|
2003-11-12 15:30:21 +00:00
|
|
|
{
|
2014-09-26 13:57:29 +00:00
|
|
|
if (vcn < NresAttr->NonResident.LowestVCN || vcn > NresAttr->NonResident.HighestVCN)
|
2013-06-16 12:15:06 +00:00
|
|
|
return FALSE;
|
2003-11-12 15:30:21 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
DecodeRun((PUCHAR)((ULONG_PTR)NresAttr + NresAttr->NonResident.MappingPairsOffset), (PLONGLONG)lcn, count);
|
2013-06-16 12:15:06 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
return TRUE;
|
2003-11-12 15:30:21 +00:00
|
|
|
}
|
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
static
|
|
|
|
NTSTATUS
|
|
|
|
InternalReadNonResidentAttributes(PFIND_ATTR_CONTXT Context)
|
|
|
|
{
|
|
|
|
ULONGLONG ListSize;
|
|
|
|
PNTFS_ATTR_RECORD Attribute;
|
|
|
|
PNTFS_ATTR_CONTEXT ListContext;
|
|
|
|
|
|
|
|
DPRINT("InternalReadNonResidentAttributes(%p)\n", Context);
|
|
|
|
|
|
|
|
Attribute = Context->CurrAttr;
|
|
|
|
ASSERT(Attribute->Type == AttributeAttributeList);
|
|
|
|
|
|
|
|
if (Context->OnlyResident)
|
|
|
|
{
|
|
|
|
Context->NonResidentStart = NULL;
|
|
|
|
Context->NonResidentEnd = NULL;
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context->NonResidentStart != NULL)
|
|
|
|
{
|
|
|
|
return STATUS_FILE_CORRUPT_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ListContext = PrepareAttributeContext(Attribute);
|
|
|
|
ListSize = AttributeDataLength(&ListContext->Record);
|
|
|
|
if (ListSize > 0xFFFFFFFF)
|
|
|
|
{
|
|
|
|
ReleaseAttributeContext(ListContext);
|
|
|
|
return STATUS_BUFFER_OVERFLOW;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context->NonResidentStart = ExAllocatePoolWithTag(NonPagedPool, (ULONG)ListSize, TAG_NTFS);
|
|
|
|
if (Context->NonResidentStart == NULL)
|
|
|
|
{
|
|
|
|
ReleaseAttributeContext(ListContext);
|
|
|
|
return STATUS_INSUFFICIENT_RESOURCES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ReadAttribute(Context->Vcb, ListContext, 0, (PCHAR)Context->NonResidentStart, (ULONG)ListSize) != ListSize)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
|
|
|
|
Context->NonResidentStart = NULL;
|
|
|
|
ReleaseAttributeContext(ListContext);
|
|
|
|
return STATUS_FILE_CORRUPT_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
ReleaseAttributeContext(ListContext);
|
|
|
|
Context->NonResidentEnd = (PNTFS_ATTR_RECORD)((PCHAR)Context->NonResidentStart + ListSize);
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
static
|
|
|
|
PNTFS_ATTR_RECORD
|
|
|
|
InternalGetNextAttribute(PFIND_ATTR_CONTXT Context)
|
|
|
|
{
|
|
|
|
if (Context->CurrAttr == (PVOID)-1)
|
|
|
|
{
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context->CurrAttr >= Context->FirstAttr &&
|
|
|
|
Context->CurrAttr < Context->LastAttr)
|
|
|
|
{
|
|
|
|
if (Context->CurrAttr->Length == 0)
|
|
|
|
{
|
|
|
|
DPRINT1("Broken length!\n");
|
|
|
|
Context->CurrAttr = (PVOID)-1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context->CurrAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
|
|
|
|
if (Context->CurrAttr < Context->LastAttr &&
|
|
|
|
Context->CurrAttr->Type != AttributeEnd)
|
|
|
|
{
|
|
|
|
return Context->CurrAttr;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context->NonResidentStart == NULL)
|
|
|
|
{
|
|
|
|
Context->CurrAttr = (PVOID)-1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context->CurrAttr < Context->NonResidentStart ||
|
|
|
|
Context->CurrAttr >= Context->NonResidentEnd)
|
|
|
|
{
|
|
|
|
Context->CurrAttr = Context->NonResidentStart;
|
|
|
|
}
|
|
|
|
else if (Context->CurrAttr->Length != 0)
|
|
|
|
{
|
|
|
|
Context->CurrAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)Context->CurrAttr + Context->CurrAttr->Length);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
DPRINT1("Broken length!\n");
|
|
|
|
Context->CurrAttr = (PVOID)-1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context->CurrAttr < Context->NonResidentEnd &&
|
|
|
|
Context->CurrAttr->Type != AttributeEnd)
|
|
|
|
{
|
|
|
|
return Context->CurrAttr;
|
|
|
|
}
|
|
|
|
|
|
|
|
Context->CurrAttr = (PVOID)-1;
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FindFirstAttribute(PFIND_ATTR_CONTXT Context,
|
|
|
|
PDEVICE_EXTENSION Vcb,
|
|
|
|
PFILE_RECORD_HEADER FileRecord,
|
|
|
|
BOOLEAN OnlyResident,
|
|
|
|
PNTFS_ATTR_RECORD * Attribute)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("FindFistAttribute(%p, %p, %p, %p, %u, %p)\n", Context, Vcb, FileRecord, OnlyResident, Attribute);
|
|
|
|
|
|
|
|
Context->Vcb = Vcb;
|
|
|
|
Context->OnlyResident = OnlyResident;
|
|
|
|
Context->FirstAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset);
|
|
|
|
Context->CurrAttr = Context->FirstAttr;
|
|
|
|
Context->LastAttr = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse);
|
|
|
|
Context->NonResidentStart = NULL;
|
|
|
|
Context->NonResidentEnd = NULL;
|
|
|
|
|
|
|
|
if (Context->FirstAttr->Type == AttributeEnd)
|
|
|
|
{
|
|
|
|
Context->CurrAttr = (PVOID)-1;
|
|
|
|
return STATUS_END_OF_FILE;
|
|
|
|
}
|
|
|
|
else if (Context->FirstAttr->Type == AttributeAttributeList)
|
|
|
|
{
|
|
|
|
Status = InternalReadNonResidentAttributes(Context);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
*Attribute = InternalGetNextAttribute(Context);
|
|
|
|
if (*Attribute == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_END_OF_FILE;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
*Attribute = Context->CurrAttr;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
NTSTATUS
|
|
|
|
FindNextAttribute(PFIND_ATTR_CONTXT Context,
|
|
|
|
PNTFS_ATTR_RECORD * Attribute)
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
|
|
|
|
DPRINT("FindNextAttribute(%p, %p)\n", Context, Attribute);
|
|
|
|
|
|
|
|
*Attribute = InternalGetNextAttribute(Context);
|
|
|
|
if (*Attribute == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_END_OF_FILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (Context->CurrAttr->Type != AttributeAttributeList)
|
|
|
|
{
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = InternalReadNonResidentAttributes(Context);
|
|
|
|
if (!NT_SUCCESS(Status))
|
|
|
|
{
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
*Attribute = InternalGetNextAttribute(Context);
|
|
|
|
if (*Attribute == NULL)
|
|
|
|
{
|
|
|
|
return STATUS_END_OF_FILE;
|
|
|
|
}
|
|
|
|
|
|
|
|
return STATUS_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
|
|
FindCloseAttribute(PFIND_ATTR_CONTXT Context)
|
|
|
|
{
|
|
|
|
if (Context->NonResidentStart != NULL)
|
|
|
|
{
|
|
|
|
ExFreePoolWithTag(Context->NonResidentStart, TAG_NTFS);
|
|
|
|
Context->NonResidentStart = NULL;
|
|
|
|
}
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
static
|
|
|
|
VOID
|
2014-09-26 13:57:29 +00:00
|
|
|
NtfsDumpFileNameAttribute(PNTFS_ATTR_RECORD Attribute)
|
2003-01-17 18:51:13 +00:00
|
|
|
{
|
2013-06-16 12:15:06 +00:00
|
|
|
PFILENAME_ATTRIBUTE FileNameAttr;
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
DbgPrint(" $FILE_NAME ");
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
FileNameAttr = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
2014-12-08 18:44:29 +00:00
|
|
|
DbgPrint(" (%x) '%.*S' ", FileNameAttr->NameType, FileNameAttr->NameLength, FileNameAttr->Name);
|
|
|
|
DbgPrint(" '%x' ", FileNameAttr->FileAttributes);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
static
|
|
|
|
VOID
|
|
|
|
NtfsDumpStandardInformationAttribute(PNTFS_ATTR_RECORD Attribute)
|
|
|
|
{
|
|
|
|
PSTANDARD_INFORMATION StandardInfoAttr;
|
|
|
|
|
|
|
|
DbgPrint(" $STANDARD_INFORMATION ");
|
|
|
|
|
|
|
|
// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
|
|
|
|
|
|
|
|
StandardInfoAttr = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
|
|
|
DbgPrint(" '%x' ", StandardInfoAttr->FileAttribute);
|
2003-01-17 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
static
|
|
|
|
VOID
|
2014-09-26 13:57:29 +00:00
|
|
|
NtfsDumpVolumeNameAttribute(PNTFS_ATTR_RECORD Attribute)
|
2003-01-17 18:51:13 +00:00
|
|
|
{
|
2013-06-16 12:15:06 +00:00
|
|
|
PWCHAR VolumeName;
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
DbgPrint(" $VOLUME_NAME ");
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
VolumeName = (PWCHAR)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
|
|
|
DbgPrint(" '%.*S' ", Attribute->Resident.ValueLength / sizeof(WCHAR), VolumeName);
|
2003-01-17 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
static
|
|
|
|
VOID
|
2014-09-26 13:57:29 +00:00
|
|
|
NtfsDumpVolumeInformationAttribute(PNTFS_ATTR_RECORD Attribute)
|
2003-01-17 18:51:13 +00:00
|
|
|
{
|
2013-06-16 12:15:06 +00:00
|
|
|
PVOLINFO_ATTRIBUTE VolInfoAttr;
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
DbgPrint(" $VOLUME_INFORMATION ");
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
// DbgPrint(" Length %lu Offset %hu ", Attribute->Resident.ValueLength, Attribute->Resident.ValueOffset);
|
2003-01-17 18:51:13 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
VolInfoAttr = (PVOLINFO_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
2013-06-16 12:15:06 +00:00
|
|
|
DbgPrint(" NTFS Version %u.%u Flags 0x%04hx ",
|
|
|
|
VolInfoAttr->MajorVersion,
|
|
|
|
VolInfoAttr->MinorVersion,
|
|
|
|
VolInfoAttr->Flags);
|
2003-01-17 18:51:13 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-09-22 19:59:45 +00:00
|
|
|
static
|
|
|
|
VOID
|
2014-09-26 13:57:29 +00:00
|
|
|
NtfsDumpIndexRootAttribute(PNTFS_ATTR_RECORD Attribute)
|
2014-09-22 19:59:45 +00:00
|
|
|
{
|
|
|
|
PINDEX_ROOT_ATTRIBUTE IndexRootAttr;
|
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
IndexRootAttr = (PINDEX_ROOT_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
2014-09-22 19:59:45 +00:00
|
|
|
|
|
|
|
if (IndexRootAttr->AttributeType == AttributeFileName)
|
|
|
|
ASSERT(IndexRootAttr->CollationRule == COLLATION_FILE_NAME);
|
|
|
|
|
|
|
|
DbgPrint(" $INDEX_ROOT (%uB, %u) ", IndexRootAttr->SizeOfEntry, IndexRootAttr->ClustersPerIndexRecord);
|
2014-09-22 20:26:21 +00:00
|
|
|
|
|
|
|
if (IndexRootAttr->Header.Flags == INDEX_ROOT_SMALL)
|
|
|
|
{
|
|
|
|
DbgPrint(" (small) ");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
ASSERT(IndexRootAttr->Header.Flags == INDEX_ROOT_LARGE);
|
|
|
|
DbgPrint(" (large) ");
|
|
|
|
}
|
2014-09-22 19:59:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2015-06-27 15:06:25 +00:00
|
|
|
static
|
|
|
|
VOID
|
|
|
|
NtfsDumpAttribute(PDEVICE_EXTENSION Vcb,
|
|
|
|
PNTFS_ATTR_RECORD Attribute)
|
2002-07-15 15:37:33 +00:00
|
|
|
{
|
2013-06-16 12:15:06 +00:00
|
|
|
UNICODE_STRING Name;
|
2003-11-12 15:30:21 +00:00
|
|
|
|
2013-06-16 12:15:06 +00:00
|
|
|
ULONGLONG lcn = 0;
|
|
|
|
ULONGLONG runcount = 0;
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2014-09-26 13:57:29 +00:00
|
|
|
switch (Attribute->Type)
|
2002-07-15 15:37:33 +00:00
|
|
|
{
|
2013-06-16 12:15:06 +00:00
|
|
|
case AttributeFileName:
|
|
|
|
NtfsDumpFileNameAttribute(Attribute);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeStandardInformation:
|
2014-12-08 18:44:29 +00:00
|
|
|
NtfsDumpStandardInformationAttribute(Attribute);
|
2013-06-16 12:15:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeObjectId:
|
|
|
|
DbgPrint(" $OBJECT_ID ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeSecurityDescriptor:
|
|
|
|
DbgPrint(" $SECURITY_DESCRIPTOR ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeVolumeName:
|
|
|
|
NtfsDumpVolumeNameAttribute(Attribute);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeVolumeInformation:
|
|
|
|
NtfsDumpVolumeInformationAttribute(Attribute);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeData:
|
|
|
|
DbgPrint(" $DATA ");
|
|
|
|
//DataBuf = ExAllocatePool(NonPagedPool,AttributeLengthAllocated(Attribute));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeIndexRoot:
|
2014-09-22 19:59:45 +00:00
|
|
|
NtfsDumpIndexRootAttribute(Attribute);
|
2013-06-16 12:15:06 +00:00
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeIndexAllocation:
|
|
|
|
DbgPrint(" $INDEX_ALLOCATION ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeBitmap:
|
|
|
|
DbgPrint(" $BITMAP ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeReparsePoint:
|
|
|
|
DbgPrint(" $REPARSE_POINT ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeEAInformation:
|
|
|
|
DbgPrint(" $EA_INFORMATION ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeEA:
|
|
|
|
DbgPrint(" $EA ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributePropertySet:
|
|
|
|
DbgPrint(" $PROPERTY_SET ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AttributeLoggedUtilityStream:
|
|
|
|
DbgPrint(" $LOGGED_UTILITY_STREAM ");
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
DbgPrint(" Attribute %lx ",
|
2014-09-26 13:57:29 +00:00
|
|
|
Attribute->Type);
|
2013-06-16 12:15:06 +00:00
|
|
|
break;
|
2002-07-15 15:37:33 +00:00
|
|
|
}
|
|
|
|
|
2015-06-27 15:06:25 +00:00
|
|
|
if (Attribute->Type != AttributeAttributeList)
|
2002-07-15 15:37:33 +00:00
|
|
|
{
|
2015-06-27 15:06:25 +00:00
|
|
|
if (Attribute->NameLength != 0)
|
|
|
|
{
|
|
|
|
Name.Length = Attribute->NameLength * sizeof(WCHAR);
|
|
|
|
Name.MaximumLength = Name.Length;
|
|
|
|
Name.Buffer = (PWCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset);
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2015-06-27 15:06:25 +00:00
|
|
|
DbgPrint("'%wZ' ", &Name);
|
|
|
|
}
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2015-06-27 15:06:25 +00:00
|
|
|
DbgPrint("(%s)\n",
|
|
|
|
Attribute->IsNonResident ? "non-resident" : "resident");
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2015-06-27 15:06:25 +00:00
|
|
|
if (Attribute->IsNonResident)
|
|
|
|
{
|
|
|
|
FindRun(Attribute,0,&lcn, &runcount);
|
2002-07-15 15:37:33 +00:00
|
|
|
|
2015-06-27 15:06:25 +00:00
|
|
|
DbgPrint(" AllocatedSize %I64u DataSize %I64u\n",
|
|
|
|
Attribute->NonResident.AllocatedSize, Attribute->NonResident.DataSize);
|
|
|
|
DbgPrint(" logical clusters: %I64u - %I64u\n",
|
|
|
|
lcn, lcn + runcount - 1);
|
|
|
|
}
|
2003-11-12 15:30:21 +00:00
|
|
|
}
|
|
|
|
}
|
2003-09-15 16:01:16 +00:00
|
|
|
|
|
|
|
|
2003-11-12 15:30:21 +00:00
|
|
|
VOID
|
2015-06-27 15:06:25 +00:00
|
|
|
NtfsDumpFileAttributes(PDEVICE_EXTENSION Vcb,
|
|
|
|
PFILE_RECORD_HEADER FileRecord)
|
2003-11-12 15:30:21 +00:00
|
|
|
{
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
FIND_ATTR_CONTXT Context;
|
2014-09-26 13:57:29 +00:00
|
|
|
PNTFS_ATTR_RECORD Attribute;
|
2003-09-15 16:01:16 +00:00
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
|
|
|
|
while (NT_SUCCESS(Status))
|
2003-11-12 15:30:21 +00:00
|
|
|
{
|
2015-06-27 15:06:25 +00:00
|
|
|
NtfsDumpAttribute(Vcb, Attribute);
|
2002-07-15 15:37:33 +00:00
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
Status = FindNextAttribute(&Context, &Attribute);
|
2003-11-12 15:30:21 +00:00
|
|
|
}
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
|
|
|
|
FindCloseAttribute(&Context);
|
2002-07-15 15:37:33 +00:00
|
|
|
}
|
|
|
|
|
2014-10-08 19:12:48 +00:00
|
|
|
PFILENAME_ATTRIBUTE
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
GetFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
|
|
|
PFILE_RECORD_HEADER FileRecord,
|
|
|
|
UCHAR NameType)
|
2014-10-08 19:12:48 +00:00
|
|
|
{
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FIND_ATTR_CONTXT Context;
|
2014-10-08 19:12:48 +00:00
|
|
|
PNTFS_ATTR_RECORD Attribute;
|
2014-10-26 19:10:17 +00:00
|
|
|
PFILENAME_ATTRIBUTE Name;
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
NTSTATUS Status;
|
2014-10-08 19:12:48 +00:00
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
|
|
|
|
while (NT_SUCCESS(Status))
|
2014-10-08 19:12:48 +00:00
|
|
|
{
|
|
|
|
if (Attribute->Type == AttributeFileName)
|
2014-10-26 19:10:17 +00:00
|
|
|
{
|
|
|
|
Name = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
|
|
|
if (Name->NameType == NameType ||
|
|
|
|
(Name->NameType == NTFS_FILE_NAME_WIN32_AND_DOS && NameType == NTFS_FILE_NAME_WIN32) ||
|
|
|
|
(Name->NameType == NTFS_FILE_NAME_WIN32_AND_DOS && NameType == NTFS_FILE_NAME_DOS))
|
|
|
|
{
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FindCloseAttribute(&Context);
|
2014-10-26 19:10:17 +00:00
|
|
|
return Name;
|
|
|
|
}
|
|
|
|
}
|
2014-10-08 19:12:48 +00:00
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
Status = FindNextAttribute(&Context, &Attribute);
|
2014-10-08 19:12:48 +00:00
|
|
|
}
|
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FindCloseAttribute(&Context);
|
2014-10-08 19:12:48 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-12-08 19:19:30 +00:00
|
|
|
PSTANDARD_INFORMATION
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
GetStandardInformationFromRecord(PDEVICE_EXTENSION Vcb,
|
|
|
|
PFILE_RECORD_HEADER FileRecord)
|
2014-12-08 19:19:30 +00:00
|
|
|
{
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
NTSTATUS Status;
|
|
|
|
FIND_ATTR_CONTXT Context;
|
2014-12-08 19:19:30 +00:00
|
|
|
PNTFS_ATTR_RECORD Attribute;
|
|
|
|
PSTANDARD_INFORMATION StdInfo;
|
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
Status = FindFirstAttribute(&Context, Vcb, FileRecord, FALSE, &Attribute);
|
|
|
|
while (NT_SUCCESS(Status))
|
2014-12-08 19:19:30 +00:00
|
|
|
{
|
|
|
|
if (Attribute->Type == AttributeStandardInformation)
|
|
|
|
{
|
|
|
|
StdInfo = (PSTANDARD_INFORMATION)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset);
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FindCloseAttribute(&Context);
|
2014-12-08 19:19:30 +00:00
|
|
|
return StdInfo;
|
|
|
|
}
|
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
Status = FindNextAttribute(&Context, &Attribute);
|
2014-12-08 19:19:30 +00:00
|
|
|
}
|
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FindCloseAttribute(&Context);
|
2014-12-08 19:19:30 +00:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2014-11-23 14:07:08 +00:00
|
|
|
PFILENAME_ATTRIBUTE
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
GetBestFileNameFromRecord(PDEVICE_EXTENSION Vcb,
|
|
|
|
PFILE_RECORD_HEADER FileRecord)
|
2014-11-23 14:07:08 +00:00
|
|
|
{
|
|
|
|
PFILENAME_ATTRIBUTE FileName;
|
|
|
|
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FileName = GetFileNameFromRecord(Vcb, FileRecord, NTFS_FILE_NAME_POSIX);
|
2014-11-23 14:07:08 +00:00
|
|
|
if (FileName == NULL)
|
|
|
|
{
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FileName = GetFileNameFromRecord(Vcb, FileRecord, NTFS_FILE_NAME_WIN32);
|
2014-11-23 14:07:08 +00:00
|
|
|
if (FileName == NULL)
|
|
|
|
{
|
[NTFS]
Totally rewrite the way MFT records attributes are handled.
Up to now, we were having really similar loops, only looking at the resident part of the attribute list, not really caring about how the loop was going.
This was leading to some issues:
- In case the attribute we were looking for was stored in the non-resident part of the attribute list, we would miss it (excepted in the case of FindAttribute() which was properly browsing the whole attribute list).
- In the specific case of FindAttribute(), one would have been able to setup a broken MFT record with the resident attribute list pointing on the non resident attribute list which itself would point to the resident attribute list. In such case, the driver would loop forever caught on the loop, allocating tones of memory. It was possible to trigger this by user space, from a non-privileged user, just by browsing the right directory entry.
- In the case of the other loops (non FindAttribute()), another issue (other than missing attributes) was present, one would have been able to setup a broken MFT record with an attribute of null-length. This would have caused the driver to loop forever on the attribute list. This could be triggered from usermode too. And could be triggered by a non-privileged user.
This commit introduces a new set of functions for attributes browsing: FindFirstAttribute(), FindNextAttribute(), FindCloseAttribute(). It allows safely browsing attributes and handles broken cases. It also performs reading of the attribute list when present and makes sure there's only one read. This method should be the only one to use to browse the attributes.
The whole NTFS code base has been converted to use this newly set of functions. This really simplifies the implementation of FindAttribute(), and prevent unsafe code duplication.
CORE-10037 #resolve #comment Fixed with r68829
svn path=/trunk/; revision=68829
2015-08-26 18:20:04 +00:00
|
|
|
FileName = GetFileNameFromRecord(Vcb, FileRecord, NTFS_FILE_NAME_DOS);
|
2014-11-23 14:07:08 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return FileName;
|
|
|
|
}
|
|
|
|
|
2002-07-15 15:37:33 +00:00
|
|
|
/* EOF */
|