windows-nt/Source/XPSP1/NT/base/ntos/config/cmchek2.c
2020-09-26 16:20:57 +08:00

250 lines
7.5 KiB
C

/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
cmchek2.c
Abstract:
This module implements consistency checking for the registry.
Author:
Bryan M. Willman (bryanwi) 27-Jan-92
Environment:
Revision History:
--*/
#include "cmp.h"
#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE,CmpValidateHiveSecurityDescriptors)
#endif
extern ULONG CmpUsedStorage;
#ifdef HIVE_SECURITY_STATS
ULONG
CmpCheckForSecurityDuplicates(
IN OUT PCMHIVE CmHive
);
#endif
BOOLEAN
CmpValidateHiveSecurityDescriptors(
IN PHHIVE Hive,
OUT PBOOLEAN ResetSD
)
/*++
Routine Description:
Walks the list of security descriptors present in the hive and passes
each security descriptor to RtlValidSecurityDescriptor.
Only applies to descriptors in Stable store. Those in Volatile store
cannot have come from disk and therefore do not need this treatment
anyway.
Arguments:
Hive - Supplies pointer to the hive control structure
Return Value:
TRUE - All security descriptors are valid
FALSE - At least one security descriptor is invalid
--*/
{
PCM_KEY_NODE RootNode;
PCM_KEY_SECURITY SecurityCell;
HCELL_INDEX ListAnchor;
HCELL_INDEX NextCell;
HCELL_INDEX LastCell;
BOOLEAN BuildSecurityCache;
#ifdef HIVE_SECURITY_STATS
UNICODE_STRING HiveName;
ULONG NoOfCells = 0;
ULONG SmallestSize = 0;
ULONG BiggestSize = 0;
ULONG TotalSecuritySize = 0;
RtlInitUnicodeString(&HiveName, (PCWSTR)Hive->BaseBlock->FileName);
#ifndef _CM_LDR_
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Security stats for hive (%lx) (%.*S):\n",Hive,HiveName.Length / sizeof(WCHAR),HiveName.Buffer);
#endif //_CM_LDR_
#endif
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC,"CmpValidateHiveSecurityDescriptor: Hive = %p\n",(ULONG_PTR)Hive));
ASSERT( Hive->ReleaseCellRoutine == NULL );
*ResetSD = FALSE;
if( ((PCMHIVE)Hive)->SecurityCount == 0 ) {
BuildSecurityCache = TRUE;
} else {
BuildSecurityCache = FALSE;
}
if (!HvIsCellAllocated(Hive,Hive->BaseBlock->RootCell)) {
//
// root cell HCELL_INDEX is bogus
//
return(FALSE);
}
RootNode = (PCM_KEY_NODE) HvGetCell(Hive, Hive->BaseBlock->RootCell);
if( RootNode == NULL ) {
//
// we couldn't map a view for the bin containing this cell
//
return FALSE;
}
if( FALSE ) {
YankSD:
if( CmDoSelfHeal() ) {
//
// reset all security for the entire hive to the root security. There is no reliable way to
// patch the security list
//
SecurityCell = (PCM_KEY_SECURITY) HvGetCell(Hive, RootNode->Security);
if( SecurityCell == NULL ) {
return FALSE;
}
if( HvMarkCellDirty(Hive, RootNode->Security) ) {
SecurityCell->Flink = SecurityCell->Blink = RootNode->Security;
} else {
return FALSE;
}
//
// destroy existing cache and set up an empty one
//
CmpDestroySecurityCache((PCMHIVE)Hive);
CmpInitSecurityCache((PCMHIVE)Hive);
CmMarkSelfHeal(Hive);
*ResetSD = TRUE;
} else {
return FALSE;
}
}
LastCell = 0;
ListAnchor = NextCell = RootNode->Security;
do {
if (!HvIsCellAllocated(Hive, NextCell)) {
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC,"CM: CmpValidateHiveSecurityDescriptors\n"));
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC," NextCell: %08lx is invalid HCELL_INDEX\n",NextCell));
goto YankSD;
}
SecurityCell = (PCM_KEY_SECURITY) HvGetCell(Hive, NextCell);
if( SecurityCell == NULL ) {
//
// we couldn't map a view for the bin containing this cell
//
return FALSE;
}
#ifdef HIVE_SECURITY_STATS
NoOfCells++;
if( (SmallestSize == 0) || ((SecurityCell->DescriptorLength + FIELD_OFFSET(CM_KEY_SECURITY, Descriptor)) < SmallestSize) ) {
SmallestSize = SecurityCell->DescriptorLength + FIELD_OFFSET(CM_KEY_SECURITY, Descriptor);
}
if( (BiggestSize == 0) || ((SecurityCell->DescriptorLength + FIELD_OFFSET(CM_KEY_SECURITY, Descriptor)) > BiggestSize) ) {
BiggestSize = SecurityCell->DescriptorLength + FIELD_OFFSET(CM_KEY_SECURITY, Descriptor);
}
TotalSecuritySize += (SecurityCell->DescriptorLength + FIELD_OFFSET(CM_KEY_SECURITY, Descriptor));
#endif
if (NextCell != ListAnchor) {
//
// Check to make sure that our Blink points to where we just
// came from.
//
if (SecurityCell->Blink != LastCell) {
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC," Invalid Blink (%08lx) on security cell %08lx\n",SecurityCell->Blink, NextCell));
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC," should point to %08lx\n", LastCell));
return(FALSE);
}
}
CmKdPrintEx((DPFLTR_CONFIG_ID,CML_SEC,"CmpValidSD: SD shared by %d nodes\n",SecurityCell->ReferenceCount));
if (!SeValidSecurityDescriptor(SecurityCell->DescriptorLength, &SecurityCell->Descriptor)) {
#if DBG
CmpDumpSecurityDescriptor(&SecurityCell->Descriptor,"INVALID DESCRIPTOR");
#endif
goto YankSD;
}
//
// cache this security cell; now that we know it is valid
//
if( BuildSecurityCache == TRUE ) {
if( !NT_SUCCESS(CmpAddSecurityCellToCache ( (PCMHIVE)Hive,NextCell,TRUE) ) ) {
return FALSE;
}
} else {
//
// just check this cell is there
//
ULONG Index;
if( CmpFindSecurityCellCacheIndex ((PCMHIVE)Hive,NextCell,&Index) == FALSE ) {
//
// bad things happened; maybe an error in our caching code?
//
return FALSE;
}
}
LastCell = NextCell;
NextCell = SecurityCell->Flink;
} while ( NextCell != ListAnchor );
#ifdef HIVE_SECURITY_STATS
#ifndef _CM_LDR_
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\t NumberOfCells \t = %20lu (%8lx) \n",NoOfCells,NoOfCells);
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\t SmallestCellSize \t = %20lu (%8lx) \n",SmallestSize,SmallestSize);
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\t BiggestCellSize \t = %20lu (%8lx) \n",BiggestSize,BiggestSize);
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\t TotalSecuritySize\t = %20lu (%8lx) \n",TotalSecuritySize,TotalSecuritySize);
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\t HiveLength \t = %20lu (%8lx) \n",Hive->BaseBlock->Length,Hive->BaseBlock->Length);
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"\n");
#endif //_CM_LDR_
#endif
if( BuildSecurityCache == TRUE ) {
//
// adjust the size of the cache in case we allocated too much
//
CmpAdjustSecurityCacheSize ( (PCMHIVE)Hive );
#ifdef HIVE_SECURITY_STATS
{
ULONG Duplicates;
Duplicates = CmpCheckForSecurityDuplicates((PCMHIVE)Hive);
if( Duplicates ) {
#ifndef _CM_LDR_
DbgPrintEx(DPFLTR_CONFIG_ID,DPFLTR_TRACE_LEVEL,"Hive %p %lu security cells duplicated !!!\n",Hive,Duplicates);
#endif //_CM_LDR_
}
}
#endif
}
return(TRUE);
}