Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[SDK][CMLIB] Implement registry check validation
Description to be added... CORE-9195 CORE-6762
- Loading branch information
Showing
6 changed files
with
299 additions
and
38 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,6 +4,7 @@ add_definitions( | |
-DNASSERT) | ||
|
||
list(APPEND SOURCE | ||
cmcheck.c | ||
cminit.c | ||
cmindex.c | ||
cmkeydel.c | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,234 @@ | ||
/* | ||
* PROJECT: ReactOS Kernel | ||
* LICENSE: GPL-2.0-or-later (https://spdx.org/licenses/GPL-2.0-or-later) | ||
* PURPOSE: Configuration Manager Library - Registry Validation | ||
* COPYRIGHT: Copyright 2022 George Bișoc <george.bisoc@reactos.org> | ||
*/ | ||
|
||
/* INCLUDES ******************************************************************/ | ||
|
||
#include "cmlib.h" | ||
#define NDEBUG | ||
#include <debug.h> | ||
|
||
/* DEFINES ******************************************************************/ | ||
|
||
#define GET_HHIVE(CmHive) (&((CmHive)->Hive)) | ||
#define GET_HHIVE_BIN(Hive, StorageIndex, BlockIndex) ((PHBIN)Hive->Storage[StorageIndex].BlockList[BlockIndex].BinAddress) | ||
#define GET_CELL_BIN(Bin) ((PHCELL)(Bin +1)) | ||
|
||
#if !defined(CMLIB_HOST) && !defined(_BLDR_) | ||
extern PCMHIVE CmiVolatileHive; | ||
#endif | ||
|
||
/* PRIVATE FUNCTIONS **********************************************************/ | ||
|
||
BOOLEAN | ||
NTAPI | ||
CmpValidateSDsOfHive( | ||
_In_ PHHIVE Hive, | ||
_Out_ PBOOLEAN SecurityDefaulted) | ||
{ | ||
// TODO | ||
UNREFERENCED_PARAMETER(Hive); | ||
UNREFERENCED_PARAMETER(SecurityDefaulted); | ||
return TRUE; | ||
} | ||
|
||
/* PUBLIC FUNCTIONS ***********************************************************/ | ||
|
||
CM_CHECK_REGISTRY_STATUS | ||
NTAPI | ||
HvValidateBin( | ||
_In_ PHBIN Bin, | ||
_In_ PHHIVE Hive, | ||
_In_ ULONG StorageIndex, | ||
_In_ ULONG StorageLength) | ||
{ | ||
HCELL_INDEX FileOffset; | ||
PHCELL Cell, Basket; | ||
|
||
/* Sanity checks */ | ||
ASSERT(Bin); | ||
ASSERT(Hive); | ||
ASSERT(StorageLength != 0); | ||
|
||
/* | ||
* The block offset is the current storage space | ||
* times the block size. | ||
*/ | ||
FileOffset = Hive->Storage[StorageIndex].Length * | ||
HBLOCK_SIZE; | ||
|
||
/* Ensure that this bin we got has valid header */ | ||
if (Bin->Signature != HV_HBIN_SIGNATURE || | ||
Bin->Size > StorageLength || | ||
Bin->FileOffset != FileOffset) | ||
{ | ||
DPRINT1("HvValidateBin(): The bin's header is corrupt!\n"); | ||
return CM_CHECK_REGISTRY_BIN_HEADER_CORRUPT; | ||
} | ||
|
||
/* | ||
* Walk over all the cells from this bin and | ||
* validate that they're consistent with the bin. | ||
* Namely we want that each cell from this bin doesn't | ||
* have a bogus size. | ||
*/ | ||
Cell = GET_CELL_BIN(Bin); | ||
Basket = (PHCELL)((PULONG)Bin + Bin->Size); | ||
while (Cell < Basket) | ||
{ | ||
/* Does this cell have some free space? */ | ||
if (Cell->Size > 0) | ||
{ | ||
/* | ||
* This cell indeed is free, check that | ||
* the size of this cell is not bogus. | ||
*/ | ||
if (Cell->Size > Bin->Size) | ||
{ | ||
/* | ||
* This cell has too much free space that | ||
* exceeds the boundary of the bin size. | ||
*/ | ||
DPRINT1("HvValidateBin(): The free cell exceeds the bin size (cell: %p, cell size %d, bin size %lu)\n", | ||
Cell, Cell->Size, Bin->Size); | ||
return CM_CHECK_REGISTRY_FREE_CELL_EXCEEDS_BIN_SIZE; | ||
} | ||
} | ||
else if (Cell->Size < 0) | ||
{ | ||
/* | ||
* This cell is allocated, make sure that | ||
* the size of this cell is not bogus. | ||
*/ | ||
if (abs(Cell->Size) > Bin->Size) | ||
{ | ||
/* | ||
* This cell allocated too much space | ||
* that exceeds the boundary of the | ||
* bin size. | ||
*/ | ||
DPRINT1("HvValidateBin(): The allocated cell exceeds the bin size (cell: %p, cell size %d, bin size %lu)\n", | ||
Cell, abs(Cell->Size), Bin->Size); | ||
return CM_CHECK_REGISTRY_ALLOC_CELL_EXCEEDS_BIN_SIZE; | ||
} | ||
} | ||
else | ||
{ | ||
/* | ||
* If we reach this path then the cell is | ||
* neither allocated nor free (Size == 0). | ||
* Such a cell of this kind is a no go for | ||
* this bin so bail out. | ||
*/ | ||
DPRINT1("HvValidateBin(): This cell is neither allocated nor free!\n"); | ||
return CM_CHECK_REGISTRY_BAD_CELL_IN_BIN; | ||
} | ||
|
||
/* Go to the next cell */ | ||
Cell = (PHCELL)((PULONG)Cell + abs(Cell->Size)); | ||
} | ||
|
||
return CM_CHECK_REGISTRY_GOOD; | ||
} | ||
|
||
CM_CHECK_REGISTRY_STATUS | ||
NTAPI | ||
HvValidateHive( | ||
_In_ PHHIVE Hive) | ||
{ | ||
ULONG CmStatusCode; | ||
ULONG StorageIndex; | ||
ULONG BlockIndex; | ||
ULONG StorageLength; | ||
PHBIN Bin; | ||
|
||
/* Sanity check */ | ||
ASSERT(Hive); | ||
|
||
/* Is the hive signature valid? */ | ||
if (Hive->Signature != HV_HHIVE_SIGNATURE) | ||
{ | ||
/* Someone sent Fat Man type of nuclear bomb to this hive, bail out */ | ||
DPRINT1("HvValidateHive(): Hive's signature corrupted (signature %lu)\n", Hive->Signature); | ||
return CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE; | ||
} | ||
|
||
/* | ||
* Now loop each bin in the storage of this | ||
* hive. | ||
*/ | ||
for (StorageIndex = 0; StorageIndex < Hive->StorageTypeCount; StorageIndex++) | ||
{ | ||
for (BlockIndex = 0; BlockIndex < Hive->Storage[StorageIndex].Length; BlockIndex++) | ||
{ | ||
/* Go to the next if this bin does not exist */ | ||
if (Hive->Storage[StorageIndex].BlockList[BlockIndex].BinAddress == (ULONG_PTR)NULL) | ||
{ | ||
continue; | ||
} | ||
|
||
/* Get the storage length at this index */ | ||
StorageLength = Hive->Storage[StorageIndex].Length; | ||
|
||
/* Capture this bin and begin validate its contents */ | ||
Bin = GET_HHIVE_BIN(Hive, StorageIndex, BlockIndex); | ||
CmStatusCode = HvValidateBin(Bin, Hive, StorageIndex, StorageLength); | ||
if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode)) | ||
{ | ||
DPRINT1("HvValidateHive(): This bin is not valid (bin %p)\n", Bin); | ||
return CmStatusCode; | ||
} | ||
} | ||
} | ||
|
||
return CM_CHECK_REGISTRY_GOOD; | ||
} | ||
|
||
CM_CHECK_REGISTRY_STATUS | ||
NTAPI | ||
CmCheckRegistry( | ||
_In_ PCMHIVE RegistryHive, | ||
_In_ ULONG Flags) | ||
{ | ||
ULONG CmStatusCode; | ||
PHHIVE Hive; | ||
|
||
/* Make sure the submitted flag is valid */ | ||
ASSERT(Flags & CM_CHECK_REGISTRY_VALID_FLAGS); | ||
|
||
#if !defined(CMLIB_HOST) && !defined(_BLDR_) | ||
/* | ||
* If this CM hive that we got is a volatile | ||
* hive (aka master hive which is what it's called | ||
* on Windows) then registry validation checks is | ||
* not necessary. | ||
*/ | ||
if (RegistryHive == CmiVolatileHive) | ||
{ | ||
DPRINT("CmCheckRegistry(): This is master registry hive, don't do anything!\n"); | ||
return CM_CHECK_REGISTRY_GOOD; | ||
} | ||
#endif | ||
|
||
/* | ||
* Obtain the hive and check if the caller wants | ||
* that the hive to be validated. | ||
*/ | ||
Hive = GET_HHIVE(RegistryHive); | ||
if (Flags & CM_CHECK_REGISTRY_VALIDATE_HIVE) | ||
{ | ||
CmStatusCode = HvValidateHive(Hive); | ||
if (!CM_CHECK_REGISTRY_SUCCESS(CmStatusCode)) | ||
{ | ||
DPRINT1("CmCheckRegistry(): The hive is not valid (hive pointer %p)!\n", Hive); | ||
return CmStatusCode; | ||
} | ||
} | ||
|
||
// TODO | ||
|
||
return CM_CHECK_REGISTRY_GOOD; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters