/** * @file PlatformEvent.c * @author Sina Karvandi (sina@hyperdbg.org) * @brief Implementation of cross platform APIs for kernel event and object management * @details * @version 0.19 * @date 2026-05-09 * * @copyright This project is released under the GNU Public License v3. * */ #include "pch.h" #if defined(__linux__) # include "../header/PlatformEvent.h" // // Backing token for the NT global declared in PlatformEvent.h — never // inspected, it only has to be a dereferenceable address // static POBJECT_TYPE g_LinuxEventObjectType = NULL; POBJECT_TYPE * ExEventObjectType = &g_LinuxEventObjectType; #endif // defined(__linux__) /** * @brief Dereference a kernel object, decrementing its reference count * * @param Object Pointer to the kernel object to dereference * @return VOID */ VOID PlatformObjectDereference(PVOID Object) { #if defined(_WIN32) || defined(_WIN64) ObDereferenceObject(Object); #elif defined(__linux__) // // STUB: EVENT_BASED notify is unsupported on Linux until an eventfd backing // lands. TODO(Linux): eventfd_ctx_put((struct eventfd_ctx *)Object). // UNREFERENCED_PARAMETER(Object); #else # error "Unsupported platform" #endif } /** * @brief Signal (set) a kernel event object * * @param Event Pointer to the KEVENT to signal * @param Increment Priority increment for any waiting threads to be awakened * @param Wait If TRUE, the caller intends to immediately call a wait routine after this call * @return LONG The previous signal state of the event */ LONG PlatformEventSet(PKEVENT Event, KPRIORITY Increment, BOOLEAN Wait) { #if defined(_WIN32) || defined(_WIN64) return KeSetEvent(Event, Increment, Wait); #elif defined(__linux__) // // STUB. TODO(Linux): eventfd_signal((struct eventfd_ctx *)Event). Returns the // previous signal state; 0 is a safe default (no caller inspects it). // UNREFERENCED_PARAMETER(Event); UNREFERENCED_PARAMETER(Increment); UNREFERENCED_PARAMETER(Wait); return 0; #else # error "Unsupported platform" #endif } /** * @brief Initialize a kernel event object * * @param Event Pointer to the KEVENT to initialize * @param Type Event type (SynchronizationEvent = auto-reset, NotificationEvent = manual-reset) * @param State Initial signaled state * @return VOID */ VOID PlatformEventInitialize(PRKEVENT Event, EVENT_TYPE Type, BOOLEAN State) { #if defined(_WIN32) || defined(_WIN64) KeInitializeEvent(Event, Type, State); #elif defined(__linux__) // // STUB. TODO(Linux): initialize an eventfd/completion backing the KEVENT // (Type selects auto- vs manual-reset semantics). // UNREFERENCED_PARAMETER(Event); UNREFERENCED_PARAMETER(Type); UNREFERENCED_PARAMETER(State); #else # error "Unsupported platform" #endif } /** * @brief Wait until a kernel event object is signaled * * @param Object Pointer to the dispatcher object (KEVENT) to wait on * @param WaitReason Reason for the wait (Executive) * @param WaitMode Processor mode to wait in (KernelMode or UserMode) * @param Alertable Whether the wait can be interrupted by an alert/APC * @param Timeout Optional timeout; NULL waits indefinitely * @return NTSTATUS STATUS_SUCCESS when the object is signaled */ NTSTATUS PlatformEventWait(PVOID Object, KWAIT_REASON WaitReason, KPROCESSOR_MODE WaitMode, BOOLEAN Alertable, PLARGE_INTEGER Timeout) { #if defined(_WIN32) || defined(_WIN64) return KeWaitForSingleObject(Object, WaitReason, WaitMode, Alertable, Timeout); #elif defined(__linux__) // // STUB. TODO(Linux): wait on the eventfd/completion backing the KEVENT. // Returns immediately as signaled; no caller inspects the status today. // UNREFERENCED_PARAMETER(Object); UNREFERENCED_PARAMETER(WaitReason); UNREFERENCED_PARAMETER(WaitMode); UNREFERENCED_PARAMETER(Alertable); UNREFERENCED_PARAMETER(Timeout); return STATUS_SUCCESS; #else # error "Unsupported platform" #endif } /** * @brief Obtain a pointer to a kernel object by its user-mode handle and increment its reference count * * @param Handle User-mode handle referencing the kernel object * @param DesiredAccess Access mask for the requested access rights * @param ObjectType Pointer to the object type object (e.g., *ExEventObjectType); NULL to skip type check * @param AccessMode Processor mode to use for access checks (KernelMode or UserMode) * @param Object Receives a pointer to the referenced kernel object body * @param HandleInformation Optional; receives access state information * @return NTSTATUS STATUS_SUCCESS on success, or an error code on failure */ NTSTATUS PlatformObjectReferenceByHandle(HANDLE Handle, ACCESS_MASK DesiredAccess, POBJECT_TYPE ObjectType, KPROCESSOR_MODE AccessMode, PVOID * Object, POBJECT_HANDLE_INFORMATION HandleInformation) { #if defined(_WIN32) || defined(_WIN64) return ObReferenceObjectByHandle(Handle, DesiredAccess, ObjectType, AccessMode, Object, HandleInformation); #elif defined(__linux__) // // STUB. TODO(Linux): eventfd_ctx_fdget((int)(uintptr_t)Handle) into *Object. // Fail closed so the EVENT_BASED registration path bails cleanly. // UNREFERENCED_PARAMETER(Handle); UNREFERENCED_PARAMETER(DesiredAccess); UNREFERENCED_PARAMETER(ObjectType); UNREFERENCED_PARAMETER(AccessMode); UNREFERENCED_PARAMETER(HandleInformation); if (Object != NULL) { *Object = NULL; } return STATUS_NOT_IMPLEMENTED; #else # error "Unsupported platform" #endif }