diff --git a/sdk/xtdk/ketypes.h b/sdk/xtdk/ketypes.h index 4e966e5..d0ac21b 100644 --- a/sdk/xtdk/ketypes.h +++ b/sdk/xtdk/ketypes.h @@ -198,6 +198,14 @@ typedef enum _WAIT_TYPE WaitAny } WAIT_TYPE, *PWAIT_TYPE; +/* Kernel UBSAN data types enumeration list */ +typedef enum _KUBSAN_DATA_TYPE +{ + DataTypeInt, + DataTypeFloat, + DataTypeUnknown = 0xFFFF +} KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; + /* Kernel routine callbacks */ typedef EXCEPTION_DISPOSITION (XTCDECL *PEXCEPTION_ROUTINE)(IN PEXCEPTION_RECORD ExceptionRecord, IN PVOID EstablisherFrame, IN OUT PCONTEXT ContextRecord, IN OUT PVOID DispatcherContext); typedef VOID (XTAPI *PKDEFERRED_ROUTINE)(IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2); @@ -551,4 +559,90 @@ typedef struct _SYSTEM_RESOURCE_FRAMEBUFFER } Pixels; } SYSTEM_RESOURCE_FRAMEBUFFER, *PSYSTEM_RESOURCE_FRAMEBUFFER; +/* Kernel UBSAN source location structure definition */ +typedef struct _KUBSAN_SOURCE_LOCATION +{ + PCCHAR FileName; + union + { + ULONG Reported; + struct + { + UINT Line; + UINT Column; + }; + }; +} KUBSAN_SOURCE_LOCATION, *PKUBSAN_SOURCE_LOCATION; + +/* Kernel UBSAN type descriptor structure definition */ +typedef struct _KUBSAN_TYPE_DESCRIPTOR +{ + USHORT DataType; + USHORT TypeInfo; + CHAR TypeName[1]; +} KUBSAN_TYPE_DESCRIPTOR, *PKUBSAN_TYPE_DESCRIPTOR; + +/* Kernel UBSAN float cast overflow data structure definition */ +typedef struct _KUBSAN_FLOAT_CAST_OVERFLOW_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR LhsType; + PKUBSAN_TYPE_DESCRIPTOR RhsType; +} KUBSAN_FLOAT_CAST_OVERFLOW_DATA, *PKUBSAN_FLOAT_CAST_OVERFLOW_DATA; + +/* Kernel UBSAN function type mismatch data structure definition */ +typedef struct _KUBSAN_FUNCTION_TYPE_MISMATCH_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR Type; +} KUBSAN_FUNCTION_TYPE_MISMATCH_DATA, *PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA; + +/* Kernel UBSAN invalid builtin data structure definition */ +typedef struct _KUBSAN_INVALID_BUILTIN_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + UCHAR Kind; +} KUBSAN_INVALID_BUILTIN_DATA, *PKUBSAN_INVALID_BUILTIN_DATA; + +/* Kernel UBSAN shift out of bounds data structure definition */ +typedef struct _KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR LhsType; + PKUBSAN_TYPE_DESCRIPTOR RhsType; +} KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA, *PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA; + +/* Kernel UBSAN out of bounds data structure definition */ +typedef struct _KUBSAN_OUT_OF_BOUNDS_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR ArrayType; + PKUBSAN_TYPE_DESCRIPTOR IndexType; +} KUBSAN_OUT_OF_BOUNDS_DATA, *PKUBSAN_OUT_OF_BOUNDS_DATA; + +/* Kernel UBSAN overflow data structure definition */ +typedef struct _KUBSAN_OVERFLOW_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR Type; +} KUBSAN_OVERFLOW_DATA, *PKUBSAN_OVERFLOW_DATA; + +/* Kernel UBSAN type mismatch data structure definition */ +typedef struct _KUBSAN_TYPE_MISMATCH_DATA +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR Type; + ULONG Alignment; + UCHAR TypeCheckKind; +} KUBSAN_TYPE_MISMATCH_DATA, *PKUBSAN_TYPE_MISMATCH_DATA; + +/* Kernel UBSAN type mismatch data structure definition */ +typedef struct _KUBSAN_TYPE_MISMATCH_DATA_V1 +{ + KUBSAN_SOURCE_LOCATION Location; + PKUBSAN_TYPE_DESCRIPTOR Type; + UCHAR LogAlignment; + UCHAR TypeCheckKind; +} KUBSAN_TYPE_MISMATCH_DATA_V1, *PKUBSAN_TYPE_MISMATCH_DATA_V1; + #endif /* __XTDK_KEFUNCS_H */ diff --git a/sdk/xtdk/xtstruct.h b/sdk/xtdk/xtstruct.h index 28206f1..21b7464 100644 --- a/sdk/xtdk/xtstruct.h +++ b/sdk/xtdk/xtstruct.h @@ -47,6 +47,7 @@ typedef enum _KOBJECTS KOBJECTS, *PKOBJECTS; typedef enum _KPROCESS_STATE KPROCESS_STATE, *PKPROCESS_STATE; typedef enum _KTHREAD_STATE KTHREAD_STATE, *PKTHREAD_STATE; typedef enum _KTIMER_TYPE KTIMER_TYPE, *PKTIMER_TYPE; +typedef enum _KUBSAN_DATA_TYPE KUBSAN_DATA_TYPE, *PKUBSAN_DATA_TYPE; typedef enum _LOADER_MEMORY_TYPE LOADER_MEMORY_TYPE, *PLOADER_MEMORY_TYPE; typedef enum _MODE MODE, *PMODE; typedef enum _SYSTEM_FIRMWARE_TYPE SYSTEM_FIRMWARE_TYPE, *PSYSTEM_FIRMWARE_TYPE; @@ -248,6 +249,16 @@ typedef struct _KSERVICE_DESCRIPTOR_TABLE KSERVICE_DESCRIPTOR_TABLE, *PKSERVICE_ typedef struct _KSPIN_LOCK_QUEUE KSPIN_LOCK_QUEUE, *PKSPIN_LOCK_QUEUE; typedef struct _KTHREAD KTHREAD, *PKTHREAD; typedef struct _KTIMER KTIMER, *PKTIMER; +typedef struct _KUBSAN_FLOAT_CAST_OVERFLOW_DATA KUBSAN_FLOAT_CAST_OVERFLOW_DATA, *PKUBSAN_FLOAT_CAST_OVERFLOW_DATA; +typedef struct _KUBSAN_FUNCTION_TYPE_MISMATCH_DATA KUBSAN_FUNCTION_TYPE_MISMATCH_DATA, *PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA; +typedef struct _KUBSAN_INVALID_BUILTIN_DATA KUBSAN_INVALID_BUILTIN_DATA, *PKUBSAN_INVALID_BUILTIN_DATA; +typedef struct _KUBSAN_OUT_OF_BOUNDS_DATA KUBSAN_OUT_OF_BOUNDS_DATA, *PKUBSAN_OUT_OF_BOUNDS_DATA; +typedef struct _KUBSAN_OVERFLOW_DATA KUBSAN_OVERFLOW_DATA, *PKUBSAN_OVERFLOW_DATA; +typedef struct _KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA KUBSAN_SHIFT_OUT_OF_BOUNDS_DATA, *PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA; +typedef struct _KUBSAN_SOURCE_LOCATION KUBSAN_SOURCE_LOCATION, *PKUBSAN_SOURCE_LOCATION; +typedef struct _KUBSAN_TYPE_DESCRIPTOR KUBSAN_TYPE_DESCRIPTOR, *PKUBSAN_TYPE_DESCRIPTOR; +typedef struct _KUBSAN_TYPE_MISMATCH_DATA KUBSAN_TYPE_MISMATCH_DATA, *PKUBSAN_TYPE_MISMATCH_DATA; +typedef struct _KUBSAN_TYPE_MISMATCH_DATA_V1 KUBSAN_TYPE_MISMATCH_DATA_V1, *PKUBSAN_TYPE_MISMATCH_DATA_V1; typedef struct _KWAIT_BLOCK KWAIT_BLOCK, *PKWAIT_BLOCK; typedef struct _LDR_DATA_TABLE_ENTRY LDR_DATA_TABLE_ENTRY, *PLDR_DATA_TABLE_ENTRY; typedef struct _LIST_ENTRY LIST_ENTRY, *PLIST_ENTRY; diff --git a/xtoskrnl/CMakeLists.txt b/xtoskrnl/CMakeLists.txt index 2703161..ffdf12c 100644 --- a/xtoskrnl/CMakeLists.txt +++ b/xtoskrnl/CMakeLists.txt @@ -30,6 +30,7 @@ list(APPEND XTOSKRNL_SOURCE ${XTOSKRNL_SOURCE_DIR}/ke/kprocess.c ${XTOSKRNL_SOURCE_DIR}/ke/krnlinit.c ${XTOSKRNL_SOURCE_DIR}/ke/kthread.c + ${XTOSKRNL_SOURCE_DIR}/ke/kubsan.c ${XTOSKRNL_SOURCE_DIR}/ke/panic.c ${XTOSKRNL_SOURCE_DIR}/ke/runlevel.c ${XTOSKRNL_SOURCE_DIR}/ke/semphore.c diff --git a/xtoskrnl/includes/globals.h b/xtoskrnl/includes/globals.h index 13339de..f692aef 100644 --- a/xtoskrnl/includes/globals.h +++ b/xtoskrnl/includes/globals.h @@ -57,6 +57,9 @@ EXTERN LIST_ENTRY KepSystemResourcesListHead; /* Kernel system resources lock */ EXTERN KSPIN_LOCK KepSystemResourcesLock; +/* Kernel UBSAN active frame flag */ +EXTERN BOOLEAN KepUbsanActiveFrame; + /* Biggest free memory descriptor */ EXTERN PLOADER_MEMORY_DESCRIPTOR MmFreeDescriptor; diff --git a/xtoskrnl/includes/kei.h b/xtoskrnl/includes/kei.h index c4d6963..e64ca70 100644 --- a/xtoskrnl/includes/kei.h +++ b/xtoskrnl/includes/kei.h @@ -86,20 +86,115 @@ XTAPI VOID KeStartXtSystem(IN PKERNEL_INITIALIZATION_BLOCK Parameters); +XTCDECL +BOOLEAN +KepCheckUbsanReport(PKUBSAN_SOURCE_LOCATION Location); + +XTCDECL +VOID +KepEnterUbsanFrame(PKUBSAN_SOURCE_LOCATION Location, + PCCHAR Reason); + XTFASTCALL VOID KepExitDispatcher(IN KRUNLEVEL OldRunLevel); +XTCDECL +LONGLONG +KepGetSignedUbsanValue(PKUBSAN_TYPE_DESCRIPTOR Type, + PVOID Value); + XTAPI VOID KepGetSystemResource(IN SYSTEM_RESOURCE_TYPE ResourceType, IN BOOLEAN Acquire, OUT PSYSTEM_RESOURCE_HEADER *ResourceHeader); +XTCDECL +PCCHAR +KepGetUbsanTypeKind(UCHAR TypeCheckKind); + +XTCDECL +ULONGLONG +KepGetUnsignedUbsanValue(PKUBSAN_TYPE_DESCRIPTOR Type, + PVOID Value); + +XTCDECL +VOID +KepHandleUbsanDivisionOverflow(PKUBSAN_OVERFLOW_DATA Data, + PVOID Lhs, + PVOID Rhs); + +XTCDECL +VOID +KepHandleUbsanFloatCastOverflow(PKUBSAN_FLOAT_CAST_OVERFLOW_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs); + +XTCDECL +VOID +KepHandleUbsanFunctionTypeMismatch(PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer); + +XTCDECL +VOID +KepHandleUbsanIntegerOverflow(PKUBSAN_OVERFLOW_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs); + +XTCDECL +VOID +KepHandleUbsanInvalidBuiltin(PKUBSAN_INVALID_BUILTIN_DATA Data); + +XTCDECL +VOID +KepHandleUbsanMisalignedAccess(PKUBSAN_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer); + +XTCDECL +VOID +KepHandleUbsanNegateOverflow(PKUBSAN_OVERFLOW_DATA Data, + ULONG_PTR OldValue); + +XTCDECL +VOID +KepHandleUbsanNullPointerDereference(PKUBSAN_TYPE_MISMATCH_DATA Data); + +XTCDECL +VOID +KepHandleUbsanObjectSizeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer); + +XTCDECL +VOID +KepHandleUbsanOutOfBounds(PKUBSAN_OUT_OF_BOUNDS_DATA Data, + ULONG_PTR Index); + +XTCDECL +VOID +KepHandleUbsanPointerOverflow(PKUBSAN_OVERFLOW_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs); + +XTCDECL +VOID +KepHandleUbsanShiftOutOfBounds(PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs); + +XTCDECL +VOID +KepHandleUbsanTypeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer); + XTAPI VOID KepInitializeSystemResources(VOID); +XTCDECL +VOID +KepLeaveUbsanFrame(); + XTAPI VOID KepRemoveTimer(IN OUT PKTIMER Timer); diff --git a/xtoskrnl/ke/globals.c b/xtoskrnl/ke/globals.c index 28c6904..eb0a126 100644 --- a/xtoskrnl/ke/globals.c +++ b/xtoskrnl/ke/globals.c @@ -32,3 +32,6 @@ LIST_ENTRY KepSystemResourcesListHead; /* Kernel system resources lock */ KSPIN_LOCK KepSystemResourcesLock; + +/* Kernel UBSAN active frame flag */ +BOOLEAN KepUbsanActiveFrame = FALSE; diff --git a/xtoskrnl/ke/kubsan.c b/xtoskrnl/ke/kubsan.c new file mode 100644 index 0000000..db7b538 --- /dev/null +++ b/xtoskrnl/ke/kubsan.c @@ -0,0 +1,1048 @@ +/** + * PROJECT: ExectOS + * COPYRIGHT: See COPYING.md in the top level directory + * FILE: xtoskrnl/ke/kubsan.c + * DESCRIPTION: Kernel Undefined Behaviour Sanitizer (UBSAN) error reporting handler + * DEVELOPERS: Rafal Kupiec + */ + +#include + + +/** + * Checks whether handled UBSAN error should be reported. + * + * @param Location + * Supplies a pointer to the UBSAN location descriptor. + * + * @return This routine returns TRUE if UBSAN error should be reported, or FALSE otherwise. + * + * @since XT 1.0 + */ +XTCDECL +BOOLEAN +KepCheckUbsanReport(PKUBSAN_SOURCE_LOCATION Location) +{ + /* Make sure, this error should be reported */ + return !KepUbsanActiveFrame; +} + +/** + * Enters UBSAN frame and marks it as active. + * + * @param Location + * Supplies a pointer to the UBSAN location descriptor. + * + * @param Reason + * Supplies a pointer to the reason of the UBSAN failure. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepEnterUbsanFrame(PKUBSAN_SOURCE_LOCATION Location, + PCCHAR Reason) +{ + /* Enter UBSAN frame */ + KepUbsanActiveFrame = TRUE; + + /* Print generic error message to debug console */ + DebugPrint(L"UBSAN: Undefined behavior (%s) in %s:%d:%d\n", + Reason, Location->FileName, Location->Line, Location->Column); +} + +/** + * Gets signed value from UBSAN. + * + * @param Type + * Supplies a pointer to the UBSAN type descriptor. + * + * @param Value + * Supplies a pointer to the UBSAN value. + * + * @return This routine returns a 64-bit signed integer. + * + * @since XT 1.0 + */ +XTCDECL +LONGLONG +KepGetSignedUbsanValue(PKUBSAN_TYPE_DESCRIPTOR Type, + PVOID Value) +{ + ULONG BitWidth, ExtraBits; + ULONG_PTR LongValue; + + /* Calculate bit width of the type */ + BitWidth = 1 << (Type->TypeInfo >> 1); + + /* Check if inline integer */ + if(BitWidth <= sizeof(ULONG) * 8) + { + /* Calculate extra bits and return value */ + ExtraBits = sizeof(LONGLONG) * 8 - BitWidth; + LongValue = (ULONG_PTR)Value; + return ((LONGLONG)LongValue) << ExtraBits >> ExtraBits; + } + + /* Return 64-bit integer */ + return *(PLONGLONG)Value; +} + +/** + * Gets a string representation of the UBSAN type kind. + * + * @param TypeCheckKind + * Supplies a UBSAN type kind as a numeric value. + * + * @return This routine returns a string representation of the UBSAN type. + * + * @since XT 1.0 + */ +XTCDECL +PCCHAR +KepGetUbsanTypeKind(UCHAR TypeCheckKind) +{ + /* Get type kind name */ + switch(TypeCheckKind) + { + case 0: + return "Load of"; + case 1: + return "Store to"; + case 2: + return "Reference binding to"; + case 3: + return "Member access within"; + case 4: + return "Member call on"; + case 5: + return "Constructor call on"; + case 6: + return "Downcast of"; + case 7: + return "Downcast of"; + case 8: + return "Upcast of"; + case 9: + return "Cast to virtual base of"; + default: + return "Unrecognized failure code"; + } +} + +/** + * Gets unsigned value from UBSAN. + * + * @param Type + * Supplies a pointer to the UBSAN type descriptor. + * + * @param Value + * Supplies a pointer to the UBSAN value. + * + * @return This routine returns a 64-bit unsigned integer. + * + * @since XT 1.0 + */ +XTCDECL +ULONGLONG +KepGetUnsignedUbsanValue(PKUBSAN_TYPE_DESCRIPTOR Type, + PVOID Value) +{ + ULONG BitWidth; + + /* Calculate bit width of the type */ + BitWidth = 1 << (Type->TypeInfo >> 1); + + /* Check if inline integer */ + if(BitWidth <= sizeof(ULONG) * 8) + { + /* Return value */ + return (ULONG_PTR)Value; + } + + /* Return 64-bit integer */ + return *(PULONGLONG)Value; +} + +/** + * Handles the division overflow error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanDivisionOverflow(PKUBSAN_OVERFLOW_DATA Data, + PVOID Lhs, + PVOID Rhs) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Division-Overflow"); + + /* Check if signed type, which value is -1 */ + if((Data->Type->TypeInfo & 1) && (KepGetSignedUbsanValue(Data->Type, Rhs) == -1)) + { + /* Division by -1, print error message to debug console */ + DebugPrint(L"UBSAN: Division by -1 cannot be represented in type %s\n", Data->Type->TypeName); + } + else + { + /* Division by 0, print error message to debug console */ + DebugPrint(L"UBSAN: Division by zero\n"); + } + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the float cast overflow error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN float cast overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanFloatCastOverflow(PKUBSAN_FLOAT_CAST_OVERFLOW_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Float-Cast-Overflow"); + + /* Print error message to debug console */ + DebugPrint(L"Value of type %s is outside the range of type %s\n", Data->LhsType->TypeName, Data->RhsType->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the function type mismatch error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN function type mismatch data. + * + * @param Pointer + * Supplies pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanFunctionTypeMismatch(PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Float-Cast-Overflow"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: Indirect function call through %P address of a wrong type %s\n", + (PVOID)Pointer, Data->Type->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the integer overflow error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanIntegerOverflow(PKUBSAN_OVERFLOW_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Integer-Overflow"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: The result of an arithmetic operation cannot be represented in type %s\n", Data->Type->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the invalid builtin error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN invalid builtin data. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanInvalidBuiltin(PKUBSAN_INVALID_BUILTIN_DATA Data) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Invalid-Builtin"); + + /* Check kind of UBSAN error */ + if(Data->Kind == 0 || Data->Kind == 1) + { + /* Invalid ctz()/clz() parameter, print error message to debug console */ + DebugPrint(L"UBSAN: Passing zero to ctz() or clz() which is not a valid argument\n"); + } + else + { + /* Unknown kind, print error message to debug console */ + DebugPrint(L"UBSAN: Unknown kind %u\n", Data->Kind); + } + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the misaligned access error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN type mismatch data. + * + * @param Pointer + * Supplies a pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanMisalignedAccess(PKUBSAN_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Misaligned-Access"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: %s misaligned address %p for type %s which requires %ld byte alignment\n", + KepGetUbsanTypeKind(Data->TypeCheckKind), (PVOID)Pointer, Data->Type->TypeName, Data->Alignment); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the negate overflow error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param OldValue + * Supplies old value. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanNegateOverflow(PKUBSAN_OVERFLOW_DATA Data, + ULONG_PTR OldValue) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Negate-Overflow"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: Negation of %lu cannot be represented in type %s\n", OldValue, Data->Type->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + + +/** + * Handles the NULL pointer dereference error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN type mismatch data. + * + * @param Pointer + * Supplies a pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanNullPointerDereference(PKUBSAN_TYPE_MISMATCH_DATA Data) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "NULL-Pointer-Dereference"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: %s NULL pointer of type %s\n", KepGetUbsanTypeKind(Data->TypeCheckKind), Data->Type->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the object size mismatch error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN type mismatch data. + * + * @param Pointer + * Supplies a pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanObjectSizeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Object-Size-Mismatch"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: %s address %p with insufficient space for an object of type %s\n", + KepGetUbsanTypeKind(Data->TypeCheckKind), (PVOID)Pointer, Data->Type->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the out of bounds error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN out of bounds data. + * + * @param Index + * Supplies an index operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanOutOfBounds(PKUBSAN_OUT_OF_BOUNDS_DATA Data, + ULONG_PTR Index) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Array-Index-Out-Of-Bounds"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: index is out of range for type %s", Data->ArrayType->TypeName); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the pointer overflow error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanPointerOverflow(PKUBSAN_OVERFLOW_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs) +{ + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Pointer-Overflow"); + + /* Print error message to debug console */ + DebugPrint(L"UBSAN: Pointer operation %s %p to %p\n", + Lhs > Rhs ? "overflowed" : "underflowed", (PVOID)Lhs, (PVOID)Rhs); + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + + +/** + * Handles the shift out of bounds error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN shift out of bounds data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanShiftOutOfBounds(PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA Data, + ULONG_PTR Lhs, + ULONG_PTR Rhs) +{ + ULONG LhsBitWidth; + + /* Check if this error was already reported */ + if(!KepCheckUbsanReport(&Data->Location)) + { + /* Don't report twice */ + return; + } + + /* Enter UBSAN frame */ + KepEnterUbsanFrame(&Data->Location, "Shift-Out-Of-Bounds"); + + /* Calculate Lhs bit width */ + LhsBitWidth = 1 << (Data->LhsType->TypeInfo >> 1); + + /* Check a type of out of bounds error */ + if((Data->RhsType->TypeInfo & 1) && (KepGetSignedUbsanValue(Data->RhsType, (PVOID)Rhs) < 0)) + { + /* Negative shift exponent, print error message to debug console */ + DebugPrint(L"UBSAN: Shift exponent %lld is negative\n", KepGetSignedUbsanValue(Data->RhsType, (PVOID)Rhs)); + } + else if((Data->LhsType->TypeInfo & 1) && (KepGetSignedUbsanValue(Data->LhsType, (PVOID)Lhs) < 0)) + { + /* Negative left shift value, print error message to debug console */ + DebugPrint(L"UBSAN: Left shift of negative value %lld\n", KepGetSignedUbsanValue(Data->LhsType, (PVOID)Lhs)); + } + else if(KepGetUnsignedUbsanValue(Data->RhsType, (PVOID)Rhs) >= LhsBitWidth) + { + /* Shift exponent too large, print error message to debug console */ + DebugPrint(L"UBSAN: Shift exponent %lld is too large for %u-bit type %s\n", + KepGetUnsignedUbsanValue(Data->RhsType, (PVOID)Rhs), LhsBitWidth, Data->LhsType->TypeName); + } + else + { + /* Left shift too large, print error message to debug console */ + DebugPrint(L"UBSAN: Left shift of %lld by %lld places cannot be represented in type %s\n", + KepGetSignedUbsanValue(Data->LhsType, (PVOID)Lhs), KepGetSignedUbsanValue(Data->RhsType, (PVOID)Rhs), + Data->LhsType->TypeName); + } + + /* Leave UBSAN frame */ + KepLeaveUbsanFrame(); +} + +/** + * Handles the type mismatch error reported by UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN type mismatch data. + * + * @param Pointer + * Supplies a pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepHandleUbsanTypeMismatch(PKUBSAN_TYPE_MISMATCH_DATA Data, + ULONG_PTR Pointer) +{ + /* Check the type of mismatch */ + if(!Pointer) + { + /* Handle NULL pointer dereference */ + KepHandleUbsanNullPointerDereference(Data); + } + else if(Data->Alignment && (((Pointer) & ((typeof(Pointer))(Data->Alignment) - 1)) != 0)) + { + /* Handle misaligned access */ + KepHandleUbsanMisalignedAccess(Data, Pointer); + } + else + { + /* Handle object size mismatch */ + KepHandleUbsanObjectSizeMismatch(Data, Pointer); + } +} + +/** + * Leaves the UBSAN frame by marking it as inactive. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + */ +XTCDECL +VOID +KepLeaveUbsanFrame() +{ + /* Leave UBSAN frame */ + KepUbsanActiveFrame = FALSE; +} + +/** + * Handles the addition overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_add_overflow(IN PKUBSAN_OVERFLOW_DATA Data, + IN ULONG_PTR Lhs, + IN ULONG_PTR Rhs) +{ + /* Call UBSAN arithmetic overflow handler */ + KepHandleUbsanIntegerOverflow(Data, Lhs, Rhs); +} + +/** + * Handles the division overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_divrem_overflow(IN PKUBSAN_OVERFLOW_DATA Data, + IN PVOID Lhs, + IN PVOID Rhs) +{ + /* Call UBSAN division overflow handler */ + KepHandleUbsanDivisionOverflow(Data, Lhs, Rhs); +} + +/** + * Handles the float cast overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN float cast overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_float_cast_overflow(IN PKUBSAN_FLOAT_CAST_OVERFLOW_DATA Data, + IN ULONG_PTR Lhs, + IN ULONG_PTR Rhs) +{ + /* Call UBSAN float cast overflow handler */ + KepHandleUbsanFloatCastOverflow(Data, Lhs, Rhs); +} + +/** + * Handles the function type mismatch error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN function type mismatch data. + * + * @param Pointer + * Supplies pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_function_type_mismatch(IN PKUBSAN_FUNCTION_TYPE_MISMATCH_DATA Data, + IN ULONG_PTR Pointer) +{ + /* Call UBSAN function type mismatch handler */ + KepHandleUbsanFunctionTypeMismatch(Data, Pointer); +} + +/** + * Handles the invalid builtin error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN invalid builtin data. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_invalid_builtin(IN PKUBSAN_INVALID_BUILTIN_DATA Data) +{ + /* Call UBSAN invalid builtin handler */ + KepHandleUbsanInvalidBuiltin(Data); +} + +/** + * Handles the multiplication overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_mul_overflow(IN PKUBSAN_OVERFLOW_DATA Data, + IN ULONG_PTR Lhs, + IN ULONG_PTR Rhs) +{ + /* Call UBSAN arithmetic overflow handler */ + KepHandleUbsanIntegerOverflow(Data, Lhs, Rhs); +} + +/** + * Handles the negate overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param OldValue + * Supplies old value. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_negate_overflow(IN PKUBSAN_OVERFLOW_DATA Data, + IN ULONG_PTR OldValue) +{ + /* Call UBSAN negate overflow handler */ + KepHandleUbsanNegateOverflow(Data, OldValue); +} + +/** + * Handles the out of bounds error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN out of bounds data. + * + * @param Index + * Supplies an index operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_out_of_bounds(IN PKUBSAN_OUT_OF_BOUNDS_DATA Data, + IN ULONG_PTR Index) +{ + /* Call UBSAN out of bounds handler */ + KepHandleUbsanOutOfBounds(Data, Index); +} + +/** + * Handles the pointer overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_pointer_overflow(IN PKUBSAN_OVERFLOW_DATA Data, + IN ULONG_PTR Lhs, + IN ULONG_PTR Rhs) +{ + /* Call UBSAN pointer overflow handler */ + KepHandleUbsanPointerOverflow(Data, Lhs, Rhs); +} + +/** + * Handles the shift out of bounds error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN shift out of bounds data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_shift_out_of_bounds(IN PKUBSAN_SHIFT_OUT_OF_BOUNDS_DATA Data, + IN ULONG_PTR Lhs, + IN ULONG_PTR Rhs) +{ + /* Call UBSAN out of bounds handler */ + KepHandleUbsanShiftOutOfBounds(Data, Lhs, Rhs); +} + +/** + * Handles the subtraction overflow error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN overflow data. + * + * @param Lhs + * Supplies LHS operand. + * + * @param Rhs + * Supplies RHS operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_sub_overflow(IN PKUBSAN_OVERFLOW_DATA Data, + IN ULONG_PTR Lhs, + IN ULONG_PTR Rhs) +{ + /* Call UBSAN arithmetic overflow handler */ + KepHandleUbsanIntegerOverflow(Data, Lhs, Rhs); +} + +/** + * Handles the type mismatch error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN type mismatch data. + * + * @param Pointer + * Supplies a pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_type_mismatch(IN PKUBSAN_TYPE_MISMATCH_DATA Data, + IN ULONG_PTR Pointer) +{ + /* Call UBSAN type mismatch handler */ + KepHandleUbsanTypeMismatch(Data, Pointer); +} + +/** + * Handles the type mismatch error. This is internal routine implementing ABI defined by CLANG UBSAN. + * + * @param Data + * Supplies a pointer to the UBSAN type mismatch data. + * + * @param Pointer + * Supplies a pointer operand. + * + * @return This routine does not return any value. + * + * @since XT 1.0 + * + * @see https://github.com/llvm/llvm-project/blob/release/18.x/clang/lib/CodeGen/CodeGenFunction.h#L113 + */ +XTCDECL +VOID +__ubsan_handle_type_mismatch_v1(IN PKUBSAN_TYPE_MISMATCH_DATA_V1 Data, + IN ULONG_PTR Pointer) +{ + /* Prepare UBSAN type mismatch data in old format */ + KUBSAN_TYPE_MISMATCH_DATA MismatchData = { + .Location = Data->Location, + .Type = Data->Type, + .Alignment = 1UL << Data->LogAlignment, + .TypeCheckKind = Data->TypeCheckKind, + }; + + /* Call UBSAN type mismatch handler */ + KepHandleUbsanTypeMismatch(&MismatchData, Pointer); +}