diff options
Diffstat (limited to 'private/ntos/cntfs/views/check.c')
-rw-r--r-- | private/ntos/cntfs/views/check.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/private/ntos/cntfs/views/check.c b/private/ntos/cntfs/views/check.c new file mode 100644 index 000000000..c07b71acd --- /dev/null +++ b/private/ntos/cntfs/views/check.c @@ -0,0 +1,282 @@ +/*++ + +Copyright (c) 1989-1997 Microsoft Corporation + +Module Name: + + check.c + +Abstract: + + This module contains the property set check support + + +--*/ + +#include <viewprop.h> // needs propset.h and ntfsprop.h + +#define Dbg DEBUG_TRACE_PROP_FSCTL + + +VOID +CheckPropertySet ( + IN PPROPERTY_CONTEXT Context + ) + +/*++ + +Routine Description: + + This routine performs validates the syntax of the property set + stream. + +Arguments: + + Context - context of call + +Return Value: + + Nothing. May raise if object is corrupt. + +--*/ + +{ + PPROPERTY_SET_HEADER Header = Context->Header; + PPROPERTY_ID_TABLE IdTable = Context->IdTable; + PPROPERTY_HEAP_HEADER HeapHeader = Context->HeapHeader; + PPROPERTY_HEAP_ENTRY HeapEntry; + ULONG Length = (ULONG) Context->Attribute->Header.FileSize.QuadPart ; + ULONG i; + + if ( + // + // Verify initial length + // + + (Length < sizeof( PROPERTY_SET_HEADER ) + DebugDoit( && PROPASSERT( !"Not enough room for header" ))) || + + // + // Verify header of attribute. Check the signature and format stamp. + // + + (Header->wByteOrder != 0xFFFE + DebugDoit( && PROPASSERT( !"Byte order invalid" ))) || + (Header->wFormat != PSH_FORMAT_VERSION + DebugDoit( && PROPASSERT( !"Format version invalid" ))) || + ((HIWORD( Header->dwOSVer ) > 2 || + LOBYTE( LOWORD( Header->dwOSVer )) > 5) + DebugDoit( && PROPASSERT( !"dwOSVer invalid" ))) || + + // + // Verify offsets of table and heap are valid. + // + + (Header->IdTableOffset >= Length + DebugDoit( && PROPASSERT( !"IdTable offset invalid" ))) || + (Header->IdTableOffset != LongAlign( Header->IdTableOffset ) + DebugDoit( && PROPASSERT( !"IdTable misaligned" ))) || + (Header->ValueHeapOffset >= Length + DebugDoit( && PROPASSERT( !"ValueHeap offset invalid" ))) || + (Header->ValueHeapOffset != LongAlign( Header->ValueHeapOffset ) + DebugDoit( && PROPASSERT( !"ValueHeap misaligned" ))) || + + // + // Verify that the table fits below the value heap + // + + (PROPERTY_ID_TABLE_SIZE( IdTable->MaximumPropertyCount ) > + Header->ValueHeapOffset - Header->IdTableOffset + DebugDoit( && PROPASSERT( !"IdTable overlaps ValueHeap" ))) || + + // + // Verify that the heap is within the stream + // + + (Header->ValueHeapOffset + HeapHeader->PropertyHeapLength > Length + DebugDoit( && PROPASSERT( !"ValueHeap beyond end of stream" ))) || + + // + // Verify table counts are correct + // + + (IdTable->PropertyCount > IdTable->MaximumPropertyCount + DebugDoit( && PROPASSERT( !"IdTable counts are incorrect" ))) + + ) { + + NtfsRaiseStatus( Context->IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Context->Object ); + } + + for (i = 0; i < IdTable->PropertyCount; i++) { + PPROPERTY_TABLE_ENTRY Entry = (PPROPERTY_TABLE_ENTRY) &IdTable->Entry[i]; + if ( + // + // Verify sorting + // + + (i > 1 && Entry[-1].PropertyId >= Entry[0].PropertyId + DebugDoit( && PROPASSERT( !"IdTable entry sort invalid" ))) || + (i < IdTable->PropertyCount - 1 && Entry[0].PropertyId >= Entry[1].PropertyId + DebugDoit( && PROPASSERT( !"IdTable entry sort invalid 2" ))) || + + // + // Verify offset points within heap + // + + (Entry[0].PropertyValueOffset >= HeapHeader->PropertyHeapLength + DebugDoit( && PROPASSERT( !"IdTable entry offset invalid" ))) || + + // + // Verify the back pointer matches + // + + (Entry[0].PropertyId != GET_HEAP_ENTRY( HeapHeader, Entry[0].PropertyValueOffset )->PropertyId + DebugDoit( && PROPASSERT( !"Backpointer invalid" ))) + ) { + + NtfsRaiseStatus( Context->IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Context->Object ); + } + } + + HeapEntry = FIRST_HEAP_ENTRY( HeapHeader ); + while (!IS_LAST_HEAP_ENTRY( HeapHeader, HeapEntry )) { + + if (HeapEntry->PropertyId != PID_ILLEGAL) { + ULONG Index = + BinarySearchIdTable( Context, HeapEntry->PropertyId ); + + if ( + // + // Verify length is aligned + // + + (HeapEntry->PropertyValueLength != LongAlign( HeapEntry->PropertyValueLength ) + DebugDoit( && PROPASSERT( !"Property length misaligned" ))) || + // + // Verify backpointer works + // + + (Index >= IdTable->PropertyCount + DebugDoit( && PROPASSERT( !"Backpointer after end of table" ))) || + + // + // Backpointer Id agrees + // + + (IdTable->Entry[Index].PropertyId != HeapEntry->PropertyId + DebugDoit( && PROPASSERT( !"Backpointer not found in table" ))) || + + // + // Backpointer offset agrees + // + + (IdTable->Entry[Index].PropertyValueOffset != HeapOffset( Context, HeapEntry) + DebugDoit( && PROPASSERT( !"Backpointer not found in table" ))) || + + // + // Name length is word aligned + // + + (HeapEntry->PropertyNameLength != WordAlign( HeapEntry->PropertyNameLength ) + DebugDoit( && PROPASSERT( !"Name is odd number of bytes" ))) || + + // + // Verify property is entirely in heap + // + + (HeapOffset( Context, NEXT_HEAP_ENTRY( HeapEntry)) > HeapHeader->PropertyHeapLength + DebugDoit( && PROPASSERT( !"Property Value overlaps end of heap" ))) + + ) { + + NtfsRaiseStatus( Context->IrpContext, STATUS_FILE_CORRUPT_ERROR, NULL, Context->Object ); + } + } + + HeapEntry = NEXT_HEAP_ENTRY( HeapEntry ); + } +} + + +VOID +DumpPropertyData ( + IN PPROPERTY_CONTEXT Context + ) + +/*++ + +Routine Description: + + This routine performs validates the syntax of the property set + stream. + +Arguments: + + Context - context of call + +Return Value: + + None + +--*/ + +{ + PPROPERTY_HEAP_ENTRY HeapEntry; + + ULONG i; + + // + // Map attribute for full size + // + + MapPropertyContext( Context ); + + // + // Verify the property set has valid contents. + // + + CheckPropertySet( Context ); + + // + // Dump out contents of property set + // + + DebugTrace( 0, Dbg, ("Property set dump\n") ); + DebugTrace( 0, Dbg, ("wByteOrder %04x wFormat %04x dwOSVer %08x\n", + Context->Header->wByteOrder, + Context->Header->wFormat, + Context->Header->dwOSVer) ); + DebugTrace( 0, Dbg, ("IdTableOffset %08x ValueHeapOffset %08x\n", + Context->Header->IdTableOffset, + Context->Header->ValueHeapOffset) ); + + DebugTrace( 0, Dbg, ("IdTable %x/%x entries used\n", + Context->IdTable->PropertyCount, + Context->IdTable->MaximumPropertyCount) ); + for (i = 0; i < Context->IdTable->PropertyCount; i++) { + DebugTrace( 0, Dbg, (" Entry[%d].PropertyId %08x .Header %08x\n", + i, + Context->IdTable->Entry[i].PropertyId, + Context->IdTable->Entry[i].PropertyValueOffset) ); + } + + + DebugTrace( 0, Dbg, ("PropertyHeapLength %08x\n", + Context->HeapHeader->PropertyHeapLength) ); + + HeapEntry = FIRST_HEAP_ENTRY( Context->HeapHeader ); + while (!IS_LAST_HEAP_ENTRY( Context->HeapHeader, HeapEntry )) { + DebugTrace( 0, Dbg, (" Heap[%08x].Length %08x .PropertyId %08x .PropertyNameLength %04x\n", + HeapOffset( Context, HeapEntry ), + HeapEntry->PropertyValueLength, + HeapEntry->PropertyId, + HeapEntry->PropertyNameLength) ); + DebugTrace( 0, Dbg, (" .PropertyName '%.*ws'\n", + HeapEntry->PropertyNameLength / sizeof( WCHAR ), + HeapEntry->PropertyName) ); + HeapEntry = NEXT_HEAP_ENTRY( HeapEntry ); + } + +} + |