Skip to content

Commit

Permalink
[SDK][CMLIB] Implement registry check validation
Browse files Browse the repository at this point in the history
Description to be added...
CORE-9195
CORE-6762
  • Loading branch information
GeoB99 committed Jul 10, 2022
1 parent ba1269b commit 21b0eca
Show file tree
Hide file tree
Showing 6 changed files with 299 additions and 38 deletions.
27 changes: 0 additions & 27 deletions ntoskrnl/config/cmcheck.c

This file was deleted.

10 changes: 0 additions & 10 deletions ntoskrnl/include/internal/cm.h
Expand Up @@ -562,16 +562,6 @@ CmpCompareNewValueDataAgainstKCBCache(
IN ULONG DataSize
);

//
// Registry Validation Functions
//
ULONG
NTAPI
CmCheckRegistry(
IN PCMHIVE Hive,
IN ULONG Flags
);

//
// Hive List Routines
//
Expand Down
1 change: 0 additions & 1 deletion ntoskrnl/ntos.cmake
Expand Up @@ -48,7 +48,6 @@ list(APPEND SOURCE
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmalloc.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmapi.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmboot.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmcheck.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmconfig.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmcontrl.c
${REACTOS_SOURCE_DIR}/ntoskrnl/config/cmdata.c
Expand Down
1 change: 1 addition & 0 deletions sdk/lib/cmlib/CMakeLists.txt
Expand Up @@ -4,6 +4,7 @@ add_definitions(
-DNASSERT)

list(APPEND SOURCE
cmcheck.c
cminit.c
cmindex.c
cmkeydel.c
Expand Down
234 changes: 234 additions & 0 deletions sdk/lib/cmlib/cmcheck.c
@@ -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;
}
64 changes: 64 additions & 0 deletions sdk/lib/cmlib/cmlib.h
Expand Up @@ -211,6 +211,42 @@

#define CMAPI NTAPI

//
// Check Registry status type definition
//
#define CM_CHECK_REGISTRY_STATUS ULONG

//
// Check Registry flags
//
#define CM_CHECK_REGISTRY_PURGE 0x1
#define CM_CHECK_REGISTRY_MANDATORY_PURGE 0x2
#define CM_CHECK_REGISTRY_BOOTLOADER_PURGE 0x4
#define CM_CHECK_REGISTRY_SYSTEM_PURGE 0x8
#define CM_CHECK_REGISTRY_VALIDATE_HIVE 0x10

#define CM_CHECK_REGISTRY_VALID_FLAGS (CM_CHECK_REGISTRY_PURGE | \
CM_CHECK_REGISTRY_MANDATORY_PURGE | \
CM_CHECK_REGISTRY_BOOTLOADER_PURGE | \
CM_CHECK_REGISTRY_SYSTEM_PURGE | \
CM_CHECK_REGISTRY_VALIDATE_HIVE)

//
// Check Registry success macro
//
#define CM_CHECK_REGISTRY_SUCCESS(StatusCode) ((ULONG)(StatusCode) >= 0)

//
// Check Registry status codes
//
#define CM_CHECK_REGISTRY_GOOD 0
#define CM_CHECK_REGISTRY_SD_INVALID 1000
#define CM_CHECK_REGISTRY_HIVE_CORRUPT_SIGNATURE 2000
#define CM_CHECK_REGISTRY_BIN_HEADER_CORRUPT 3000
#define CM_CHECK_REGISTRY_FREE_CELL_EXCEEDS_BIN_SIZE 3010
#define CM_CHECK_REGISTRY_ALLOC_CELL_EXCEEDS_BIN_SIZE 3020
#define CM_CHECK_REGISTRY_BAD_CELL_IN_BIN 3030

#include <wine/unicode.h>
#include <wchar.h>
#include "hivedata.h"
Expand Down Expand Up @@ -496,6 +532,34 @@ CmPrepareHive(

/* NT-style Public Cm functions */

//
// Check Registry Routines
//
BOOLEAN
NTAPI
CmpValidateSDsOfHive(
_In_ PHHIVE Hive,
_Out_ PBOOLEAN SecurityDefaulted);

CM_CHECK_REGISTRY_STATUS
NTAPI
HvValidateBin(
_In_ PHBIN Bin,
_In_ PHHIVE Hive,
_In_ ULONG StorageIndex,
_In_ ULONG StorageLength);

CM_CHECK_REGISTRY_STATUS
NTAPI
HvValidateHive(
_In_ PHHIVE Hive);

CM_CHECK_REGISTRY_STATUS
NTAPI
CmCheckRegistry(
_In_ PCMHIVE RegistryHive,
_In_ ULONG Flags);

//
// Cell Index Routines
//
Expand Down

0 comments on commit 21b0eca

Please sign in to comment.