825 строки
30 KiB
C++
825 строки
30 KiB
C++
// Copyright (c) Microsoft Corporation
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
#pragma once
|
|
#include "ebpf_result.h"
|
|
#include "ebpf_windows.h"
|
|
#include "framework.h"
|
|
|
|
#ifdef __cplusplus
|
|
extern "C"
|
|
{
|
|
#endif
|
|
|
|
#define EBPF_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0]))
|
|
#define EBPF_OFFSET_OF(s, m) (((size_t) & ((s*)0)->m))
|
|
#define EBPF_FROM_FIELD(s, m, o) (s*)((uint8_t*)o - EBPF_OFFSET_OF(s, m))
|
|
|
|
#define EBPF_DEVICE_NAME L"\\Device\\EbpfIoDevice"
|
|
#define EBPF_SYMBOLIC_DEVICE_NAME L"\\GLOBAL??\\EbpfIoDevice"
|
|
#define EBPF_DEVICE_WIN32_NAME L"\\\\.\\EbpfIoDevice"
|
|
|
|
#define EBPF_MAX_GENERAL_HELPER_FUNCTION 0xFFFF
|
|
|
|
#define EBPF_UTF8_STRING_FROM_CONST_STRING(x) \
|
|
{ \
|
|
((uint8_t*)(x)), sizeof((x)) - 1 \
|
|
}
|
|
|
|
/**
|
|
* @brief A UTF-8 encoded string.
|
|
* Notes:
|
|
* 1) This string is not NULL terminated, instead relies on length.
|
|
* 2) A single UTF-8 code point (aka character) could be 1-4 bytes in
|
|
* length.
|
|
*
|
|
*/
|
|
typedef struct _ebpf_utf8_string
|
|
{
|
|
uint8_t* value;
|
|
size_t length;
|
|
} ebpf_utf8_string_t;
|
|
|
|
typedef enum _ebpf_code_integrity_state
|
|
{
|
|
EBPF_CODE_INTEGRITY_DEFAULT = 0,
|
|
EBPF_CODE_INTEGRITY_HYPER_VISOR_KERNEL_MODE = 1
|
|
} ebpf_code_integrity_state_t;
|
|
|
|
typedef struct _ebpf_non_preemptible_work_item ebpf_non_preemptible_work_item_t;
|
|
typedef struct _ebpf_timer_work_item ebpf_timer_work_item_t;
|
|
typedef struct _ebpf_extension_client ebpf_extension_client_t;
|
|
typedef struct _ebpf_extension_provider ebpf_extension_provider_t;
|
|
typedef ebpf_result_t (*_ebpf_extension_dispatch_function)();
|
|
typedef struct _ebpf_extension_dispatch_table
|
|
{
|
|
uint16_t version;
|
|
uint16_t size;
|
|
_ebpf_extension_dispatch_function function[1];
|
|
} ebpf_extension_dispatch_table_t;
|
|
|
|
typedef struct _ebpf_extension_data
|
|
{
|
|
uint16_t version;
|
|
size_t size;
|
|
void* data;
|
|
} ebpf_extension_data_t;
|
|
|
|
typedef struct _ebpf_attach_provider_data
|
|
{
|
|
ebpf_program_type_t supported_program_type;
|
|
} ebpf_attach_provider_data_t;
|
|
#define EBPF_ATTACH_PROVIDER_DATA_VERSION 1
|
|
|
|
typedef struct _ebpf_trampoline_table ebpf_trampoline_table_t;
|
|
|
|
typedef uintptr_t ebpf_lock_t;
|
|
typedef uint8_t ebpf_lock_state_t;
|
|
|
|
// A self-relative security descriptor.
|
|
typedef struct _SECURITY_DESCRIPTOR ebpf_security_descriptor_t;
|
|
typedef struct _GENERIC_MAPPING ebpf_security_generic_mapping_t;
|
|
typedef uint32_t ebpf_security_access_mask_t;
|
|
|
|
typedef struct _ebpf_helper_function_addresses ebpf_helper_function_addresses_t;
|
|
|
|
/**
|
|
* @brief Initialize the eBPF platform abstraction layer.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_platform_initiate();
|
|
|
|
/**
|
|
* @brief Terminate the eBPF platform abstraction layer.
|
|
*/
|
|
void
|
|
ebpf_platform_terminate();
|
|
|
|
/**
|
|
* @brief Allocate memory.
|
|
* @param[in] size Size of memory to allocate
|
|
* @returns Pointer to memory block allocated, or null on failure.
|
|
*/
|
|
__drv_allocatesMem(Mem) _Must_inspect_result_ _Ret_maybenull_
|
|
_Post_writable_byte_size_(size) void* ebpf_allocate(size_t size);
|
|
|
|
/**
|
|
* @brief Free memory.
|
|
* @param[in] memory Allocation to be freed.
|
|
*/
|
|
void
|
|
ebpf_free(_Frees_ptr_opt_ void* memory);
|
|
|
|
typedef enum _ebpf_page_protection
|
|
{
|
|
EBPF_PAGE_PROTECT_READ_ONLY,
|
|
EBPF_PAGE_PROTECT_READ_WRITE,
|
|
EBPF_PAGE_PROTECT_READ_EXECUTE,
|
|
} ebpf_page_protection_t;
|
|
|
|
typedef struct _ebpf_memory_descriptor ebpf_memory_descriptor_t;
|
|
|
|
/**
|
|
* @brief Allocate pages from physical memory and create a mapping into the
|
|
* system address space.
|
|
*
|
|
* @param[in] length Size of memory to allocate (internally this gets rounded
|
|
* up to a page boundary).
|
|
* @return Pointer to an ebpf_memory_descriptor_t on success, NULL on failure.
|
|
*/
|
|
ebpf_memory_descriptor_t*
|
|
ebpf_map_memory(size_t length);
|
|
|
|
/**
|
|
* @brief Release physical memory previously allocated via ebpf_map_memory.
|
|
*
|
|
* @param[in] memory_descriptor Pointer to ebpf_memory_descriptor_t describing
|
|
* allocated pages.
|
|
*/
|
|
void
|
|
ebpf_unmap_memory(_Frees_ptr_opt_ ebpf_memory_descriptor_t* memory_descriptor);
|
|
|
|
/**
|
|
* @brief Change the page protection on memory allocated via
|
|
* ebpf_map_memory.
|
|
*
|
|
* @param[in] memory_descriptor Pointer to an ebpf_memory_descriptor_t
|
|
* describing allocated pages.
|
|
* @param[in] protection The new page protection to apply.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_INVALID_ARGUMENT An invalid argument was supplied.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_protect_memory(_In_ const ebpf_memory_descriptor_t* memory_descriptor, ebpf_page_protection_t protection);
|
|
|
|
/**
|
|
* @brief Given an ebpf_memory_descriptor_t allocated via ebpf_map_memory
|
|
* obtain the base virtual address.
|
|
*
|
|
* @param[in] memory_descriptor Pointer to an ebpf_memory_descriptor_t
|
|
* describing allocated pages.
|
|
* @return Base virtual address of pages that have been allocated.
|
|
*/
|
|
void*
|
|
ebpf_memory_descriptor_get_base_address(ebpf_memory_descriptor_t* memory_descriptor);
|
|
|
|
/**
|
|
* @brief Allocate and copy a UTF-8 string.
|
|
*
|
|
* @param[out] destination Pointer to memory where the new UTF-8 character
|
|
* sequence will be allocated.
|
|
* @param[in] source UTF-8 string that will be copied.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* UTF-8 string.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_duplicate_utf8_string(_Out_ ebpf_utf8_string_t* destination, _In_ const ebpf_utf8_string_t* source);
|
|
|
|
/**
|
|
* @brief Get the code integrity state from the platform.
|
|
* @param[out] state The code integrity state being enforced.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NOT_SUPPORTED Unable to obtain state from platform.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_get_code_integrity_state(_Out_ ebpf_code_integrity_state_t* state);
|
|
|
|
/**
|
|
* @brief Multiplies one value of type size_t by another and check for
|
|
* overflow.
|
|
* @param[in] multiplicand The value to be multiplied by multiplier.
|
|
* @param[in] multiplier The value by which to multiply multiplicand.
|
|
* @param[out] result A pointer to the result.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_ARITHMETIC_OVERFLOW Multiplication overflowed.
|
|
*/
|
|
_Must_inspect_result_ ebpf_result_t
|
|
ebpf_safe_size_t_multiply(
|
|
size_t multiplicand, size_t multiplier, _Out_ _Deref_out_range_(==, multiplicand* multiplier) size_t* result);
|
|
|
|
/**
|
|
* @brief Add one value of type size_t by another and check for
|
|
* overflow.
|
|
* @param[in] augend The value to be added by addend.
|
|
* @param[in] addend The value add to augend.
|
|
* @param[out] result A pointer to the result.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_ARITHMETIC_OVERFLOW Addition overflowed.
|
|
*/
|
|
_Must_inspect_result_ ebpf_result_t
|
|
ebpf_safe_size_t_add(size_t augend, size_t addend, _Out_ _Deref_out_range_(==, augend + addend) size_t* result);
|
|
|
|
/**
|
|
* @brief Subtract one value of type size_t from another and check for
|
|
* overflow or underflow.
|
|
* @param[in] minuend The value from which subtrahend is subtracted.
|
|
* @param[in] subtrahend The value subtract from minuend.
|
|
* @param[out] result A pointer to the result.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_ARITHMETIC_OVERFLOW Addition overflowed or underflowed.
|
|
*/
|
|
_Must_inspect_result_ ebpf_result_t
|
|
ebpf_safe_size_t_subtract(
|
|
size_t minuend, size_t subtrahend, _Out_ _Deref_out_range_(==, minuend - subtrahend) size_t* result);
|
|
|
|
/**
|
|
* @brief Create an instance of a lock.
|
|
* @param[out] lock Pointer to memory location that will contain the lock.
|
|
*/
|
|
void
|
|
ebpf_lock_create(_Out_ ebpf_lock_t* lock);
|
|
|
|
/**
|
|
* @brief Destroy an instance of a lock.
|
|
* @param[in] lock Pointer to memory location that contains the lock.
|
|
*/
|
|
void
|
|
ebpf_lock_destroy(_In_ ebpf_lock_t* lock);
|
|
|
|
/**
|
|
* @brief Acquire exclusive access to the lock.
|
|
* @param[in] lock Pointer to memory location that contains the lock.
|
|
* @returns - The previous lock_state required for unlock.
|
|
*/
|
|
_Requires_lock_not_held_(*lock) _Acquires_lock_(*lock) _IRQL_requires_max_(DISPATCH_LEVEL) _IRQL_saves_
|
|
_IRQL_raises_(DISPATCH_LEVEL) ebpf_lock_state_t ebpf_lock_lock(_In_ ebpf_lock_t* lock);
|
|
|
|
/**
|
|
* @brief Release exclusive access to the lock.
|
|
* @param[in] lock Pointer to memory location that contains the lock.
|
|
* @param[in] state The state returned from ebpf_lock_lock.
|
|
*/
|
|
_Requires_lock_held_(*lock) _Releases_lock_(*lock) _IRQL_requires_(DISPATCH_LEVEL) void ebpf_lock_unlock(
|
|
_In_ ebpf_lock_t* lock, _IRQL_restores_ ebpf_lock_state_t state);
|
|
|
|
/**
|
|
* @brief Query the platform for the total number of CPUs.
|
|
* @param[out] cpu_count Pointer to memory location that contains the
|
|
* number of CPUs.
|
|
*/
|
|
void
|
|
ebpf_get_cpu_count(_Out_ uint32_t* cpu_count);
|
|
|
|
/**
|
|
* @brief Query the platform to determine if the current execution can
|
|
* be preempted by other execution.
|
|
* @retrval True if this execution can be preempted.
|
|
*/
|
|
bool
|
|
ebpf_is_preemptible();
|
|
|
|
/**
|
|
* @brief Query the platform to determine which CPU this execution is
|
|
* running on. Only valid if ebpf_is_preemptible() == true.
|
|
* @retval Zero based index of CPUs.
|
|
*/
|
|
uint32_t
|
|
ebpf_get_current_cpu();
|
|
|
|
/**
|
|
* @brief Query the platform to determine an opaque identifier for the
|
|
* current thread. Only valid if ebpf_is_preemptible() == false.
|
|
* @return Opaque identifier for the current thread.
|
|
*/
|
|
uint64_t
|
|
ebpf_get_current_thread_id();
|
|
|
|
/**
|
|
* @brief Query the platform to determine if non-preemptible work items are
|
|
* supported.
|
|
*
|
|
* @retval true Non-preemptible work items are supported.
|
|
* @retval false Non-preemptible work items are not supported.
|
|
*/
|
|
bool
|
|
ebpf_is_non_preemptible_work_item_supported();
|
|
|
|
/**
|
|
* @brief Create a non-preemptible work item.
|
|
*
|
|
* @param[out] work_item Pointer to memory that will contain the pointer to
|
|
* the non-preemptible work item on success.
|
|
* @param[in] cpu_id Associate the work item with this CPU.
|
|
* @param[in] work_item_routine Routine to execute as a work item.
|
|
* @param[in] work_item_context Context to pass to the routine.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* work item.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_allocate_non_preemptible_work_item(
|
|
_Out_ ebpf_non_preemptible_work_item_t** work_item,
|
|
uint32_t cpu_id,
|
|
_In_ void (*work_item_routine)(void* work_item_context, void* parameter_1),
|
|
_In_opt_ void* work_item_context);
|
|
|
|
/**
|
|
* @brief Free a non-preemptible work item.
|
|
*
|
|
* @param[in] work_item Pointer to the work item to free.
|
|
*/
|
|
void
|
|
ebpf_free_non_preemptible_work_item(_Frees_ptr_opt_ ebpf_non_preemptible_work_item_t* work_item);
|
|
|
|
/**
|
|
* @brief Schedule a non-preemptible work item to run.
|
|
*
|
|
* @param[in] work_item Work item to schedule.
|
|
* @param[in] parameter_1 Parameter to pass to work item.
|
|
* @retval true Work item was queued.
|
|
* @retval false Work item is already queued.
|
|
*/
|
|
bool
|
|
ebpf_queue_non_preemptible_work_item(_In_ ebpf_non_preemptible_work_item_t* work_item, _In_opt_ void* parameter_1);
|
|
|
|
/**
|
|
* @brief Allocate a timer to run a non-preemptible work item.
|
|
*
|
|
* @param[out] timer Pointer to memory that will contain timer on success.
|
|
* @param[in] work_item_routine Routine to execute when time expires.
|
|
* @param[in] work_item_context Context to pass to routine.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* timer.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_allocate_timer_work_item(
|
|
_Out_ ebpf_timer_work_item_t** timer,
|
|
_In_ void (*work_item_routine)(void* work_item_context),
|
|
_In_opt_ void* work_item_context);
|
|
|
|
/**
|
|
* @brief Schedule a work item to be executed after elaped_microseconds.
|
|
*
|
|
* @param[in] timer Pointer to timer to schedule.
|
|
* @param[in] elapsed_microseconds Microseconds to delay before executing
|
|
* work item.
|
|
*/
|
|
void
|
|
ebpf_schedule_timer_work_item(_In_ ebpf_timer_work_item_t* timer, uint32_t elapsed_microseconds);
|
|
|
|
/**
|
|
* @brief Free a timer.
|
|
*
|
|
* @param[in] timer Timer to be freed.
|
|
*/
|
|
void
|
|
ebpf_free_timer_work_item(_Frees_ptr_opt_ ebpf_timer_work_item_t* timer);
|
|
|
|
typedef struct _ebpf_hash_table ebpf_hash_table_t;
|
|
|
|
/**
|
|
* @brief Allocate and initialize a hash table.
|
|
*
|
|
* @param[out] hash_table Pointer to memory that will contain hash table on
|
|
* success.
|
|
* @param[in] allocate Function to use when allocating elements in the
|
|
* hash table.
|
|
* @param[in] free Function to use when freeing elements in the hash table.
|
|
* @param[in] key_size Size of the keys used in the hash table.
|
|
* @param[in] value_size Size of the values used in the hash table.
|
|
* @param[in] bucket_count Count of buckets to use.
|
|
* @param[in] extract_function Function used to convert a key into a value
|
|
* that can be hashed and compared. If NULL, key is assumes to be
|
|
* comparable.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* hash table.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_hash_table_create(
|
|
_Out_ ebpf_hash_table_t** hash_table,
|
|
_In_ void* (*allocate)(size_t size),
|
|
_In_ void (*free)(void* memory),
|
|
size_t key_size,
|
|
size_t value_size,
|
|
size_t bucket_count,
|
|
_In_opt_ void (*extract_function)(
|
|
_In_ const uint8_t* value, _Outptr_ const uint8_t** data, _Out_ size_t* length));
|
|
|
|
/**
|
|
* @brief Remove all items from the hash table and release memory.
|
|
*
|
|
* @param[in] hash_table Hash-table to release.
|
|
*/
|
|
void
|
|
ebpf_hash_table_destroy(_In_opt_ _Post_ptr_invalid_ ebpf_hash_table_t* hash_table);
|
|
|
|
/**
|
|
* @brief Find an element in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to search.
|
|
* @param[in] key Key to find in hash table.
|
|
* @param[out] value Pointer to value if found.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NOT_FOUND Key not found in hash table.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_hash_table_find(_In_ ebpf_hash_table_t* hash_table, _In_ const uint8_t* key, _Outptr_ uint8_t** value);
|
|
|
|
/**
|
|
* @brief Insert or update an entry in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to update.
|
|
* @param[in] key Key to find and insert or update.
|
|
* @param[in] value Value to insert into hash table or NULL to insert zero entry.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate memory for this
|
|
* entry in the hash table.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_hash_table_update(_In_ ebpf_hash_table_t* hash_table, _In_ const uint8_t* key, _In_opt_ const uint8_t* value);
|
|
|
|
/**
|
|
* @brief Remove an entry from the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to update.
|
|
* @param[in] key Key to find and remove.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_hash_table_delete(_In_ ebpf_hash_table_t* hash_table, _In_ const uint8_t* key);
|
|
|
|
/**
|
|
* @brief Find the next key in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to query.
|
|
* @param[in] previous_key Previous key or NULL to restart.
|
|
* @param[out] next_key Next key if it exists.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MORE_KEYS No keys exist in the hash table that
|
|
* are lexicographically after the specified key.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_hash_table_next_key(
|
|
_In_ ebpf_hash_table_t* hash_table, _In_opt_ const uint8_t* previous_key, _Out_ uint8_t* next_key);
|
|
|
|
/**
|
|
* @brief Returns the next (key, value) pair in the hash table.
|
|
*
|
|
* @param[in] hash_table Hash-table to query.
|
|
* @param[in] previous_key Previous key or NULL to restart.
|
|
* @param[out] next_key Next key if it exists.
|
|
* @param[out] next_value If non-NULL, returns the next value if it exists.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MORE_KEYS No keys exist in the hash table that
|
|
* are lexicographically after the specified key.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_hash_table_next_key_and_value(
|
|
_In_ ebpf_hash_table_t* hash_table,
|
|
_In_opt_ const uint8_t* previous_key,
|
|
_Out_ uint8_t* next_key,
|
|
_Inout_opt_ uint8_t** next_value);
|
|
|
|
/**
|
|
* @brief Get the number of keys in the hash table
|
|
*
|
|
* @param[in] hash_table Hash-table to query.
|
|
* @return Count of entries in the hash table.
|
|
*/
|
|
size_t
|
|
ebpf_hash_table_key_count(_In_ ebpf_hash_table_t* hash_table);
|
|
|
|
/**
|
|
* @brief Atomically increase the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to increase by 1.
|
|
* @return The new value.
|
|
*/
|
|
int32_t
|
|
ebpf_interlocked_increment_int32(_Inout_ volatile int32_t* addend);
|
|
|
|
/**
|
|
* @brief Atomically decrease the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to decrease by 1.
|
|
* @return The new value.
|
|
*/
|
|
int32_t
|
|
ebpf_interlocked_decrement_int32(_Inout_ volatile int32_t* addend);
|
|
|
|
/**
|
|
* @brief Atomically increase the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to increase by 1.
|
|
* @return The new value.
|
|
*/
|
|
int64_t
|
|
ebpf_interlocked_increment_int64(_Inout_ volatile int64_t* addend);
|
|
|
|
/**
|
|
* @brief Atomically decrease the value of addend by 1 and return the new
|
|
* value.
|
|
*
|
|
* @param[in,out] addend Value to increase by 1.
|
|
* @return The new value.
|
|
*/
|
|
int64_t
|
|
ebpf_interlocked_decrement_int64(_Inout_ volatile int64_t* addend);
|
|
|
|
/**
|
|
* @brief Performs an atomic operation that compares the input value pointed
|
|
* to by destination with the value of comperand and replaces it with
|
|
* exchange.
|
|
*
|
|
* @param[in,out] destination A pointer to the input value that is compared
|
|
* with the value of comperand.
|
|
* @param[in] exchange Specifies the output value pointed to by destination
|
|
* if the input value pointed to by destination equals the value of
|
|
* comperand.
|
|
* @param[in] comperand Specifies the value that is compared with the input
|
|
* value pointed to by destination.
|
|
* @return Returns the original value of memory pointed to by
|
|
* destination.
|
|
*/
|
|
int32_t
|
|
ebpf_interlocked_compare_exchange_int32(_Inout_ volatile int32_t* destination, int32_t exchange, int32_t comperand);
|
|
|
|
/**
|
|
* @brief Performs an atomic operation that compares the input value pointed
|
|
* to by destination with the value of comperand and replaces it with
|
|
* exchange.
|
|
*
|
|
* @param[in,out] destination A pointer to the input value that is compared
|
|
* with the value of comperand.
|
|
* @param[in] exchange Specifies the output value pointed to by destination
|
|
* if the input value pointed to by destination equals the value of
|
|
* comperand.
|
|
* @param[in] comperand Specifies the value that is compared with the input
|
|
* value pointed to by destination.
|
|
* @return Returns the original value of memory pointed to by
|
|
* destination.
|
|
*/
|
|
void*
|
|
ebpf_interlocked_compare_exchange_pointer(
|
|
_Inout_ void* volatile* destination, _In_opt_ const void* exchange, _In_opt_ const void* comperand);
|
|
|
|
typedef void (*ebpf_extension_change_callback_t)(
|
|
_In_ void* client_binding_context,
|
|
_In_ const void* provider_binding_context,
|
|
_In_opt_ const ebpf_extension_data_t* provider_data);
|
|
|
|
/**
|
|
* @brief Load an extension and get its dispatch table.
|
|
*
|
|
* @param[out] client_context Context used to unload the extension.
|
|
* @param[in] interface_id GUID representing the identity of the interface.
|
|
* @param[in] extension_client_context Opaque per-instance pointer passed to the extension.
|
|
* @param[in] client_data Opaque client data passed to the extension or
|
|
NULL if there is none.
|
|
* @param[in] client_data_length Length of the client data.
|
|
* @param[in] client_dispatch_table Table of function pointers the client
|
|
* exposes or NULL if there is none.
|
|
* @param[out] provider_binding_context Provider binding context. Can be NULL.
|
|
* @param[out] provider_data Opaque provider data. Can be NULL.
|
|
* @param[out] provider_dispatch_table Table of function pointers the
|
|
* provider exposes. Can be NULL.
|
|
* @param[in] extension_changed Callback invoked when a provider attaches
|
|
* or detaches. NULL if not used.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NOT_FOUND The provider was not found.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_extension_load(
|
|
_Outptr_ ebpf_extension_client_t** client_context,
|
|
_In_ const GUID* interface_id,
|
|
_In_ void* extension_client_context,
|
|
_In_opt_ const ebpf_extension_data_t* client_data,
|
|
_In_opt_ const ebpf_extension_dispatch_table_t* client_dispatch_table,
|
|
_Outptr_opt_ void** provider_binding_context,
|
|
_Outptr_opt_ const ebpf_extension_data_t** provider_data,
|
|
_Outptr_opt_ const ebpf_extension_dispatch_table_t** provider_dispatch_table,
|
|
_In_opt_ ebpf_extension_change_callback_t extension_changed);
|
|
|
|
/**
|
|
* @brief Helper function that returns an opaque client context from an extension client.
|
|
*
|
|
* @param[in] extension_client_binding_context Opaque pointer to an extension client binding context. This is the
|
|
* same as the extension_client_binding_context input parameter obtained in the _ebpf_extension_dispatch_function
|
|
* callback function.
|
|
*
|
|
* @returns Pointer to opaque per-instance context that was passed in call to ebpf_extension_load, or NULL on
|
|
* failure.
|
|
*/
|
|
void*
|
|
ebpf_extension_get_client_context(_In_ const void* extension_client_binding_context);
|
|
|
|
/**
|
|
* @brief Unload an extension.
|
|
*
|
|
* @param[in] client_context Context of the extension to unload.
|
|
*/
|
|
void
|
|
ebpf_extension_unload(_Frees_ptr_opt_ ebpf_extension_client_t* client_context);
|
|
|
|
typedef ebpf_result_t (*ebpf_provider_client_attach_callback_t)(
|
|
void* context,
|
|
const GUID* client_id,
|
|
void* client_binding_context,
|
|
const ebpf_extension_data_t* client_data,
|
|
const ebpf_extension_dispatch_table_t* client_dispatch_table);
|
|
|
|
typedef ebpf_result_t (*ebpf_provider_client_detach_callback_t)(void* context, const GUID* client_id);
|
|
|
|
/**
|
|
* @brief Register as an extension provider.
|
|
*
|
|
* @param[out] provider_context Context used to unload the provider.
|
|
* @param[in] interface_id GUID representing the identity of the interface.
|
|
* @param[in] provider_data Opaque provider data.
|
|
* @param[in] provider_dispatch_table Table of function pointers the
|
|
* provider exposes.
|
|
* @param[in] client_attach_callback Function invoked when a client attaches.
|
|
* @param[in] client_detach_callback Function invoked when a client detaches.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_ERROR_EXTENSION_FAILED_TO_LOAD The provider was unable to
|
|
* load.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_provider_load(
|
|
_Outptr_ ebpf_extension_provider_t** provider_context,
|
|
_In_ const GUID* interface_id,
|
|
_In_opt_ void* provider_binding_context,
|
|
_In_opt_ const ebpf_extension_data_t* provider_data,
|
|
_In_opt_ const ebpf_extension_dispatch_table_t* provider_dispatch_table,
|
|
_In_opt_ void* callback_context,
|
|
_In_opt_ ebpf_provider_client_attach_callback_t client_attach_callback,
|
|
_In_opt_ ebpf_provider_client_detach_callback_t client_detach_callback);
|
|
|
|
/**
|
|
* @brief Unload a provider.
|
|
*
|
|
* @param[in] provider_context Provider to unload.
|
|
*/
|
|
void
|
|
ebpf_provider_unload(_Frees_ptr_opt_ ebpf_extension_provider_t* provider_context);
|
|
|
|
ebpf_result_t
|
|
ebpf_guid_create(_Out_ GUID* new_guid);
|
|
|
|
int32_t
|
|
ebpf_log_function(_In_ void* context, _In_z_ const char* format_string, ...);
|
|
|
|
/**
|
|
* @brief Allocate a new empty trampoline table of entry_count size.
|
|
*
|
|
* @param[in] entry_count Maximum number of functions to build trampolines for.
|
|
* @param[out] trampoline_table Pointer to memory that holds the trampoline
|
|
* table on success.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_allocate_trampoline_table(size_t entry_count, _Outptr_ ebpf_trampoline_table_t** trampoline_table);
|
|
|
|
/**
|
|
* @brief Free a previously allocated trampoline table.
|
|
*
|
|
* @param[in] trampoline_table Pointer to trampoline table to free.
|
|
*/
|
|
void
|
|
ebpf_free_trampoline_table(_Frees_ptr_opt_ ebpf_trampoline_table_t* trampoline_table);
|
|
|
|
/**
|
|
* @brief Populate the function pointers in a trampoline table.
|
|
*
|
|
* @param[in] trampoline_table Trampoline table to populate.
|
|
* @param[in] dispatch_table Dispatch table to populate from.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_update_trampoline_table(
|
|
_Inout_ ebpf_trampoline_table_t* trampoline_table,
|
|
_In_ const ebpf_helper_function_addresses_t* helper_function_addresses);
|
|
|
|
/**
|
|
* @brief Get the address of a trampoline function.
|
|
*
|
|
* @param[in] trampoline_table Trampoline table to query.
|
|
* @param[in] index Index of function to get.
|
|
* @param[out] function Pointer to memory that contains the function on success.
|
|
* @retval EBPF_SUCCESS The operation was successful.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
* @retval EBPF_INVALID_ARGUMENT An invalid argument was supplied.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_get_trampoline_function(
|
|
_In_ const ebpf_trampoline_table_t* trampoline_table, size_t index, _Out_ void** function);
|
|
|
|
typedef struct _ebpf_program_info ebpf_program_info_t;
|
|
|
|
/**
|
|
* @brief Serialize an ebpf_program_info_t structure into a flat
|
|
* buffer.
|
|
*
|
|
* @param[in] program_info ebpf_program_info_t to be serialized.
|
|
* @param[out] buffer On success, the buffer that contains the serialized
|
|
* structure. Must be freed by caller using ebpf_free.
|
|
* @param[out] buffer_size On success, the size of the serialized buffer.
|
|
* @retval EBPF_SUCCESS The operation succeeded.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_program_info_encode(
|
|
_In_ const ebpf_program_info_t* program_info,
|
|
_Outptr_result_bytebuffer_(*buffer_size) uint8_t** buffer,
|
|
_Out_ unsigned long* buffer_size);
|
|
|
|
/**
|
|
* @brief Deserialize an ebpf_program_info_t structure from a flat
|
|
* buffer.
|
|
*
|
|
* @param[out] program_info On success, a newly allocated
|
|
* ebpf_program_info_t with the data from the flat buffer. Must be
|
|
* freed by the caller using ebpf_free.
|
|
* @param[in] buffer Buffer containing the serialized structure.
|
|
* @param[in] buffer_size Size of the buffer.
|
|
* @retval EBPF_SUCCESS The operation succeeded.
|
|
* @retval EBPF_NO_MEMORY Unable to allocate resources for this
|
|
* operation.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_program_info_decode(
|
|
_Outptr_ ebpf_program_info_t** program_info,
|
|
_In_ _Readable_bytes_(buffer_size) const uint8_t* buffer,
|
|
size_t buffer_size);
|
|
|
|
/**
|
|
* @brief Check if the user associated with the current thread is granted
|
|
* the rights requested.
|
|
*
|
|
* @param[in] security_descriptor Security descriptor representing the
|
|
* security policy.
|
|
* @param[in] request_access Access the caller is requesting.
|
|
* @param[in] generic_mapping Mappings for generic read/write/execute to
|
|
* specific rights.
|
|
* @retval EBPF_SUCCESS Requested access is granted.
|
|
* @retval EBPF_ACCESS_DENIED Requested access is denied.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_access_check(
|
|
_In_ ebpf_security_descriptor_t* security_descriptor,
|
|
ebpf_security_access_mask_t request_access,
|
|
_In_ ebpf_security_generic_mapping_t* generic_mapping);
|
|
|
|
/**
|
|
* @brief Check the validity of the provided security descriptor.
|
|
*
|
|
* @param[in] security_descriptor Security descriptor to verify.
|
|
* @param[in] security_descriptor_length Length of security descriptor.
|
|
* @retval EBPF_SUCCESS Security descriptor is well formed.
|
|
* @retval EBPF_INVALID_ARGUMENT Security descriptor is malformed.
|
|
*/
|
|
ebpf_result_t
|
|
ebpf_validate_security_descriptor(
|
|
_In_ ebpf_security_descriptor_t* security_descriptor, size_t security_descriptor_length);
|
|
|
|
/**
|
|
* @brief Return a pseudorandom number.
|
|
*
|
|
* @return A pseudorandom number.
|
|
*/
|
|
uint32_t
|
|
ebpf_random_uint32();
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|
|
|
|
#ifdef __cplusplus
|
|
#include <memory>
|
|
namespace ebpf_helper {
|
|
|
|
struct _ebpf_free_functor
|
|
{
|
|
void
|
|
operator()(void* memory)
|
|
{
|
|
ebpf_free(memory);
|
|
}
|
|
};
|
|
|
|
typedef std::unique_ptr<void, _ebpf_free_functor> ebpf_memory_ptr;
|
|
|
|
} // namespace ebpf_helper
|
|
|
|
#endif
|