diff --git a/sdk/xtdk/xtstatus.h b/sdk/xtdk/xtstatus.h index 61ba7d6..3ed9d9d 100644 --- a/sdk/xtdk/xtstatus.h +++ b/sdk/xtdk/xtstatus.h @@ -60,6 +60,7 @@ #define STATUS_TIMEOUT ((XTSTATUS) 0x00000102L) #define STATUS_PENDING ((XTSTATUS) 0x00000103L) #define STATUS_REPARSE ((XTSTATUS) 0x00000104L) +#define STATUS_DATATYPE_MISALIGNMENT ((XTSTATUS) 0x80000002L) #define STATUS_WAKE_SYSTEM_DEBUGGER ((XTSTATUS) 0x80000007L) #define STATUS_END_OF_MEDIA ((XTSTATUS) 0x8000001EL) #define STATUS_RESOURCE_LOCKED ((XTSTATUS) 0xC0000000L) diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index db6f401..b7d7b17 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -85,6 +85,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/mm/paging.cc ${XTOSKRNL_SOURCE_DIR}/mm/pfn.cc ${XTOSKRNL_SOURCE_DIR}/mm/pool.cc + ${XTOSKRNL_SOURCE_DIR}/mm/probe.cc ${XTOSKRNL_SOURCE_DIR}/mm/pte.cc ${XTOSKRNL_SOURCE_DIR}/mm/quota.cc ${XTOSKRNL_SOURCE_DIR}/po/idle.cc diff --git a/xtoskrnl/includes/mm.hh b/xtoskrnl/includes/mm.hh index cdbf218..1d41839 100644 --- a/xtoskrnl/includes/mm.hh +++ b/xtoskrnl/includes/mm.hh @@ -24,6 +24,7 @@ #include #include #include +#include #include #include diff --git a/xtoskrnl/includes/mm/probe.hh b/xtoskrnl/includes/mm/probe.hh new file mode 100644 index 0000000..f4e9875 --- /dev/null +++ b/xtoskrnl/includes/mm/probe.hh @@ -0,0 +1,44 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/includes/mm/probe.hh + * DESCRIPTION: Memory Manager read/write probe support + * DEVELOPERS: Aiken Harris + */ + +#ifndef __XTOSKRNL_MM_PROBE_HH +#define __XTOSKRNL_MM_PROBE_HH + +#include + + +/* Memory Manager */ +namespace MM +{ + class Probe + { + public: + STATIC XTAPI VOID ProbeForRead(IN CONST PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment); + STATIC XTAPI VOID ProbeForReadArray(IN CONST PVOID Array, + IN ULONG ItemSize, + IN ULONG ItemCount, + IN ULONG Alignment); + STATIC XTAPI VOID ProbeForReadStructure(IN CONST PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment); + STATIC XTAPI VOID ProbeForWrite(IN PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment); + STATIC XTAPI VOID ProbeForWriteArray(IN OUT PVOID Array, + IN ULONG ItemSize, + IN ULONG ItemCount, + IN ULONG Alignment); + STATIC XTAPI VOID ProbeForWriteStructure(IN PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment); + }; +} + +#endif /* __XTOSKRNL_MM_PROBE_HH */ diff --git a/xtoskrnl/mm/probe.cc b/xtoskrnl/mm/probe.cc new file mode 100644 index 0000000..d15f186 --- /dev/null +++ b/xtoskrnl/mm/probe.cc @@ -0,0 +1,278 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/mm/probe.cc + * DESCRIPTION: Memory Manager read/write probe support + * DEVELOPERS: Aiken Harris + */ + +#include + + +/** +* Probes a generic memory buffer for read accessibility. +* +* @param Address +* Supplies the base address of the buffer to probe. +* +* @param Size +* Supplies the size of the buffer in bytes. +* +* @param Alignment +* Supplies the required data alignment (must be 1, 2, 4, 8, or 16). +* +* @return This routine does not return any value. +* +* @since XT 1.0 +*/ +XTAPI +VOID +MM::Probe::ProbeForRead(IN CONST PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment) +{ + /* Check if the buffer size is non-zero */ + if(Size) + { + /* Check if the base address violates the required alignment */ + if(((ULONG_PTR)Address & (Alignment - 1)) != 0) + { + /* Raise datatype misalignment exception */ + RTL::Exception::RaiseStatus(STATUS_DATATYPE_MISALIGNMENT); + } + + /* Verify that the end address do not overflow and remains within user space */ + if((((ULONG_PTR)Address + Size) < (ULONG_PTR)Address) || + (((ULONG_PTR)Address + Size) > MM::Paging::GetUserProbeAddress())) + { + /* Raise access violation exception */ + RTL::Exception::RaiseStatus(STATUS_ACCESS_VIOLATION); + } + } +} + +/** + * Probes an array of fixed-size items for read accessibility. + * + * @param Array + * Supplies the base address of the array. + * + * @param ItemSize + * Supplies the size of a single array element in bytes. + * + * @param ItemCount + * Supplies the total number of elements in the array. + * + * @param Alignment + * Supplies the required array alignment (must be 1, 2, 4, 8, or 16). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Probe::ProbeForReadArray(IN CONST PVOID Array, + IN ULONG ItemSize, + IN ULONG ItemCount, + IN ULONG Alignment) +{ + ULONG ArraySize; + + /* Calculate total array size */ + ArraySize = ItemSize * ItemCount; + + /* Check for integer overflow */ + if((ItemSize != 0) && (ArraySize / ItemSize != ItemCount)) + { + RTL::Exception::RaiseStatus(STATUS_INVALID_PARAMETER); + } + + /* Perform boundary and alignment verification */ + ProbeForRead(Array, ArraySize, Alignment); +} + +/** + * Probes a structure for read accessibility. + * + * @param Address + * Supplies the base address of the structure to probe. + * + * @param Size + * Supplies the total size of the structure in bytes. + * + * @param Alignment + * Supplies the required structure alignment (must be 1, 2, 4, 8, or 16). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Probe::ProbeForReadStructure(IN CONST PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment) +{ + /* Check if the buffer size is zero or greater than 64k */ + if((Size == 0) || (Size > 0x10000)) + { + /* Perform boundary and alignment verification */ + ProbeForRead(Address, Size, Alignment); + } + else + { + /* Check if the base address violates the required alignment */ + if(((ULONG_PTR)Address & (Alignment - 1)) != 0) + { + /* Raise datatype misalignment exception */ + RTL::Exception::RaiseStatus(STATUS_DATATYPE_MISALIGNMENT); + } + + /* Check address space boundary */ + if((ULONG_PTR)Address >= (ULONG_PTR)MM::Paging::GetUserProbeAddress()) + { + /* Force access violation on the invalid probe boundary */ + *(VOLATILE PULONG CONST)MM::Paging::GetUserProbeAddress() = 0; + } + } +} + +/** + * Probes a generic memory buffer for write accessibility. + * + * @param Address + * Supplies the base address of the buffer to probe. + * + * @param Size + * Supplies the size of the buffer in bytes. + * + * @param Alignment + * Supplies the required data alignment (must be 1, 2, 4, 8, or 16). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Probe::ProbeForWrite(IN PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment) +{ + ULONG_PTR CurrentAddress, LastAddress; + + /* Check if the buffer size is non-zero */ + if(Size) + { + /* Perform boundary and alignment verification */ + ProbeForRead(Address, Size, Alignment); + + /* Store the current address */ + CurrentAddress = (ULONG_PTR)Address; + + /* Calculate the end boundary of the requested buffer */ + LastAddress = CurrentAddress + Size - 1; + LastAddress = (LastAddress & ~(MM_PAGE_SIZE - 1)) + MM_PAGE_SIZE; + + /* Loop through each page in the range */ + while(CurrentAddress < LastAddress) + { + /* Touch the page with a read-write cycle */ + *(VOLATILE PCHAR)CurrentAddress = *(volatile CHAR*)CurrentAddress; + + /* Advance to the next page */ + CurrentAddress = (CurrentAddress & ~(MM_PAGE_SIZE - 1)) + MM_PAGE_SIZE; + } + } +} + +/** + * Probes an array of fixed-size items for write accessibility. + * + * @param Array + * Supplies the base address of the array. + * + * @param ItemSize + * Supplies the size of a single array element in bytes. + * + * @param ItemCount + * Supplies the total number of elements in the array. + * + * @param Alignment + * Supplies the required data alignment (must be 1, 2, 4, 8, or 16). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Probe::ProbeForWriteArray(IN OUT PVOID Array, + IN ULONG ItemSize, + IN ULONG ItemCount, + IN ULONG Alignment) +{ + ULONG ArraySize; + + /* Calculate total array size */ + ArraySize = ItemSize * ItemCount; + + /* Check for integer overflow */ + if((ItemSize != 0) && (ArraySize / ItemSize != ItemCount)) + { + RTL::Exception::RaiseStatus(STATUS_INVALID_PARAMETER); + } + + /* Perform write accessibility verification */ + ProbeForWrite(Array, ArraySize, Alignment); +} + + + + +/** + * Probes a structure for write accessibility. + * + * @param Address + * Supplies the base address of the structure to probe. + * + * @param Size + * Supplies the total size of the structure in bytes. + * + * @param Alignment + * Supplies the required structure alignment (must be 1, 2, 4, 8, or 16). + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTAPI +VOID +MM::Probe::ProbeForWriteStructure(IN PVOID Address, + IN SIZE_T Size, + IN ULONG Alignment) +{ + /* Delegate fast-path boundary and alignment verification to the Read probe (DRY) */ + ProbeForReadStructure(Address, Size, Alignment); + + /* Check if the buffer size is zero or exceeds the page size */ + if((Size == 0) || (Size >= MM_PAGE_SIZE)) + { + /* Perform write accessibility verification */ + ProbeForWrite(Address, Size, Alignment); + } + else + { + /* Touch the first byte to verify write access */ + *(VOLATILE PUCHAR)Address = *(VOLATILE PUCHAR)Address; + + /* Check if the buffer size exceeds the alignment */ + if(Size > Alignment) + { + /* Touch the last byte to ensure full structure spans valid memory */ + ((VOLATILE PUCHAR)Address)[(Size - 1) & ~(SIZE_T)(Alignment - 1)] = + ((VOLATILE PUCHAR)Address)[(Size - 1) & ~(SIZE_T)(Alignment - 1)]; + } + } +}