diff --git a/docs/eBpfExtensions.md b/docs/eBpfExtensions.md index 54d1b7d9bd..ae30a49edb 100644 --- a/docs/eBpfExtensions.md +++ b/docs/eBpfExtensions.md @@ -62,8 +62,23 @@ initialized as follows: * `NpiSpecificCharacteristics`: Pointer to structure of type `ebpf_extension_data_t`. * The `data` field of this structure should point to a structure of type `ebpf_program_data_t`. +#### `ebpf_extension_header_t` Struct +This is a mandatory header that is common to all data structures needed by eBPF extensions to register with the eBPF framework. +* `version`: Version of the extension data structure. +* `size`: Size of the extension data structure. + When populating these data structures, the correct `version` and `size` fields must be set. The set of current version numbers and the + size for the various extension structures are listed in `ebpf_windows.h`. For example: +```c + #define EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION 1 + #define EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE \ + (EBPF_OFFSET_OF(ebpf_program_type_descriptor_t, is_privileged) + sizeof(char)) +``` +> NOTE: Extension developers **must not** set the `size` field of these structures to `sizeof()` of the corresponding type. Instead, +> the `CURRENT_VERSION_SIZE` macros defined in `ebpf_windows.h` should be used. + #### `ebpf_program_data_t` Struct The various fields of this structure should be set as follows: +* `header`: Version and size. * `program_info`: Pointer to `ebpf_program_info_t`. * `program_type_specific_helper_function_addresses`: Pointer to `ebpf_helper_function_addresses_t`. This structure provides the helper functions that are exclusive to this program type. @@ -77,12 +92,14 @@ context structure and populates the returned data and context buffers. #### `ebpf_program_info_t` Struct The various fields of this structure should be set as follows: -* `program_type_descriptor`: Field of type `ebpf_program_type_descriptor_t`. +* `header`: Version and size. +* `program_type_descriptor`: Pointer to `ebpf_program_type_descriptor_t`. * `count_of_helpers`: The number of helper functions that are implemented by this extension for the given program type. * `helper_prototype`: Pointer to array of `ebpf_helper_function_prototype_t`. #### `ebpf_program_type_descriptor_t` Struct The various fields of this structure should be set as follows: +* `header`: Version and size. * `name`: Friendly name of the program type. * `context_descriptor`: Pointer of type `ebpf_context_descriptor_t`. * `program_type`: GUID for the program type. This should be the same as the `NpiId` in `NPI_REGISTRATION_INSTANCE` as @@ -94,6 +111,7 @@ field should be set to `0 (BPF_PROG_TYPE_UNSPEC)`. #### `ebpf_context_descriptor_t` Struct This structure (as the name signifies) provides a description of the context parameter that a hook passes when invoking an eBPF program. The various fields of this struct are as follows. +* `header`: Version and size. * `size`: Size of the context structure. * `data`: Offset (in bytes) to the field in the context structure that is pointing to the beginning of context data. * `end`: Offset (in bytes) to the field in the context structure that is pointing to the end of context data. @@ -124,6 +142,7 @@ in the context descriptor. #### `ebpf_helper_function_prototype_t` Struct This structure is used to describe the prototypes of the various helper functions implemented by the extension. +* `header`: Version and size. * `helper_id`: Integer signifying the helper function ID. (See section 2.6). Helper function IDs for different program types need not be unique. * `name`: Helper function name. @@ -189,7 +208,17 @@ This optional function is used to populate the flat buffers representing the dat returned to the application when the `bpf_prog_test_run_opts` call completes. In addition, the function frees any resources allocated in the `ebpf_program_context_create_t` call. -### 2.2 Program Information NPI Client Attach and Detach Callbacks +### 2.2 Backward compatibility of the Extension data structures +All the extension data structures are versioned. To maintain backward compatibility with the existing extensions, new fields **MUST** be added +to the end of a data structure. The constant defining the current size of the modified struct will be updated in `ebpf_windows.h`. Existing +eBPF extensions will continue to work without requiring recompilation. If an extension is modified to use a newly added field, the length +field must be updated accordingly. + +If the change in data structure is such that it is no longer backward compatible (such as changing field type or position), +then the version number will be updated. In this case, the product version of eBPF for Windows must be updated to indicate a breaking change +as well. Existing eBPF extensions would need to be re-compiled to work with the latest version of eBPF. + +### 2.3 Program Information NPI Client Attach and Detach Callbacks The eBPF Execution Context registers a Program Information NPI client module with the NMR for every eBPF program that gets loaded. The Execution Context will use the program type GUID of the program as the NPI ID of the client module. And as a result, upon eBPF program load, the associated Program Information NPI client module will attach with the @@ -198,7 +227,7 @@ client or provider dispatch tables. Neither does the client's `NpiSpecificCharac special processing is required in the client attach and detach callback handler on the provider module. An extension must not unload until there are no more attached Program Information NPI clients. -### 2.3 Hook NPI Provider Registration +### 2.4 Hook NPI Provider Registration When registering itself to the NMR, the Hook NPI provider should have the [`NPI_REGISTRATION_INSTANCE`](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/netioddk/ns-netioddk-_npi_registration_instance) initialized as follows: @@ -220,7 +249,7 @@ requested attach type is supported by the Hook NPI provider. If not, the eBPF pr The `bpf_attach_type` field should contain the equivalent bpf attach type integer. If there is no equivalent bpf attach type, this field should be set to `0 (BPF_ATTACH_TYPE_UNSPEC)`. -### 2.4 Hook NPI Client Attach and Detach Callbacks +### 2.5 Hook NPI Client Attach and Detach Callbacks The eBPF Execution Context registers a Hook NPI client module with the NMR for each program that is attached to a hook. The attach type GUID is used as the NPI of the client module. And as a result, when an eBPF program gets attached to a hook, the associated Hook NPI client module will attach to the corresponding Hook NPI provider module in the @@ -246,7 +275,7 @@ Upon [client detach callback](https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/netioddk/nc-netioddk-npi_provider_detach_client_fn) the provider must free the per-client context passed in via `ProviderBindingContext` parameter. -### 2.5 Invoking an eBPF program from Hook NPI Provider +### 2.6 Invoking an eBPF program from Hook NPI Provider To invoke an eBPF program, the extension uses the dispatch table supplied by the Hook NPI client during attaching. The client dispatch table contains the functions, with the following type prototypes: @@ -330,7 +359,7 @@ of time a batch is open and must not change IRQL between calling batch begin and the number of times the program has been invoked, so callers should limit the number of calls within a batch to prevent long delays in batch end. -### 2.6 Authoring Helper Functions +### 2.7 Authoring Helper Functions An extension can provide an implementation of helper functions that can be invoked by the eBPF programs. The helper functions can be of two types: 1. Program-Type specific: These helper functions can only be invoked by eBPF programs of a given program type. Usually, @@ -356,7 +385,7 @@ The helper function ID for a general helper function must be in the range 0 - 65 The parameter and return types for these helper functions must adhere to the `ebpf_argument_type_t` and `ebpf_return_type_t` enums. -### 2.7 Registering Program Types and Attach Types - eBPF Store +### 2.8 Registering Program Types and Attach Types - eBPF Store The eBPF Execution Context loads an eBPF program from an ELF file that has program section(s) with section names. The prefix to these names determines the program type. For example, the section name `"xdp_test"` implies that the corresponding program type is `EBPF_PROGRAM_TYPE_XDP_TEST`. @@ -373,15 +402,15 @@ To operate on the eBPF store, the user mode application needs to link with eBPFA _In_reads_(section_info_count) const ebpf_program_section_info_t* section_info, uint32_t section_info_count); ``` -- `ebpf_store_update_program_information`: updates program information in the eBPF store, given a pointer to an array of program information (i.e., `_ebpf_program_info`): +- `ebpf_store_update_program_information_array`: updates program information in the eBPF store, given a pointer to an array of program information (i.e., `_ebpf_program_info`): ```c ebpf_result_t - ebpf_store_update_program_information( + ebpf_store_update_program_information_array( _In_reads_(program_info_count) const ebpf_program_info_t* program_info, uint32_t program_info_count); ``` -### 2.8 eBPF Sample Driver +### 2.9 eBPF Sample Driver The eBPF for Windows project provides a [sample extension driver](https://github.com/microsoft/ebpf-for-windows/tree/8f46b4020f79c32f994d3a59671ce8782e4b4cf0/tests/sample/ext) as an example for how to implement an extension. This simple extension exposes a new program type, and implements a diff --git a/ebpfapi/Source.def b/ebpfapi/Source.def index 4b5fb8ab0a..c9ca49aa12 100644 --- a/ebpfapi/Source.def +++ b/ebpfapi/Source.def @@ -119,7 +119,7 @@ EXPORTS ebpf_program_query_info ebpf_store_delete_program_information ebpf_store_delete_section_information - ebpf_store_update_program_information + ebpf_store_update_program_information_array ebpf_store_update_section_information libbpf_attach_type_by_name libbpf_bpf_attach_type_str diff --git a/include/ebpf_extension.h b/include/ebpf_extension.h index 760feb18ff..2c57893973 100644 --- a/include/ebpf_extension.h +++ b/include/ebpf_extension.h @@ -87,13 +87,13 @@ typedef struct _ebpf_extension_program_dispatch_table typedef struct _ebpf_extension_data { - uint16_t version; - size_t size; + ebpf_extension_header_t header; const void* data; } ebpf_extension_data_t; typedef struct _ebpf_attach_provider_data { + ebpf_extension_header_t header; ebpf_program_type_t supported_program_type; bpf_attach_type_t bpf_attach_type; enum bpf_link_type link_type; @@ -118,9 +118,4 @@ typedef struct _ebpf_execution_context_state const void* next_program; uint32_t count; } tail_call_state; -} ebpf_execution_context_state_t; - -#define EBPF_ATTACH_CLIENT_DATA_VERSION 0 -#define EBPF_ATTACH_PROVIDER_DATA_VERSION 1 -#define EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION 0 -#define EBPF_MAX_GENERAL_HELPER_FUNCTION 0xFFFF +} ebpf_execution_context_state_t; \ No newline at end of file diff --git a/include/ebpf_program_attach_type_guids.h b/include/ebpf_program_attach_type_guids.h index b0cd7fa2be..793178f31e 100644 --- a/include/ebpf_program_attach_type_guids.h +++ b/include/ebpf_program_attach_type_guids.h @@ -21,69 +21,98 @@ extern "C" __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_XDP = { 0x85e0d8ef, 0x579e, 0x4931, {0xb0, 0x72, 0x8e, 0xe2, 0x26, 0xbb, 0x2e, 0x9d}}; +#define EBPF_ATTACH_TYPE_BIND_GUID \ + { \ + 0xb9707e04, 0x8127, 0x4c72, { 0x83, 0x3e, 0x05, 0xb1, 0xfb, 0x43, 0x94, 0x96 } \ + } /** @brief Attach type for handling socket bind() requests. * * Program type: \ref EBPF_PROGRAM_TYPE_BIND */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_BIND = { - 0xb9707e04, 0x8127, 0x4c72, {0x83, 0x3e, 0x05, 0xb1, 0xfb, 0x43, 0x94, 0x96}}; + __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_BIND = EBPF_ATTACH_TYPE_BIND_GUID; +#define EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT_GUID \ + { \ + 0xa82e37b1, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \ + } /** @brief The programs attached to the INET4_CONNECT hook will be invoked for * connect() calls on TCP or UDP sockets or when a UDP socket sends a packet to * a unique remote address/port tuple. * * Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT = { - 0xa82e37b1, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}}; + __declspec(selectany) + ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT = EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT_GUID; +#define EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT_GUID \ + { \ + 0xa82e37b2, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \ + } /** @brief The programs attached to the INET6_CONNECT hook will be invoked for * connect() calls on TCP or UDP sockets or when a UDP socket sends a packet to * a unique remote address/port tuple. * * Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT = { - 0xa82e37b2, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}}; + __declspec(selectany) + ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT = EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT_GUID; +#define EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT_GUID \ + { \ + 0xa82e37b3, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \ + } /** @brief The programs attached to the INET4_RECV_ACCEPT hook will get invoked for * TCP accept() calls or for the first unicast UDP packet from a unique remote * address/port tuple. * * Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT = { - 0xa82e37b3, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}}; + __declspec(selectany) + ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT = EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT_GUID; +#define EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT_GUID \ + { \ + 0xa82e37b4, 0xaee7, 0x11ec, { 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee } \ + } /** @brief The programs attached to the INET6_RECV_ACCEPT hook will get invoked for * TCP accept() calls or for the first unicast UDP packet from a unique remote * address/port tuple. * * Program type: \ref EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT = { - 0xa82e37b4, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}}; + __declspec(selectany) + ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT = EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT_GUID; +#define EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS_GUID \ + { \ + 0x837d02cd, 0x3251, 0x4632, { 0x8d, 0x94, 0x60, 0xd3, 0xb4, 0x57, 0x69, 0xf2 } \ + } /** @brief Attach type for handling socket event notifications. * * Program type: \ref EBPF_PROGRAM_TYPE_SOCK_OPS */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS = { - 0x837d02cd, 0x3251, 0x4632, {0x8d, 0x94, 0x60, 0xd3, 0xb4, 0x57, 0x69, 0xf2}}; + __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS = EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS_GUID; + +#define EBPF_ATTACH_TYPE_SAMPLE_GUID \ + { \ + 0xf788ef4b, 0x207d, 0x4dc3, { 0x85, 0xcf, 0x0f, 0x2e, 0xa1, 0x07, 0x21, 0x3c } \ + } /** @brief Attach type implemented by eBPF Sample Extension driver, used for testing. * - * Program type: \ref EBPF_PROGRAM_TYPE_SAMPLE + * Program type: \ref EBPF_ATTACH_TYPE_SAMPLE */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_SAMPLE = { - 0xf788ef4b, 0x207d, 0x4dc3, {0x85, 0xcf, 0x0f, 0x2e, 0xa1, 0x07, 0x21, 0x3c}}; + __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_SAMPLE = EBPF_ATTACH_TYPE_SAMPLE_GUID; +#define EBPF_ATTACH_TYPE_XDP_TEST_GUID \ + { \ + 0x0dccc15d, 0xa5f9, 0x4dc1, { 0xac, 0x79, 0xfa, 0x25, 0xee, 0xf2, 0x15, 0xc3 } \ + } /** @brief Attach type for handling incoming packets as early as possible. * * Program type: \ref EBPF_PROGRAM_TYPE_XDP_TEST */ - __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_XDP_TEST = { - 0x0dccc15d, 0xa5f9, 0x4dc1, {0xac, 0x79, 0xfa, 0x25, 0xee, 0xf2, 0x15, 0xc3}}; + __declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_XDP_TEST = EBPF_ATTACH_TYPE_XDP_TEST_GUID; // // Program Types. diff --git a/include/ebpf_program_types.h b/include/ebpf_program_types.h index b1aabfb925..49166350fe 100644 --- a/include/ebpf_program_types.h +++ b/include/ebpf_program_types.h @@ -4,22 +4,16 @@ #include "ebpf_base.h" #include "ebpf_result.h" - -#include -#if !defined(NO_CRT) && !defined(_NO_CRT_STDIO_INLINE) -#include -#else -typedef unsigned char uint8_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -typedef unsigned short wchar_t; -#endif +#include "ebpf_windows.h" #define EBPF_MAX_PROGRAM_DESCRIPTOR_NAME_LENGTH 256 #define EBPF_MAX_HELPER_FUNCTION_NAME_LENGTH 256 +// This is the type definition for the eBPF program type descriptor +// when version is EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION. typedef struct _ebpf_program_type_descriptor { + ebpf_extension_header_t header; const char* name; const ebpf_context_descriptor_t* context_descriptor; GUID program_type; @@ -27,25 +21,34 @@ typedef struct _ebpf_program_type_descriptor char is_privileged; } ebpf_program_type_descriptor_t; +// This is the type definition for the eBPF helper function prototype +// when version is EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION. typedef struct _ebpf_helper_function_prototype { + ebpf_extension_header_t header; uint32_t helper_id; const char* name; ebpf_return_type_t return_type; ebpf_argument_type_t arguments[5]; } ebpf_helper_function_prototype_t; +// This is the type definition for the eBPF program information +// when version is EBPF_PROGRAM_INFORMATION_CURRENT_VERSION. typedef struct _ebpf_program_info { - ebpf_program_type_descriptor_t program_type_descriptor; + ebpf_extension_header_t header; + const ebpf_program_type_descriptor_t* program_type_descriptor; uint32_t count_of_program_type_specific_helpers; const ebpf_helper_function_prototype_t* program_type_specific_helper_prototype; uint32_t count_of_global_helpers; const ebpf_helper_function_prototype_t* global_helper_prototype; } ebpf_program_info_t; +// This is the type definition for the eBPF helper function addresses +// when version is EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION. typedef struct _ebpf_helper_function_addresses { + ebpf_extension_header_t header; uint32_t helper_function_count; uint64_t* helper_function_address; } ebpf_helper_function_addresses_t; @@ -64,8 +67,11 @@ typedef void (*ebpf_program_context_destroy_t)( _Out_writes_bytes_to_opt_(*context_size_out, *context_size_out) uint8_t* context_out, _Inout_ size_t* context_size_out); +// This is the type definition for the eBPF program data +// when version is EBPF_PROGRAM_DATA_CURRENT_VERSION. typedef struct _ebpf_program_data { + ebpf_extension_header_t header; const ebpf_program_info_t* program_info; ///< Pointer to program information. const ebpf_helper_function_addresses_t* program_type_specific_helper_function_addresses; ///< Pointer to program type specific helper function @@ -77,8 +83,11 @@ typedef struct _ebpf_program_data uint8_t required_irql; ///< IRQL at which the program is invoked. } ebpf_program_data_t; +// This is the type definition for the eBPF program section information +// when version is EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION. typedef struct _ebpf_program_section_info { + ebpf_extension_header_t header; const wchar_t* section_name; const GUID* program_type; const GUID* attach_type; diff --git a/include/ebpf_store_helper.h b/include/ebpf_store_helper.h index 1c5f9e8391..b303d3ea29 100644 --- a/include/ebpf_store_helper.h +++ b/include/ebpf_store_helper.h @@ -52,7 +52,7 @@ extern "C" * @returns Status of the operation. */ ebpf_result_t - ebpf_store_update_program_information( + ebpf_store_update_program_information_array( _In_reads_(program_info_count) const ebpf_program_info_t* program_info, uint32_t program_info_count); /** diff --git a/include/ebpf_structs.h b/include/ebpf_structs.h index 84bece802f..e2b737f14a 100644 --- a/include/ebpf_structs.h +++ b/include/ebpf_structs.h @@ -10,16 +10,6 @@ #include "ebpf_windows.h" -#if !defined(NO_CRT) && !defined(_NO_CRT_STDIO_INLINE) -#include -#include -#else -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned int uint32_t; -typedef unsigned long long uint64_t; -#endif - #define MAX_TAIL_CALL_CNT 33 #define BPF_ENUM_TO_STRING(X) #X diff --git a/include/ebpf_windows.h b/include/ebpf_windows.h index c02e0c7a9b..81638e879d 100644 --- a/include/ebpf_windows.h +++ b/include/ebpf_windows.h @@ -5,26 +5,38 @@ #ifdef _MSC_VER #include #else +typedef uint8_t GUID[16]; +#endif + #if !defined(NO_CRT) && !defined(_NO_CRT_STDIO_INLINE) +#include +#include #include #else typedef unsigned char uint8_t; -#endif -typedef uint8_t GUID[16]; +typedef unsigned short uint16_t; +typedef unsigned short wchar_t; +typedef unsigned int uint32_t; +typedef unsigned long long uint64_t; +typedef unsigned long long size_t; #endif // This file contains eBPF definitions needed by eBPF programs as well as -// the verifier and execution context. +// the verifier, execution context and extension drivers. #define EBPF_ROOT_REGISTRY_PATH L"\\Registry\\Machine\\Software\\eBPF" #define EBPF_ROOT_RELATIVE_PATH L"Software\\eBPF" #define EBPF_STORE_REGISTRY_PATH L"Software\\eBPF\\Providers" -#define EBPF_PROVIDERS_REGISTRY_PATH L"Providers" -#define EBPF_SECTIONS_REGISTRY_PATH L"SectionData" -#define EBPF_PROGRAM_DATA_REGISTRY_PATH L"ProgramData" -#define EBPF_PROGRAM_DATA_HELPERS_REGISTRY_PATH L"Helpers" -#define EBPF_GLOBAL_HELPERS_REGISTRY_PATH L"GlobalHelpers" +#define EBPF_PROVIDERS_REGISTRY_KEY L"Providers" +#define EBPF_SECTIONS_REGISTRY_KEY L"SectionData" +#define EBPF_PROGRAM_DATA_REGISTRY_KEY L"ProgramData" +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_REGISTRY_KEY L"TypeDescriptor" +#define EBPF_PROGRAM_DATA_HELPERS_REGISTRY_KEY L"Helpers" +#define EBPF_GLOBAL_HELPERS_REGISTRY_KEY L"GlobalHelpers" + +#define EBPF_EXTENSION_HEADER_VERSION L"Version" +#define EBPF_EXTENSION_HEADER_SIZE L"Size" #define EBPF_SECTION_DATA_PROGRAM_TYPE L"ProgramType" #define EBPF_SECTION_DATA_ATTACH_TYPE L"AttachType" @@ -49,3 +61,44 @@ typedef enum _ebpf_helper_function EBPF_UPDATE_ELEMENT = 2, ///< Update map element. EBPF_DELETE_ELEMENT = 3, ///< Delete a map element. } ebpf_helper_function_t; + +#define EBPF_MAX_GENERAL_HELPER_FUNCTION 0xFFFF + +// Version 1 of the eBPF extension data structures and their lengths. +#define EBPF_ATTACH_CLIENT_DATA_CURRENT_VERSION 1 +#define EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION 1 +#define EBPF_PROGRAM_INFORMATION_CLIENT_DATA_CURRENT_VERSION 1 + +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION 1 +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE \ + EBPF_SIZE_INCLUDING_FIELD(ebpf_program_type_descriptor_t, is_privileged) + +#define EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION 1 +#define EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE \ + EBPF_SIZE_INCLUDING_FIELD(ebpf_helper_function_prototype_t, arguments) + +#define EBPF_PROGRAM_INFORMATION_CURRENT_VERSION 1 +#define EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE \ + EBPF_SIZE_INCLUDING_FIELD(ebpf_program_info_t, global_helper_prototype) + +#define EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION 1 + +#define EBPF_PROGRAM_DATA_CURRENT_VERSION 1 +#define EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE EBPF_SIZE_INCLUDING_FIELD(ebpf_program_data_t, required_irql) + +#define EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION 1 +#define EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE \ + EBPF_SIZE_INCLUDING_FIELD(ebpf_program_section_info_t, bpf_attach_type) + +/** + * @brief Header of an eBPF extension data structure. + * Every eBPF extension data structure must start with this header. + * New fields can be added to the end of an eBPF extension data structure + * without breaking backward compatibility. The version field must be + * updated only if the new data structure is not backward compatible. + */ +typedef struct _ebpf_extension_header +{ + uint16_t version; ///< Version of the extension data structure. + size_t size; ///< Size of the extension data structure. +} ebpf_extension_header_t; diff --git a/libs/api_common/store_helper_internal.cpp b/libs/api_common/store_helper_internal.cpp index d5478c3c6a..a98e0ca1ff 100644 --- a/libs/api_common/store_helper_internal.cpp +++ b/libs/api_common/store_helper_internal.cpp @@ -6,6 +6,7 @@ #include "ebpf_serialize.h" #include "ebpf_shared_framework.h" #include "ebpf_store_helper.h" +#include "ebpf_tracelog.h" #include "ebpf_utilities.h" #include "store_helper_internal.h" #include "utilities.hpp" @@ -15,6 +16,8 @@ ebpf_store_key_t root_registry_key_current_user = HKEY_CURRENT_USER; static ebpf_result_t _open_ebpf_store_key(_Out_ ebpf_store_key_t* store_key) { + EBPF_LOG_ENTRY(); + // Open root registry path. *store_key = nullptr; @@ -22,11 +25,33 @@ _open_ebpf_store_key(_Out_ ebpf_store_key_t* store_key) ebpf_result_t result = ebpf_open_registry_key(root_registry_key_current_user, EBPF_STORE_REGISTRY_PATH, KEY_READ, store_key); - return result; + EBPF_RETURN_RESULT(result); +} + +static ebpf_result_t +_load_extension_header(HKEY data_key, _Out_ ebpf_extension_header_t* extension_header) +{ + uint32_t version, size; + + EBPF_LOG_ENTRY(); + + ebpf_result_t result = ebpf_read_registry_value_dword(data_key, EBPF_EXTENSION_HEADER_VERSION, &version); + if (result != EBPF_SUCCESS) { + EBPF_RETURN_RESULT(result); + } + result = ebpf_read_registry_value_dword(data_key, EBPF_EXTENSION_HEADER_SIZE, &size); + if (result != EBPF_SUCCESS) { + EBPF_RETURN_RESULT(result); + } + + extension_header->version = static_cast(version); + extension_header->size = size; + + EBPF_RETURN_RESULT(result); } static ebpf_result_t -_load_helper_prototype( +_ebpf_store_load_helper_prototype( HKEY helper_store_key, _In_z_ const wchar_t* helper_name, _Out_ ebpf_helper_function_prototype_t* helper_prototype) noexcept @@ -34,46 +59,57 @@ _load_helper_prototype( int32_t status; ebpf_result_t result = EBPF_SUCCESS; HKEY helper_info_key = nullptr; + uint32_t offset = 0; + char serialized_data[sizeof(ebpf_helper_function_prototype_t)] = {0}; + size_t expected_size = sizeof(helper_prototype->helper_id) + sizeof(helper_prototype->return_type) + + sizeof(helper_prototype->arguments); - try { - status = RegOpenKeyEx(helper_store_key, helper_name, 0, KEY_READ, &helper_info_key); - if (status != ERROR_SUCCESS) { - // Registry path is not present. - result = EBPF_FILE_NOT_FOUND; - goto Exit; - } + EBPF_LOG_ENTRY(); - // Read serialized helper prototype information. - char serialized_data[sizeof(ebpf_helper_function_prototype_t)] = {0}; - size_t expected_size = sizeof(helper_prototype->helper_id) + sizeof(helper_prototype->return_type) + - sizeof(helper_prototype->arguments); + status = RegOpenKeyEx(helper_store_key, helper_name, 0, KEY_READ, &helper_info_key); + if (status != ERROR_SUCCESS) { + // Registry path is not present. + result = EBPF_FILE_NOT_FOUND; + goto Exit; + } - status = ebpf_read_registry_value_binary( - helper_info_key, EBPF_HELPER_DATA_PROTOTYPE, (uint8_t*)serialized_data, expected_size); - if (status != ERROR_SUCCESS) { - result = win32_error_code_to_ebpf_result(status); - __analysis_assume(result != EBPF_SUCCESS); - goto Exit; - } + // Load extension header. + result = _load_extension_header(helper_info_key, &helper_prototype->header); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + // Read serialized helper prototype information. + result = ebpf_read_registry_value_binary( + helper_info_key, EBPF_HELPER_DATA_PROTOTYPE, (uint8_t*)serialized_data, expected_size); + if (result != ERROR_SUCCESS) { + goto Exit; + } - uint32_t offset = 0; - memcpy(&(helper_prototype->helper_id), serialized_data, sizeof(helper_prototype->helper_id)); - offset += sizeof(helper_prototype->helper_id); + memcpy(&(helper_prototype->helper_id), serialized_data, sizeof(helper_prototype->helper_id)); + offset += sizeof(helper_prototype->helper_id); - memcpy(&helper_prototype->return_type, serialized_data + offset, sizeof(helper_prototype->return_type)); - offset += sizeof(helper_prototype->return_type); + memcpy(&helper_prototype->return_type, serialized_data + offset, sizeof(helper_prototype->return_type)); + offset += sizeof(helper_prototype->return_type); - memcpy(&helper_prototype->arguments, serialized_data + offset, sizeof(helper_prototype->arguments)); - offset += sizeof(helper_prototype->arguments); + memcpy(&helper_prototype->arguments, serialized_data + offset, sizeof(helper_prototype->arguments)); + offset += sizeof(helper_prototype->arguments); + try { helper_prototype->name = cxplat_duplicate_string(ebpf_down_cast_from_wstring(std::wstring(helper_name)).c_str()); if (helper_prototype->name == nullptr) { result = EBPF_NO_MEMORY; goto Exit; } - } catch (...) { - result = EBPF_NO_MEMORY; + + } catch (std::exception& e) { + EBPF_LOG_MESSAGE_STRING( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_BASE, + "Failed to convert helper name to string:", + e.what()); + result = EBPF_FAILED; goto Exit; } @@ -81,11 +117,124 @@ _load_helper_prototype( if (helper_info_key) { ebpf_close_registry_key(static_cast(helper_info_key)); } - return result; + EBPF_RETURN_RESULT(result); } static ebpf_result_t -_load_program_data_information( +_ebpf_store_load_program_type_descriptor( + HKEY program_info_key, + _In_ const ebpf_program_type_t* program_type, + _Out_ ebpf_program_type_descriptor_t** program_type_descriptor) noexcept +{ + ebpf_result_t result = EBPF_SUCCESS; + HKEY program_type_descriptor_key = nullptr; + wchar_t* program_type_name = nullptr; + ebpf_context_descriptor_t* context_descriptor = nullptr; + uint32_t is_privileged = false; + uint32_t bpf_program_type = 0; + ebpf_program_type_descriptor_t* local_program_type_descriptor = nullptr; + std::string program_type_name_string; + + EBPF_LOG_ENTRY(); + + result = ebpf_open_registry_key( + program_info_key, + EBPF_PROGRAM_TYPE_DESCRIPTOR_REGISTRY_KEY, + KEY_READ, + (ebpf_store_key_t*)&program_type_descriptor_key); + if (result != EBPF_SUCCESS) { + // Registry path is not present. + result = EBPF_FILE_NOT_FOUND; + goto Exit; + } + + // Allocate the program type descriptor. + local_program_type_descriptor = + (ebpf_program_type_descriptor_t*)ebpf_allocate(sizeof(ebpf_program_type_descriptor_t)); + if (local_program_type_descriptor == nullptr) { + result = EBPF_NO_MEMORY; + goto Exit; + } + + // Load extension header. + result = _load_extension_header(program_type_descriptor_key, &local_program_type_descriptor->header); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + // Read the friendly program type name. + result = ebpf_read_registry_value_string(program_type_descriptor_key, EBPF_PROGRAM_DATA_NAME, &program_type_name); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + try { + program_type_name_string = (program_type_name != nullptr) + ? ebpf_down_cast_from_wstring(std::wstring(program_type_name)) + : ebpf_down_cast_from_wstring(std::wstring(L"")); + } catch (const std::exception& e) { + EBPF_LOG_MESSAGE_STRING( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_BASE, + "Failed to convert program type name to string:", + e.what()); + result = EBPF_FAILED; + goto Exit; + } + + // Allocate and read context descriptor. + context_descriptor = (ebpf_context_descriptor_t*)ebpf_allocate(sizeof(ebpf_context_descriptor_t)); + if (context_descriptor == nullptr) { + result = EBPF_NO_MEMORY; + goto Exit; + } + result = ebpf_read_registry_value_binary( + program_type_descriptor_key, + EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR, + (uint8_t*)context_descriptor, + sizeof(ebpf_context_descriptor_t)); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + // Read "is_privileged". + result = ebpf_read_registry_value_dword(program_type_descriptor_key, EBPF_PROGRAM_DATA_PRIVILEGED, &is_privileged); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + // Read bpf program type. + result = ebpf_read_registry_value_dword(program_type_descriptor_key, EBPF_DATA_BPF_PROG_TYPE, &bpf_program_type); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + // Populate the fields. + local_program_type_descriptor->name = cxplat_duplicate_string(program_type_name_string.c_str()); + if (local_program_type_descriptor->name == nullptr) { + result = EBPF_NO_MEMORY; + goto Exit; + } + local_program_type_descriptor->context_descriptor = context_descriptor; + context_descriptor = nullptr; + local_program_type_descriptor->is_privileged = !!is_privileged; + local_program_type_descriptor->bpf_prog_type = bpf_program_type; + local_program_type_descriptor->program_type = *program_type; + + *program_type_descriptor = local_program_type_descriptor; + local_program_type_descriptor = nullptr; +Exit: + ebpf_free(program_type_name); + ebpf_free(context_descriptor); + ebpf_free(local_program_type_descriptor); + if (program_type_descriptor_key) { + ebpf_close_registry_key(program_type_descriptor_key); + } + EBPF_RETURN_RESULT(result); +} + +static ebpf_result_t +_ebpf_store_load_program_information( HKEY program_data_key, _In_z_ const wchar_t* program_type_string, _Outptr_ ebpf_program_info_t** program_info) noexcept @@ -94,199 +243,164 @@ _load_program_data_information( ebpf_result_t result = EBPF_SUCCESS; HKEY program_info_key = nullptr; HKEY helper_key = nullptr; - wchar_t* program_type_name = nullptr; - ebpf_context_descriptor_t* descriptor = nullptr; - uint32_t is_privileged; - uint32_t bpf_program_type; ebpf_program_type_t* program_type = nullptr; ebpf_program_info_t* program_information = nullptr; + ebpf_program_type_descriptor_t* program_type_descriptor = nullptr; uint32_t helper_count; wchar_t* helper_name = nullptr; + EBPF_LOG_ENTRY(); + *program_info = nullptr; - try { - result = ebpf_open_registry_key( - program_data_key, program_type_string, KEY_READ, (ebpf_store_key_t*)&program_info_key); - if (result != EBPF_SUCCESS) { - // Registry path is not present. - result = EBPF_FILE_NOT_FOUND; - goto Exit; - } + result = + ebpf_open_registry_key(program_data_key, program_type_string, KEY_READ, (ebpf_store_key_t*)&program_info_key); + if (result != EBPF_SUCCESS) { + // Registry path is not present. + result = EBPF_FILE_NOT_FOUND; + goto Exit; + } - program_type = (ebpf_program_type_t*)ebpf_allocate(sizeof(ebpf_program_type_t)); - if (program_type == nullptr) { - result = EBPF_NO_MEMORY; - goto Exit; - } + // Allocate the program information struct. + program_information = (ebpf_program_info_t*)ebpf_allocate(sizeof(ebpf_program_info_t)); + if (program_information == nullptr) { + result = EBPF_NO_MEMORY; + goto Exit; + } - result = ebpf_convert_string_to_guid(program_type_string, program_type); - if (result != EBPF_SUCCESS) { - goto Exit; - } + // Load extension header. + result = _load_extension_header(program_info_key, &program_information->header); + if (result != EBPF_SUCCESS) { + goto Exit; + } - // Read the friendly program type name. - result = ebpf_read_registry_value_string(program_info_key, EBPF_PROGRAM_DATA_NAME, &program_type_name); - if (result != EBPF_SUCCESS) { - goto Exit; - } + // Allocate and read the program type GUID. + program_type = (ebpf_program_type_t*)ebpf_allocate(sizeof(ebpf_program_type_t)); + if (program_type == nullptr) { + result = EBPF_NO_MEMORY; + goto Exit; + } + result = ebpf_convert_string_to_guid(program_type_string, program_type); + if (result != EBPF_SUCCESS) { + goto Exit; + } - // Read context descriptor. - descriptor = (ebpf_context_descriptor_t*)ebpf_allocate(sizeof(ebpf_context_descriptor_t)); - if (descriptor == nullptr) { - result = EBPF_NO_MEMORY; - goto Exit; - } - result = ebpf_read_registry_value_binary( - program_info_key, - EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR, - (uint8_t*)descriptor, - sizeof(ebpf_context_descriptor_t)); - if (result != EBPF_SUCCESS) { + // Load program type descriptor. + result = _ebpf_store_load_program_type_descriptor(program_info_key, program_type, &program_type_descriptor); + if (result != EBPF_SUCCESS) { + goto Exit; + } + program_information->program_type_descriptor = const_cast(program_type_descriptor); + + // Read helper count. + result = ebpf_read_registry_value_dword(program_info_key, EBPF_PROGRAM_DATA_HELPER_COUNT, &helper_count); + if (result != EBPF_SUCCESS) { + goto Exit; + } + + if (helper_count > 0) { + // Read the helper functions prototypes. + status = RegOpenKeyEx(program_info_key, EBPF_PROGRAM_DATA_HELPERS_REGISTRY_KEY, 0, KEY_READ, &helper_key); + if (status != ERROR_SUCCESS) { + // Registry path is not present. + result = EBPF_FILE_NOT_FOUND; goto Exit; } - // Read "is_privileged". - result = ebpf_read_registry_value_dword(program_info_key, EBPF_PROGRAM_DATA_PRIVILEGED, &is_privileged); - if (result != EBPF_SUCCESS) { + uint32_t max_helper_name_size; + uint32_t max_helpers_count; + uint32_t key_size; + // Get the size of the largest subkey. + status = RegQueryInfoKey( + helper_key, + nullptr, + nullptr, + nullptr, + (unsigned long*)&max_helpers_count, + (unsigned long*)&max_helper_name_size, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr, + nullptr); + if (status != ERROR_SUCCESS) { + result = EBPF_FILE_NOT_FOUND; goto Exit; } - // Read bpf program type. - result = ebpf_read_registry_value_dword(program_info_key, EBPF_DATA_BPF_PROG_TYPE, &bpf_program_type); - if (result != EBPF_SUCCESS) { + if (max_helpers_count != helper_count) { + result = EBPF_INVALID_ARGUMENT; goto Exit; } - - // Read helper count. - result = ebpf_read_registry_value_dword(program_info_key, EBPF_PROGRAM_DATA_HELPER_COUNT, &helper_count); - if (result != EBPF_SUCCESS) { + if (max_helper_name_size == 0) { + result = EBPF_INVALID_ARGUMENT; goto Exit; } - auto program_type_name_string = (program_type_name != nullptr) - ? ebpf_down_cast_from_wstring(std::wstring(program_type_name)) - : ebpf_down_cast_from_wstring(std::wstring(L"")); - - program_information = (ebpf_program_info_t*)ebpf_allocate(sizeof(ebpf_program_info_t)); - if (program_information == nullptr) { + ebpf_helper_function_prototype_t* helper_prototype = + (ebpf_helper_function_prototype_t*)ebpf_allocate(helper_count * sizeof(ebpf_helper_function_prototype_t)); + if (helper_prototype == nullptr) { result = EBPF_NO_MEMORY; goto Exit; } + program_information->program_type_specific_helper_prototype = helper_prototype; - program_information->program_type_descriptor.name = cxplat_duplicate_string(program_type_name_string.c_str()); - if (program_information->program_type_descriptor.name == nullptr) { + // Add space for null terminator. + max_helper_name_size += 1; + + helper_name = (wchar_t*)ebpf_allocate(max_helper_name_size * sizeof(wchar_t)); + if (helper_name == nullptr) { result = EBPF_NO_MEMORY; goto Exit; } - program_information->program_type_descriptor.context_descriptor = descriptor; - descriptor = nullptr; - program_information->program_type_descriptor.is_privileged = !!is_privileged; - program_information->program_type_descriptor.bpf_prog_type = bpf_program_type; - program_information->program_type_descriptor.program_type = *program_type; - - if (helper_count > 0) { - // Read the helper functions prototypes. - status = RegOpenKeyEx(program_info_key, EBPF_PROGRAM_DATA_HELPERS_REGISTRY_PATH, 0, KEY_READ, &helper_key); - if (status != ERROR_SUCCESS) { - // Registry path is not present. - result = EBPF_FILE_NOT_FOUND; - goto Exit; - } - uint32_t max_helper_name_size; - uint32_t max_helpers_count; - uint32_t key_size; - // Get the size of the largest subkey. - status = RegQueryInfoKey( - helper_key, - nullptr, - nullptr, - nullptr, - (unsigned long*)&max_helpers_count, - (unsigned long*)&max_helper_name_size, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr, - nullptr); + for (uint32_t index = 0; index < max_helpers_count; index++) { + memset(helper_name, 0, (max_helper_name_size) * sizeof(wchar_t)); + key_size = (max_helper_name_size - 1) * sizeof(wchar_t); + status = RegEnumKeyEx( + helper_key, index, helper_name, (unsigned long*)&key_size, nullptr, nullptr, nullptr, nullptr); if (status != ERROR_SUCCESS) { - result = EBPF_FILE_NOT_FOUND; - goto Exit; - } - - if (max_helpers_count != helper_count) { - result = EBPF_INVALID_ARGUMENT; - goto Exit; - } - if (max_helper_name_size == 0) { - result = EBPF_INVALID_ARGUMENT; - goto Exit; - } - - ebpf_helper_function_prototype_t* helper_prototype = (ebpf_helper_function_prototype_t*)ebpf_allocate( - helper_count * sizeof(ebpf_helper_function_prototype_t)); - if (helper_prototype == nullptr) { - result = EBPF_NO_MEMORY; + result = win32_error_code_to_ebpf_result(status); goto Exit; } - program_information->program_type_specific_helper_prototype = helper_prototype; - // Add space for null terminator. - max_helper_name_size += 1; - - helper_name = (wchar_t*)ebpf_allocate(max_helper_name_size * sizeof(wchar_t)); - if (helper_name == nullptr) { - result = EBPF_NO_MEMORY; + result = _ebpf_store_load_helper_prototype(helper_key, helper_name, &helper_prototype[index]); + if (result != EBPF_SUCCESS) { goto Exit; } - - for (uint32_t index = 0; index < max_helpers_count; index++) { - memset(helper_name, 0, (max_helper_name_size) * sizeof(wchar_t)); - key_size = (max_helper_name_size - 1) * sizeof(wchar_t); - status = RegEnumKeyEx( - helper_key, index, helper_name, (unsigned long*)&key_size, nullptr, nullptr, nullptr, nullptr); - if (status != ERROR_SUCCESS) { - result = win32_error_code_to_ebpf_result(status); - goto Exit; - } - - result = _load_helper_prototype(helper_key, helper_name, &helper_prototype[index]); - if (result != EBPF_SUCCESS) { - goto Exit; - } - } - - program_information->count_of_program_type_specific_helpers = helper_count; } - *program_info = program_information; - } catch (...) { - result = EBPF_FAILED; + program_information->count_of_program_type_specific_helpers = helper_count; + } + + // Validate the program information struct. + if (!ebpf_validate_program_info((const ebpf_program_info_t*)program_information)) { + result = EBPF_INVALID_ARGUMENT; goto Exit; } + *program_info = program_information; + program_information = nullptr; + Exit: ebpf_free(helper_name); if (result != EBPF_SUCCESS) { - ebpf_free(descriptor); ebpf_program_info_free(program_information); } if (program_info_key) { ebpf_close_registry_key(program_info_key); } - ebpf_free(program_type_name); ebpf_free(program_type); if (helper_key) { ebpf_close_registry_key(helper_key); } - return result; + EBPF_RETURN_RESULT(result); } _Must_inspect_result_ ebpf_result_t -ebpf_store_load_program_information( +ebpf_store_load_program_data( _Outptr_result_buffer_maybenull_(*program_info_count) ebpf_program_info_t*** program_info, _Out_ uint32_t* program_info_count) { @@ -299,6 +413,8 @@ ebpf_store_load_program_information( ebpf_store_key_t store_key = nullptr; std::vector program_info_array; + EBPF_LOG_ENTRY(); + *program_info = nullptr; *program_info_count = 0; @@ -312,7 +428,7 @@ ebpf_store_load_program_information( // Open program data registry path. result = ebpf_open_registry_key( - store_key, EBPF_PROGRAM_DATA_REGISTRY_PATH, KEY_READ, (ebpf_store_key_t*)&program_data_key); + store_key, EBPF_PROGRAM_DATA_REGISTRY_KEY, KEY_READ, (ebpf_store_key_t*)&program_data_key); if (result != EBPF_SUCCESS) { if (result == EBPF_FILE_NOT_FOUND) { result = EBPF_SUCCESS; @@ -340,8 +456,14 @@ ebpf_store_load_program_information( } ebpf_program_info_t* local_program_info = nullptr; - result = _load_program_data_information(program_data_key, program_type_key, &local_program_info); - if (result == EBPF_SUCCESS) { + result = _ebpf_store_load_program_information(program_data_key, program_type_key, &local_program_info); + if (result != EBPF_SUCCESS) { + EBPF_LOG_MESSAGE_WSTRING( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_BASE, + "Failed to load program data from store.", + program_type_key); + } else { program_info_array.push_back(local_program_info); } result = EBPF_SUCCESS; @@ -380,7 +502,7 @@ ebpf_store_load_program_information( ebpf_close_registry_key(program_data_key); } - return result; + EBPF_RETURN_RESULT(result); } static ebpf_result_t @@ -398,6 +520,8 @@ _load_section_data_information( char* section_prefix = nullptr; ebpf_section_definition_t* section_information = nullptr; + EBPF_LOG_ENTRY(); + try { result = ebpf_open_registry_key(section_data_key, section_name, KEY_READ, (ebpf_store_key_t*)§ion_info_key); if (result != EBPF_SUCCESS) { @@ -485,7 +609,7 @@ _load_section_data_information( if (section_info_key) { ebpf_close_registry_key(section_info_key); } - return result; + EBPF_RETURN_RESULT(result); } _Must_inspect_result_ ebpf_result_t @@ -502,6 +626,8 @@ ebpf_store_load_section_information( ebpf_store_key_t store_key = nullptr; std::vector section_info_array; + EBPF_LOG_ENTRY(); + *section_info = nullptr; *section_info_count = 0; @@ -513,7 +639,7 @@ ebpf_store_load_section_information( goto Exit; } - status = RegOpenKeyEx(static_cast(store_key), EBPF_SECTIONS_REGISTRY_PATH, 0, KEY_READ, §ion_data_key); + status = RegOpenKeyEx(static_cast(store_key), EBPF_SECTIONS_REGISTRY_KEY, 0, KEY_READ, §ion_data_key); if (status != ERROR_SUCCESS) { if (status != ERROR_FILE_NOT_FOUND) { result = win32_error_code_to_ebpf_result(status); @@ -581,7 +707,7 @@ ebpf_store_load_section_information( if (section_data_key) { ebpf_close_registry_key(section_data_key); } - return result; + EBPF_RETURN_RESULT(result); } _Must_inspect_result_ ebpf_result_t @@ -600,6 +726,8 @@ ebpf_store_load_global_helper_information( uint32_t index = 0; ebpf_store_key_t store_key = nullptr; + EBPF_LOG_ENTRY(); + *global_helper_info = nullptr; *global_helper_info_count = 0; @@ -613,7 +741,7 @@ ebpf_store_load_global_helper_information( // Open program data registry path. result = ebpf_open_registry_key( - store_key, EBPF_GLOBAL_HELPERS_REGISTRY_PATH, KEY_READ, (ebpf_store_key_t*)&global_helpers_key); + store_key, EBPF_GLOBAL_HELPERS_REGISTRY_KEY, KEY_READ, (ebpf_store_key_t*)&global_helpers_key); if (result != EBPF_SUCCESS) { if (result == EBPF_FILE_NOT_FOUND) { result = EBPF_SUCCESS; @@ -676,7 +804,7 @@ ebpf_store_load_global_helper_information( goto Exit; } - result = _load_helper_prototype(global_helpers_key, helper_name, &(helper_prototype[index])); + result = _ebpf_store_load_helper_prototype(global_helpers_key, helper_name, &(helper_prototype[index])); if (result != EBPF_SUCCESS) { goto Exit; } @@ -698,7 +826,7 @@ ebpf_store_load_global_helper_information( } } ebpf_free(helper_name); - return result; + EBPF_RETURN_RESULT(result); } _Must_inspect_result_ ebpf_result_t @@ -708,6 +836,8 @@ ebpf_store_clear(_In_ const ebpf_store_key_t root_key_path) ebpf_store_key_t provider_handle = {0}; ebpf_result_t result = EBPF_FAILED; + EBPF_LOG_ENTRY(); + // Open root registry key. result = ebpf_open_registry_key(root_key_path, EBPF_ROOT_RELATIVE_PATH, REG_CREATE_FLAGS, &root_handle); if (result != EBPF_SUCCESS) { @@ -718,7 +848,7 @@ ebpf_store_clear(_In_ const ebpf_store_key_t root_key_path) } // Open "providers" registry key. - result = ebpf_open_registry_key(root_handle, EBPF_PROVIDERS_REGISTRY_PATH, REG_CREATE_FLAGS, &provider_handle); + result = ebpf_open_registry_key(root_handle, EBPF_PROVIDERS_REGISTRY_KEY, REG_CREATE_FLAGS, &provider_handle); if (result != EBPF_SUCCESS) { if (result == EBPF_FILE_NOT_FOUND) { result = EBPF_SUCCESS; @@ -734,7 +864,7 @@ ebpf_store_clear(_In_ const ebpf_store_key_t root_key_path) ebpf_close_registry_key(provider_handle); provider_handle = nullptr; - result = ebpf_delete_registry_key(root_handle, EBPF_PROVIDERS_REGISTRY_PATH); + result = ebpf_delete_registry_key(root_handle, EBPF_PROVIDERS_REGISTRY_KEY); if (result != EBPF_SUCCESS) { goto Exit; } @@ -749,7 +879,7 @@ ebpf_store_clear(_In_ const ebpf_store_key_t root_key_path) ebpf_close_registry_key(root_handle); } - return result; + EBPF_RETURN_RESULT(result); } ebpf_result_t @@ -760,6 +890,9 @@ ebpf_store_delete_global_helper_information(_In_ ebpf_helper_function_prototype_ ebpf_store_key_t provider_key = NULL; ebpf_store_key_t helper_info_key = NULL; wchar_t* helper_name = ebpf_get_wstring_from_string(helper_info->name); + + EBPF_LOG_ENTRY(); + if (helper_name == nullptr) { result = EBPF_NO_MEMORY; goto Exit; @@ -775,7 +908,7 @@ ebpf_store_delete_global_helper_information(_In_ ebpf_helper_function_prototype_ } // Open "providers" registry key. - result = ebpf_open_registry_key(root_key, EBPF_PROVIDERS_REGISTRY_PATH, REG_CREATE_FLAGS, &provider_key); + result = ebpf_open_registry_key(root_key, EBPF_PROVIDERS_REGISTRY_KEY, REG_CREATE_FLAGS, &provider_key); if (result != EBPF_SUCCESS) { if (result == EBPF_FILE_NOT_FOUND) { result = EBPF_SUCCESS; @@ -784,8 +917,7 @@ ebpf_store_delete_global_helper_information(_In_ ebpf_helper_function_prototype_ } // Open (or create) global helpers key. - result = - ebpf_open_registry_key(provider_key, EBPF_GLOBAL_HELPERS_REGISTRY_PATH, REG_DELETE_FLAGS, &helper_info_key); + result = ebpf_open_registry_key(provider_key, EBPF_GLOBAL_HELPERS_REGISTRY_KEY, REG_DELETE_FLAGS, &helper_info_key); if (result != EBPF_SUCCESS) { if (result == EBPF_FILE_NOT_FOUND) { result = EBPF_SUCCESS; @@ -803,5 +935,5 @@ ebpf_store_delete_global_helper_information(_In_ ebpf_helper_function_prototype_ ebpf_close_registry_key(helper_info_key); ebpf_close_registry_key(provider_key); - return result; + EBPF_RETURN_RESULT(result); } \ No newline at end of file diff --git a/libs/api_common/store_helper_internal.h b/libs/api_common/store_helper_internal.h index 5387a73cac..8820799be0 100644 --- a/libs/api_common/store_helper_internal.h +++ b/libs/api_common/store_helper_internal.h @@ -6,7 +6,7 @@ #include "windows_program_type.h" _Must_inspect_result_ ebpf_result_t -ebpf_store_load_program_information( +ebpf_store_load_program_data( _Outptr_result_buffer_maybenull_(*program_info_count) ebpf_program_info_t*** program_info, _Out_ uint32_t* program_info_count); diff --git a/libs/api_common/windows_helpers.cpp b/libs/api_common/windows_helpers.cpp index 7c0d877f23..7a6db836c2 100644 --- a/libs/api_common/windows_helpers.cpp +++ b/libs/api_common/windows_helpers.cpp @@ -47,7 +47,10 @@ get_helper_prototype_windows(int32_t n) } EbpfHelperPrototype verifier_prototype = {0}; - verifier_prototype.context_descriptor = info->program_type_descriptor.context_descriptor; + if (info->program_type_descriptor == nullptr) { + throw std::runtime_error(std::string("program type descriptor not found.")); + } + verifier_prototype.context_descriptor = info->program_type_descriptor->context_descriptor; const ebpf_helper_function_prototype_t* raw_prototype = _get_helper_function_prototype(info, n); if (raw_prototype == nullptr) { diff --git a/libs/api_common/windows_platform_common.cpp b/libs/api_common/windows_platform_common.cpp index 9077b17931..df51ff1a58 100644 --- a/libs/api_common/windows_platform_common.cpp +++ b/libs/api_common/windows_platform_common.cpp @@ -23,7 +23,7 @@ #include #include -#define GET_PROGRAM_INFO_REPLY_BUFFER_SIZE 2048 +#define GET_PROGRAM_INFO_REPLY_BUFFER_SIZE 4096 static thread_local ebpf_handle_t _program_under_verification = ebpf_handle_invalid; @@ -137,7 +137,17 @@ _get_program_descriptor_from_info(_In_ const ebpf_program_info_t* info, _Outptr_ goto Exit; } - name = cxplat_duplicate_string(info->program_type_descriptor.name); + if (info->program_type_descriptor == nullptr) { + result = EBPF_INVALID_ARGUMENT; + goto Exit; + } + + if (info->program_type_descriptor->context_descriptor == nullptr) { + result = EBPF_INVALID_ARGUMENT; + goto Exit; + } + + name = cxplat_duplicate_string(info->program_type_descriptor->name); if (name == nullptr) { result = EBPF_NO_MEMORY; goto Exit; @@ -150,16 +160,16 @@ _get_program_descriptor_from_info(_In_ const ebpf_program_info_t* info, _Outptr_ } memcpy( (void*)type->context_descriptor, - info->program_type_descriptor.context_descriptor, + info->program_type_descriptor->context_descriptor, sizeof(ebpf_context_descriptor_t)); ebpf_program_type_t* program_type = (ebpf_program_type_t*)ebpf_allocate(sizeof(ebpf_program_type_t)); if (program_type == nullptr) { result = EBPF_NO_MEMORY; goto Exit; } - *program_type = info->program_type_descriptor.program_type; + *program_type = info->program_type_descriptor->program_type; type->platform_specific_data = (uint64_t)program_type; - type->is_privileged = info->program_type_descriptor.is_privileged; + type->is_privileged = info->program_type_descriptor->is_privileged; *descriptor = type; } catch (...) { @@ -285,7 +295,7 @@ get_ebpf_program_type(bpf_prog_type_t bpf_program_type) _load_ebpf_provider_data(); for (auto const& [key, value] : _windows_program_information) { - if (value.get()->program_type_descriptor.bpf_prog_type == (uint32_t)bpf_program_type) { + if (value.get()->program_type_descriptor->bpf_prog_type == (uint32_t)bpf_program_type) { return &key; } } @@ -314,7 +324,7 @@ get_bpf_program_type(_In_ const ebpf_program_type_t* ebpf_program_type) noexcept for (auto const& [key, value] : _windows_program_information) { if (IsEqualGUID(*ebpf_program_type, key)) { - return (bpf_prog_type_t)value.get()->program_type_descriptor.bpf_prog_type; + return (bpf_prog_type_t)value.get()->program_type_descriptor->bpf_prog_type; } } @@ -662,7 +672,7 @@ _load_all_program_data_information() ebpf_program_info_t** program_info = nullptr; uint32_t program_info_count = 0; - result = ebpf_store_load_program_information(&program_info, &program_info_count); + result = ebpf_store_load_program_data(&program_info, &program_info_count); if (result != EBPF_SUCCESS) { goto Exit; } @@ -676,7 +686,7 @@ _load_all_program_data_information() for (uint32_t index = 0; index < program_info_count; index++) { ebpf_program_info_t* info = program_info[index]; program_info[index] = nullptr; - ebpf_program_type_t program_type = info->program_type_descriptor.program_type; + ebpf_program_type_t program_type = info->program_type_descriptor->program_type; _windows_program_information[program_type] = ebpf_program_info_ptr_t(info); EbpfProgramType* program_data = nullptr; diff --git a/libs/execution_context/ebpf_core.c b/libs/execution_context/ebpf_core.c index c1aa32a822..9409f857da 100644 --- a/libs/execution_context/ebpf_core.c +++ b/libs/execution_context/ebpf_core.c @@ -101,7 +101,21 @@ _ebpf_core_memmove( #define EBPF_CORE_GLOBAL_HELPER_EXTENSION_VERSION 0 -static ebpf_program_info_t _ebpf_global_helper_program_info = {{"global_helper", NULL, {0}}, 0, NULL}; +static ebpf_program_type_descriptor_t _ebpf_global_helper_program_descriptor = { + EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, + EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE, + "global_helper", + NULL, + {0}, + 0, + 0}; +static ebpf_program_info_t _ebpf_global_helper_program_info = { + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_ebpf_global_helper_program_descriptor, + 0, + NULL, + 0, + NULL}; // Order of elements in this table must match the order of the elements in ebpf_core_helper_function_prototype. static const void* _ebpf_general_helpers[] = { @@ -137,14 +151,13 @@ static const void* _ebpf_general_helpers[] = { }; static const ebpf_helper_function_addresses_t _ebpf_global_helper_function_dispatch_table = { - EBPF_COUNT_OF(_ebpf_general_helpers), (uint64_t*)_ebpf_general_helpers}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_ebpf_general_helpers), + (uint64_t*)_ebpf_general_helpers}; static const ebpf_program_data_t _ebpf_global_helper_function_program_data = { - &_ebpf_global_helper_program_info, &_ebpf_global_helper_function_dispatch_table}; - -static const ebpf_extension_data_t _ebpf_global_helper_function_extension_data = { - EBPF_CORE_GLOBAL_HELPER_EXTENSION_VERSION, - sizeof(_ebpf_global_helper_function_program_data), - &_ebpf_global_helper_function_program_data}; + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, + &_ebpf_global_helper_program_info, + &_ebpf_global_helper_function_dispatch_table}; static NPI_PROVIDER_ATTACH_CLIENT_FN _ebpf_general_helper_function_provider_attach_client; static NPI_PROVIDER_DETACH_CLIENT_FN _ebpf_general_helper_function_provider_detach_client; @@ -156,12 +169,12 @@ static const NPI_PROVIDER_CHARACTERISTICS _ebpf_global_helper_function_provider_ _ebpf_general_helper_function_provider_detach_client, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + EBPF_PROGRAM_DATA_CURRENT_VERSION, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_PROGRAM_INFO_EXTENSION_IID, &ebpf_general_helper_function_module_id, 0, - &_ebpf_global_helper_function_extension_data, + &_ebpf_global_helper_function_program_data, }, }; diff --git a/libs/execution_context/ebpf_general_helpers.c b/libs/execution_context/ebpf_general_helpers.c index 4051ca79d1..5a15fea84a 100644 --- a/libs/execution_context/ebpf_general_helpers.c +++ b/libs/execution_context/ebpf_general_helpers.c @@ -11,34 +11,56 @@ #include "ebpf_structs.h" ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = { - {BPF_FUNC_map_lookup_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_lookup_elem, "bpf_map_lookup_elem", EBPF_RETURN_TYPE_PTR_TO_MAP_VALUE_OR_NULL, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY}}, - {BPF_FUNC_map_update_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_update_elem, "bpf_map_update_elem", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_VALUE, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_map_delete_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_delete_elem, "bpf_map_delete_elem", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY}}, - {BPF_FUNC_map_lookup_and_delete_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_lookup_and_delete_elem, "bpf_map_lookup_and_delete_elem", EBPF_RETURN_TYPE_PTR_TO_MAP_VALUE_OR_NULL, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY}}, - {BPF_FUNC_tail_call, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_tail_call, "bpf_tail_call", EBPF_RETURN_TYPE_INTEGER_OR_NO_RETURN_IF_SUCCEED, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_OF_PROGRAMS, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_get_prandom_u32, "bpf_get_prandom_u32", EBPF_RETURN_TYPE_INTEGER, {0}}, - {BPF_FUNC_ktime_get_boot_ns, "bpf_ktime_get_boot_ns", EBPF_RETURN_TYPE_INTEGER, {0}}, - {BPF_FUNC_get_smp_processor_id, "bpf_get_smp_processor_id", EBPF_RETURN_TYPE_INTEGER, {0}}, - {BPF_FUNC_ktime_get_ns, "bpf_ktime_get_ns", EBPF_RETURN_TYPE_INTEGER, {0}}, - {BPF_FUNC_csum_diff, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_get_prandom_u32, + "bpf_get_prandom_u32", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_ktime_get_boot_ns, + "bpf_ktime_get_boot_ns", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_get_smp_processor_id, + "bpf_get_smp_processor_id", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_ktime_get_ns, + "bpf_ktime_get_ns", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_csum_diff, "bpf_csum_diff", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM_OR_NULL, @@ -46,29 +68,34 @@ ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = { EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM_OR_NULL, EBPF_ARGUMENT_TYPE_CONST_SIZE_OR_ZERO, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_ringbuf_output, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_ringbuf_output, "bpf_ringbuf_output", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_trace_printk2, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_trace_printk2, "bpf_trace_printk2", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE}}, - {BPF_FUNC_trace_printk3, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_trace_printk3, "bpf_trace_printk3", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_trace_printk4, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_trace_printk4, "bpf_trace_printk4", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE, EBPF_ARGUMENT_TYPE_ANYTHING, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_trace_printk5, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_trace_printk5, "bpf_trace_printk5", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, @@ -76,25 +103,38 @@ ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = { EBPF_ARGUMENT_TYPE_ANYTHING, EBPF_ARGUMENT_TYPE_ANYTHING, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_map_push_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_push_elem, "bpf_map_push_elem", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_VALUE, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_map_pop_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_pop_elem, "bpf_map_pop_elem", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_VALUE}}, - {BPF_FUNC_map_peek_elem, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_map_peek_elem, "bpf_map_peek_elem", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_VALUE}}, - {BPF_FUNC_get_current_pid_tgid, "bpf_get_current_pid_tgid", EBPF_RETURN_TYPE_INTEGER, {0}}, - {BPF_FUNC_get_current_logon_id, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_get_current_pid_tgid, + "bpf_get_current_pid_tgid", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_get_current_logon_id, "bpf_get_current_logon_id", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, - {BPF_FUNC_is_current_admin, "bpf_is_current_admin", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, - {BPF_FUNC_memcpy, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_is_current_admin, + "bpf_is_current_admin", + EBPF_RETURN_TYPE_INTEGER, + {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_memcpy, "bpf_memcpy", EBPF_RETURN_TYPE_INTEGER, { @@ -103,7 +143,8 @@ ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = { EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE_OR_ZERO, }}, - {BPF_FUNC_memcmp, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_memcmp, "bpf_memcmp", EBPF_RETURN_TYPE_INTEGER, { @@ -112,11 +153,13 @@ ebpf_helper_function_prototype_t ebpf_core_helper_function_prototype_array[] = { EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE_OR_ZERO, }}, - {BPF_FUNC_memset, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_memset, "bpf_memset", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_WRITABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE_OR_ZERO, EBPF_ARGUMENT_TYPE_ANYTHING}}, - {BPF_FUNC_memmove, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_memmove, "bpf_memmove", EBPF_RETURN_TYPE_INTEGER, { diff --git a/libs/execution_context/ebpf_link.c b/libs/execution_context/ebpf_link.c index 419fb2efed..662301ebba 100644 --- a/libs/execution_context/ebpf_link.c +++ b/libs/execution_context/ebpf_link.c @@ -59,7 +59,7 @@ static const NPI_CLIENT_CHARACTERISTICS _ebpf_link_client_characteristics = { _ebpf_link_client_detach_provider, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + EBPF_ATTACH_CLIENT_DATA_CURRENT_VERSION, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_HOOK_EXTENSION_IID, NULL, @@ -91,8 +91,9 @@ _ebpf_link_instance_invoke_batch_end(_In_ const void* extension_client_binding_c typedef enum _ebpf_link_dispatch_table_version { - EBPF_LINK_DISPATCH_TABLE_VERSION_1 = 1, ///< Initial version of the dispatch table. - EBPF_LINK_DISPATCH_TABLE_VERSION = EBPF_LINK_DISPATCH_TABLE_VERSION_1, ///< Current version of the dispatch table. + EBPF_LINK_DISPATCH_TABLE_CURRENT_VERSION = 1, ///< Initial version of the dispatch table. + EBPF_LINK_DISPATCH_TABLE_VERSION = + EBPF_LINK_DISPATCH_TABLE_CURRENT_VERSION, ///< Current version of the dispatch table. } ebpf_link_dispatch_table_version_t; static const ebpf_extension_program_dispatch_table_t _ebpf_link_dispatch_table = { @@ -121,8 +122,8 @@ _ebpf_link_client_attach_provider( ebpf_link_t* link = (ebpf_link_t*)client_context; void* provider_binding_context; void* provider_dispatch; - const ebpf_extension_data_t* provider_data = - (const ebpf_extension_data_t*)provider_registration_instance->NpiSpecificCharacteristics; + const ebpf_attach_provider_data_t* attach_provider_data = + (const ebpf_attach_provider_data_t*)provider_registration_instance->NpiSpecificCharacteristics; bool lock_held = false; @@ -132,21 +133,19 @@ _ebpf_link_client_attach_provider( UNREFERENCED_PARAMETER(nmr_binding_handle); // Verify that that the provider is using the same version of the extension as the client. - if (provider_data->version > EBPF_ATTACH_PROVIDER_DATA_VERSION || - provider_data->size < sizeof(ebpf_extension_data_t)) { + if (attach_provider_data->header.version > EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION || + attach_provider_data->header.size < sizeof(ebpf_attach_provider_data_t)) { EBPF_LOG_MESSAGE_UINT64_UINT64( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_LINK, "Attach provider data version is not compatible.", - provider_data->version, - provider_data->size); + attach_provider_data->header.version, + attach_provider_data->header.size); status = STATUS_INVALID_PARAMETER; goto Done; } - ebpf_attach_provider_data_t* attach_provider_data = (ebpf_attach_provider_data_t*)provider_data->data; - if (provider_registration_instance->ModuleId->Type != MIT_GUID) { EBPF_LOG_MESSAGE( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_LINK, "Attach provider ModuleId type is not GUID."); @@ -252,7 +251,7 @@ ebpf_link_create( ebpf_lock_state_t state = ebpf_lock_lock(&local_link->lock); lock_held = true; - local_link->client_data.size = context_data_length; + local_link->client_data.header.size = context_data_length; if (context_data_length > 0) { local_link->client_data.data = ebpf_allocate_with_tag(context_data_length, EBPF_POOL_TAG_LINK); @@ -440,7 +439,7 @@ ebpf_link_detach_program(_Inout_ ebpf_link_t* link) ebpf_free((void*)link->client_data.data); link->client_data.data = NULL; - link->client_data.size = 0; + link->client_data.header.size = 0; link->program = NULL; Done: @@ -575,8 +574,8 @@ ebpf_link_get_info( // Copy any additional parameters. size_t size = sizeof(struct bpf_link_info) - FIELD_OFFSET(struct bpf_link_info, attach_data); - if ((link->client_data.size > 0) && (link->client_data.size <= size)) { - memcpy(&info->attach_data, link->client_data.data, link->client_data.size); + if ((link->client_data.header.size > 0) && (link->client_data.header.size <= size)) { + memcpy(&info->attach_data, link->client_data.data, link->client_data.header.size); } ebpf_lock_unlock((ebpf_lock_t*)&link->lock, state); diff --git a/libs/execution_context/ebpf_native.c b/libs/execution_context/ebpf_native.c index 35291779ba..9b913906ff 100644 --- a/libs/execution_context/ebpf_native.c +++ b/libs/execution_context/ebpf_native.c @@ -121,7 +121,7 @@ static const NPI_PROVIDER_CHARACTERISTICS _ebpf_native_provider_characteristics _ebpf_native_provider_detach_client_callback, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + 0, sizeof(NPI_REGISTRATION_INSTANCE), &_ebpf_native_npi_id, &_ebpf_native_provider_module_id, diff --git a/libs/execution_context/ebpf_program.c b/libs/execution_context/ebpf_program.c index f82f017bf7..2e198bc5e4 100644 --- a/libs/execution_context/ebpf_program.c +++ b/libs/execution_context/ebpf_program.c @@ -15,6 +15,7 @@ #include "ebpf_program.h" #include "ebpf_program_attach_type_guids.h" #include "ebpf_program_types.h" +#include "ebpf_shared_framework.h" #include "ebpf_state.h" #include "ebpf_tracelog.h" #include "ubpf.h" @@ -60,8 +61,8 @@ typedef struct _ebpf_program EX_RUNDOWN_REF program_information_rundown_reference; - const ebpf_extension_data_t* general_helper_provider_data; - const ebpf_extension_data_t* info_extension_provider_data; + const ebpf_program_data_t* general_helper_program_data; + const ebpf_program_data_t* extension_program_data; bpf_prog_type_t bpf_prog_type; @@ -104,7 +105,7 @@ static const NPI_CLIENT_CHARACTERISTICS _ebpf_program_general_program_informatio _ebpf_program_general_program_information_detach_provider, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + EBPF_PROGRAM_INFORMATION_CLIENT_DATA_CURRENT_VERSION, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_PROGRAM_INFO_EXTENSION_IID, NULL, @@ -123,7 +124,7 @@ static const NPI_CLIENT_CHARACTERISTICS _ebpf_program_type_specific_program_info _ebpf_program_type_specific_program_information_detach_provider, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + EBPF_PROGRAM_INFORMATION_CLIENT_DATA_CURRENT_VERSION, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_PROGRAM_INFO_EXTENSION_IID, NULL, @@ -182,61 +183,142 @@ _IRQL_requires_max_(PASSIVE_LEVEL) static ebpf_result_t _ebpf_program_compute_pr _In_ const uint32_t* actual_helper_ids, size_t count_of_actual_helper_ids, _In_ const ebpf_program_data_t* general_program_information_data, - _In_ const ebpf_program_data_t* type_specific_program_information_data, + _In_ const ebpf_program_data_t* extension_program_data, _In_ const cxplat_utf8_string_t* hash_algorithm, _Outptr_ uint8_t** hash, _Out_ size_t* hash_length); +static bool +_ebpf_program_match_provider_data_module_id(_In_ const PNPI_MODULEID npi_module_id, _In_ const GUID* expected_module_id) +{ + bool match = false; + // Verify the NPI module ID is a GUID. + if (npi_module_id->Type != MIT_GUID) { + EBPF_LOG_MESSAGE( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "Program information provider module ID type mismatch."); + goto Done; + } + + // Check if the provider module ID matches the expected module ID. + if (memcmp(&npi_module_id->Guid, expected_module_id, sizeof(GUID)) != 0) { + // This is expected as the attach callback will be called for each provider of NPI + // EBPF_PROGRAM_INFO_EXTENSION_IID. + goto Done; + } + match = true; +Done: + return match; +} + +enum ebpf_program_info_provider_type +{ + EBPF_PROGRAM_INFO_PROVIDER_TYPE_EXTENSION, + EBPF_PROGRAM_INFO_PROVIDER_TYPE_GENERAL_HELPER +}; + +static bool +_ebpf_program_verify_provider_program_data( + _In_ enum ebpf_program_info_provider_type provider_type, + _In_ const PNPI_MODULEID npi_module_id, + _In_opt_ const ebpf_program_data_t* program_data) +{ + bool program_data_valid = false; + bool is_general_helper_program_data = (provider_type == EBPF_PROGRAM_INFO_PROVIDER_TYPE_GENERAL_HELPER); + + // Verify that the program data is present. + if (program_data == NULL) { + EBPF_LOG_MESSAGE( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "The program information provider data is not present."); + goto Done; + } + + // Perform validation of the program data. + if (!is_general_helper_program_data) { + if (!ebpf_validate_program_data(program_data)) { + EBPF_LOG_MESSAGE( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "Program data provided by the extension is not valid."); + goto Done; + } + if (program_data->required_irql > HIGH_LEVEL) { + EBPF_LOG_MESSAGE_GUID( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "An extension cannot have required_irql higher than HIGH_LEVEL", + &npi_module_id->Guid); + goto Done; + } + + if ((program_data->program_type_specific_helper_function_addresses) && + program_data->program_type_specific_helper_function_addresses->helper_function_count != + program_data->program_info->count_of_program_type_specific_helpers) { + EBPF_LOG_MESSAGE_GUID( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "An extension cannot have a mismatch between the number of helper functions and the number of helper " + "function addresses", + &npi_module_id->Guid); + goto Done; + } + + if ((program_data->global_helper_function_addresses) && + (program_data->global_helper_function_addresses->helper_function_count != + program_data->program_info->count_of_global_helpers)) { + EBPF_LOG_MESSAGE_GUID( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "An extension cannot have a mismatch between the number of helper functions and the number of helper " + "function addresses", + &npi_module_id->Guid); + goto Done; + } + } + program_data_valid = true; + +Done: + return program_data_valid; +} + static NTSTATUS _ebpf_program_general_program_information_attach_provider( _In_ HANDLE nmr_binding_handle, _In_ void* client_context, _In_ const NPI_REGISTRATION_INSTANCE* provider_registration_instance) { - const ebpf_extension_data_t* provider_data = - (const ebpf_extension_data_t*)provider_registration_instance->NpiSpecificCharacteristics; + const ebpf_program_data_t* program_data = + (const ebpf_program_data_t*)provider_registration_instance->NpiSpecificCharacteristics; ebpf_program_t* program = (ebpf_program_t*)client_context; NTSTATUS status; - void* provider_binding_context; void* provider_dispatch; - + ebpf_lock_state_t state = 0; bool lock_held = false; - ebpf_lock_state_t state = ebpf_lock_lock(&program->lock); - lock_held = true; - - // Verify that that the provider is using the same version of the extension as the client. - if (provider_data->version > EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION || - provider_data->size < sizeof(ebpf_program_data_t)) { + if (!_ebpf_program_match_provider_data_module_id( + provider_registration_instance->ModuleId, &ebpf_general_helper_function_module_id.Guid)) { EBPF_LOG_MESSAGE( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, - "Global program information provider version mismatch."); + "Program information provider module ID mismatch."); status = STATUS_INVALID_PARAMETER; goto Done; } - if (provider_registration_instance->ModuleId->Type != MIT_GUID) { - EBPF_LOG_MESSAGE( - EBPF_TRACELOG_LEVEL_ERROR, - EBPF_TRACELOG_KEYWORD_PROGRAM, - "Global program information provider module ID type mismatch."); + if (!_ebpf_program_verify_provider_program_data( + EBPF_PROGRAM_INFO_PROVIDER_TYPE_GENERAL_HELPER, provider_registration_instance->ModuleId, program_data)) { status = STATUS_INVALID_PARAMETER; goto Done; } - if (memcmp( - &provider_registration_instance->ModuleId->Guid, - &ebpf_general_helper_function_module_id.Guid, - sizeof(GUID)) != 0) { - status = STATUS_NOINTERFACE; - // This is expected as the attach callback will be called for each provider of NPI - // EBPF_PROGRAM_INFO_EXTENSION_IID. - goto Done; - } + state = ebpf_lock_lock(&program->lock); + lock_held = true; - if (program->general_helper_provider_data != NULL) { + if (program->general_helper_program_data != NULL) { EBPF_LOG_MESSAGE( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, @@ -245,8 +327,7 @@ _ebpf_program_general_program_information_attach_provider( goto Done; } - program->general_helper_provider_data = provider_data; - const ebpf_program_data_t* program_data = (const ebpf_program_data_t*)program->general_helper_provider_data->data; + program->general_helper_program_data = program_data; program->global_helper_function_count = program_data->program_type_specific_helper_function_addresses->helper_function_count; @@ -270,7 +351,7 @@ _ebpf_program_general_program_information_attach_provider( EBPF_TRACELOG_KEYWORD_PROGRAM, "NmrClientAttachProvider failed for global program information provider.", status); - program->general_helper_provider_data = NULL; + program->general_helper_program_data = NULL; goto Done; } @@ -287,7 +368,7 @@ _ebpf_program_general_program_information_detach_provider(void* client_binding_c { ebpf_program_t* program = (ebpf_program_t*)client_binding_context; ebpf_lock_state_t state = ebpf_lock_lock(&program->lock); - program->general_helper_provider_data = NULL; + program->general_helper_program_data = NULL; ebpf_lock_unlock(&program->lock, state); return STATUS_SUCCESS; } @@ -298,10 +379,9 @@ _ebpf_program_type_specific_program_information_attach_provider( _In_ void* client_context, _In_ const NPI_REGISTRATION_INSTANCE* provider_registration_instance) { - const ebpf_extension_data_t* provider_data = - (const ebpf_extension_data_t*)provider_registration_instance->NpiSpecificCharacteristics; ebpf_program_t* program = (ebpf_program_t*)client_context; - const ebpf_program_data_t* type_specific_program_information_data; + const ebpf_program_data_t* extension_program_data = + (const ebpf_program_data_t*)provider_registration_instance->NpiSpecificCharacteristics; const ebpf_program_data_t* general_program_information_data; cxplat_utf8_string_t hash_algorithm = {0}; NTSTATUS status; @@ -313,65 +393,52 @@ _ebpf_program_type_specific_program_information_attach_provider( void* provider_binding_context; void* provider_dispatch; - + ebpf_lock_state_t state = 0; bool lock_held = false; - ebpf_lock_state_t state = ebpf_lock_lock(&program->lock); - lock_held = true; - - if (ebpf_duplicate_utf8_string(&hash_algorithm, &program->parameters.program_info_hash_type) != EBPF_SUCCESS) { - status = STATUS_NO_MEMORY; - goto Done; - } - - if (!program->general_helper_provider_data) { + if (!_ebpf_program_match_provider_data_module_id( + provider_registration_instance->ModuleId, &program->parameters.program_type)) { EBPF_LOG_MESSAGE( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, - "Type specific program information provider attached before global program information provider."); + "Program information provider module ID mismatch."); status = STATUS_INVALID_PARAMETER; goto Done; } - general_program_information_data = (ebpf_program_data_t*)program->general_helper_provider_data->data; - - actual_helper_function_ids = program->helper_function_ids; - actual_helper_function_count = program->helper_function_count; - actual_helper_ids_set = program->helper_ids_set; - - ebpf_lock_unlock(&program->lock, state); - lock_held = false; - - // Verify that that the provider is using the same version of the extension as the client. - if (provider_data->version > EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION || - provider_data->size < sizeof(ebpf_program_data_t)) { - EBPF_LOG_MESSAGE_GUID( - EBPF_TRACELOG_LEVEL_ERROR, - EBPF_TRACELOG_KEYWORD_PROGRAM, - "Program information provider version mismatch.", - &program->parameters.program_type); + if (!_ebpf_program_verify_provider_program_data( + EBPF_PROGRAM_INFO_PROVIDER_TYPE_EXTENSION, + provider_registration_instance->ModuleId, + extension_program_data)) { status = STATUS_INVALID_PARAMETER; goto Done; } - if (provider_registration_instance->ModuleId->Type != MIT_GUID) { - EBPF_LOG_MESSAGE_GUID( + state = ebpf_lock_lock(&program->lock); + lock_held = true; + + if (!program->general_helper_program_data) { + EBPF_LOG_MESSAGE( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, - "Program information provider module ID type mismatch.", - &program->parameters.program_type); + "Type specific program information provider attached before global program information provider."); status = STATUS_INVALID_PARAMETER; goto Done; } - if (memcmp(&provider_registration_instance->ModuleId->Guid, &program->parameters.program_type, sizeof(GUID)) != 0) { - // This is expected as the attach callback will be called for each provider of NPI - // EBPF_PROGRAM_INFO_EXTENSION_IID. - status = STATUS_NOINTERFACE; + if (ebpf_duplicate_utf8_string(&hash_algorithm, &program->parameters.program_info_hash_type) != EBPF_SUCCESS) { + status = STATUS_NO_MEMORY; goto Done; } - type_specific_program_information_data = (ebpf_program_data_t*)provider_data->data; + general_program_information_data = program->general_helper_program_data; + + actual_helper_function_ids = program->helper_function_ids; + actual_helper_function_count = program->helper_function_count; + actual_helper_ids_set = program->helper_ids_set; + + ebpf_lock_unlock(&program->lock, state); + lock_held = false; // Compute (and compare) the hash only if the actual helper IDs have been set. if (actual_helper_ids_set) { @@ -381,7 +448,7 @@ _ebpf_program_type_specific_program_information_attach_provider( actual_helper_function_ids, actual_helper_function_count, general_program_information_data, - type_specific_program_information_data, + extension_program_data, &hash_algorithm, &hash, &hash_length) != EBPF_SUCCESS) { @@ -393,7 +460,7 @@ _ebpf_program_type_specific_program_information_attach_provider( state = ebpf_lock_lock(&program->lock); lock_held = true; - if (program->info_extension_provider_data != NULL) { + if (program->extension_program_data != NULL) { EBPF_LOG_MESSAGE_GUID( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, @@ -402,7 +469,6 @@ _ebpf_program_type_specific_program_information_attach_provider( status = STATUS_INVALID_PARAMETER; goto Done; } - program->info_extension_provider_data = provider_data; // Compare the hash only if actual helper IDs have been set. if (actual_helper_ids_set) { @@ -419,63 +485,15 @@ _ebpf_program_type_specific_program_information_attach_provider( } } - const ebpf_program_data_t* program_data = (const ebpf_program_data_t*)provider_data->data; - if (program_data == NULL) { - EBPF_LOG_MESSAGE_GUID( - EBPF_TRACELOG_LEVEL_ERROR, - EBPF_TRACELOG_KEYWORD_PROGRAM, - "An extension cannot have empty program_data", - &program->parameters.program_type); - // An extension cannot have empty program_data. - status = STATUS_INVALID_PARAMETER; - goto Done; - } - - if (program_data->required_irql > HIGH_LEVEL) { - EBPF_LOG_MESSAGE_GUID( - EBPF_TRACELOG_LEVEL_ERROR, - EBPF_TRACELOG_KEYWORD_PROGRAM, - "An extension cannot have required_irql higher than HIGH_LEVEL", - &program->parameters.program_type); - status = STATUS_INVALID_PARAMETER; - goto Done; - } - - if ((program_data->program_type_specific_helper_function_addresses) && - program_data->program_type_specific_helper_function_addresses->helper_function_count != - program_data->program_info->count_of_program_type_specific_helpers) { - EBPF_LOG_MESSAGE_GUID( - EBPF_TRACELOG_LEVEL_ERROR, - EBPF_TRACELOG_KEYWORD_PROGRAM, - "An extension cannot have a mismatch between the number of helper functions and the number of helper " - "function addresses", - &program->parameters.program_type); - status = STATUS_INVALID_PARAMETER; - goto Done; - } - - if ((program_data->global_helper_function_addresses) && - (program_data->global_helper_function_addresses->helper_function_count != - program_data->program_info->count_of_global_helpers)) { - EBPF_LOG_MESSAGE_GUID( - EBPF_TRACELOG_LEVEL_ERROR, - EBPF_TRACELOG_KEYWORD_PROGRAM, - "An extension cannot have a mismatch between the number of helper functions and the number of helper " - "function addresses", - &program->parameters.program_type); - status = STATUS_INVALID_PARAMETER; - goto Done; - } - // This should be done after the call to NmrClientAttachProvider, but _ebpf_program_update_helpers requires // the program information to be set. // Unblock calls to use the program information. - program->info_extension_provider_data = provider_data; + program->extension_program_data = extension_program_data; ExInitializeRundownProtection(&program->program_information_rundown_reference); program->program_type_specific_helper_function_count = - program_data->program_info->count_of_program_type_specific_helpers; + extension_program_data->program_info->count_of_program_type_specific_helpers; if (_ebpf_program_update_helpers(program) != EBPF_SUCCESS) { EBPF_LOG_MESSAGE( @@ -484,7 +502,7 @@ _ebpf_program_type_specific_program_information_attach_provider( goto Done; } - program->bpf_prog_type = program_data->program_info->program_type_descriptor.bpf_prog_type; + program->bpf_prog_type = extension_program_data->program_info->program_type_descriptor->bpf_prog_type; ebpf_lock_unlock(&program->lock, state); lock_held = false; @@ -506,7 +524,7 @@ _ebpf_program_type_specific_program_information_attach_provider( state = ebpf_lock_lock(&program->lock); lock_held = true; - program->general_helper_provider_data = NULL; + program->general_helper_program_data = NULL; ebpf_lock_unlock(&program->lock, state); lock_held = false; goto Done; @@ -531,7 +549,7 @@ _ebpf_program_type_specific_program_information_detach_provider(void* client_bin ExWaitForRundownProtectionRelease(&program->program_information_rundown_reference); ebpf_lock_state_t state = ebpf_lock_lock(&program->lock); - program->info_extension_provider_data = NULL; + program->extension_program_data = NULL; ebpf_lock_unlock(&program->lock, state); return STATUS_SUCCESS; } @@ -788,7 +806,7 @@ ebpf_program_create(_In_ const ebpf_program_parameters_t* program_parameters, _O goto Done; } - if (local_program->general_helper_provider_data == NULL || local_program->info_extension_provider_data == NULL) { + if (local_program->general_helper_program_data == NULL || local_program->extension_program_data == NULL) { EBPF_LOG_MESSAGE_GUID_GUID( EBPF_TRACELOG_LEVEL_INFO, EBPF_TRACELOG_KEYWORD_PROGRAM, @@ -1073,7 +1091,7 @@ _ebpf_program_update_jit_helpers( UNREFERENCED_PARAMETER(address_count); UNREFERENCED_PARAMETER(addresses); ebpf_program_t* program = (ebpf_program_t*)context; - ebpf_program_data_t* program_data = NULL; + const ebpf_program_data_t* program_data = NULL; const ebpf_helper_function_addresses_t* helper_function_addresses = NULL; const ebpf_helper_function_addresses_t* global_helper_function_addresses = NULL; @@ -1092,7 +1110,7 @@ _ebpf_program_update_jit_helpers( goto Exit; } provider_data_referenced = true; - program_data = (ebpf_program_data_t*)program->info_extension_provider_data->data; + program_data = program->extension_program_data; helper_function_addresses = program_data->program_type_specific_helper_function_addresses; global_helper_function_addresses = program_data->global_helper_function_addresses; @@ -1372,7 +1390,7 @@ ebpf_program_set_tail_call(_In_ const ebpf_program_t* next_program) _Must_inspect_result_ ebpf_result_t ebpf_program_reference_providers(_Inout_ ebpf_program_t* program) { - if (program->info_extension_provider_data == NULL) { + if (program->extension_program_data == NULL) { return EBPF_EXTENSION_FAILED_TO_LOAD; } if (!ExAcquireRundownProtection(&program->program_information_rundown_reference)) { @@ -1434,8 +1452,8 @@ _Requires_lock_held_(program->lock) static ebpf_result_t _ebpf_program_get_helpe { ebpf_result_t return_value; uint64_t* function_address = NULL; - ebpf_program_data_t* program_data = NULL; - ebpf_program_data_t* general_program_data = NULL; + const ebpf_program_data_t* program_data = NULL; + const ebpf_program_data_t* general_program_data = NULL; EBPF_LOG_ENTRY(); @@ -1454,8 +1472,8 @@ _Requires_lock_held_(program->lock) static ebpf_result_t _ebpf_program_get_helpe } provider_data_referenced = true; - program_data = (ebpf_program_data_t*)program->info_extension_provider_data->data; - general_program_data = (ebpf_program_data_t*)program->general_helper_provider_data->data; + program_data = program->extension_program_data; + general_program_data = program->general_helper_program_data; use_trampoline = program->parameters.code_type == EBPF_CODE_JIT; if (use_trampoline && !program->trampoline_table) { @@ -1573,7 +1591,6 @@ ebpf_program_set_helper_function_ids( state = ebpf_lock_lock(&program->lock); if (helper_function_count == 0) { - program->helper_ids_set = true; goto Exit; } @@ -1599,6 +1616,8 @@ ebpf_program_set_helper_function_ids( program->helper_function_ids[index] = helper_function_ids[index]; } + program->helper_ids_set = true; + Exit: ebpf_lock_unlock(&program->lock, state); EBPF_RETURN_RESULT(result); @@ -1627,7 +1646,7 @@ ebpf_program_set_program_info_hash(_Inout_ ebpf_program_t* program) ebpf_result_t result = EBPF_SUCCESS; bool provider_data_referenced = false; - const ebpf_program_data_t* type_specific_program_information_data; + const ebpf_program_data_t* extension_program_data; const ebpf_program_data_t* general_program_information_data; cxplat_utf8_string_t hash_algorithm = {0}; uint32_t* actual_helper_function_ids = NULL; @@ -1657,8 +1676,8 @@ ebpf_program_set_program_info_hash(_Inout_ ebpf_program_t* program) goto Exit; } - general_program_information_data = (ebpf_program_data_t*)program->general_helper_provider_data->data; - type_specific_program_information_data = (ebpf_program_data_t*)program->info_extension_provider_data->data; + general_program_information_data = program->general_helper_program_data; + extension_program_data = program->extension_program_data; actual_helper_function_ids = program->helper_function_ids; actual_helper_function_count = program->helper_function_count; @@ -1670,7 +1689,7 @@ ebpf_program_set_program_info_hash(_Inout_ ebpf_program_t* program) actual_helper_function_ids, actual_helper_function_count, general_program_information_data, - type_specific_program_information_data, + extension_program_data, &hash_algorithm, &hash, &hash_length); @@ -1718,8 +1737,8 @@ ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_ { EBPF_LOG_ENTRY(); ebpf_result_t result = EBPF_SUCCESS; - ebpf_program_data_t* program_data = NULL; - ebpf_program_data_t* general_helper_program_data = NULL; + const ebpf_program_data_t* program_data = NULL; + const ebpf_program_data_t* general_helper_program_data = NULL; ebpf_program_info_t* local_program_info = NULL; uint32_t total_count_of_helpers = 0; uint32_t helper_index = 0; @@ -1738,9 +1757,9 @@ ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_ goto Exit; } provider_data_referenced = true; - program_data = (ebpf_program_data_t*)program->info_extension_provider_data->data; + program_data = program->extension_program_data; - if (!program->general_helper_provider_data) { + if (!program->general_helper_program_data) { EBPF_LOG_MESSAGE_GUID( EBPF_TRACELOG_LEVEL_ERROR, EBPF_TRACELOG_KEYWORD_PROGRAM, @@ -1749,7 +1768,7 @@ ebpf_program_get_program_info(_In_ const ebpf_program_t* program, _Outptr_ ebpf_ result = EBPF_EXTENSION_FAILED_TO_LOAD; goto Exit; } - general_helper_program_data = (ebpf_program_data_t*)program->general_helper_provider_data->data; + general_helper_program_data = program->general_helper_program_data; total_count_of_helpers = program_data->program_info->count_of_program_type_specific_helpers + general_helper_program_data->program_info->count_of_program_type_specific_helpers; @@ -1984,7 +2003,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL) static ebpf_result_t _ebpf_program_compute_pr _In_ const uint32_t* actual_helper_ids, size_t count_of_actual_helper_ids, _In_ const ebpf_program_data_t* general_program_information_data, - _In_ const ebpf_program_data_t* type_specific_program_information_data, + _In_ const ebpf_program_data_t* extension_program_data, _In_ const cxplat_utf8_string_t* hash_algorithm, _Outptr_ uint8_t** hash, _Out_ size_t* hash_length) @@ -1993,7 +2012,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL) static ebpf_result_t _ebpf_program_compute_pr ebpf_result_t result; ebpf_cryptographic_hash_t* cryptographic_hash = NULL; ebpf_helper_id_to_index_t* helper_id_to_index = NULL; - const ebpf_program_info_t* type_specific_program_info = type_specific_program_information_data->program_info; + const ebpf_program_info_t* type_specific_program_info = extension_program_data->program_info; const ebpf_program_info_t* general_program_info = general_program_information_data->program_info; size_t helper_function_count = count_of_actual_helper_ids; uint32_t helper_function_index = 0; @@ -2070,31 +2089,31 @@ _IRQL_requires_max_(PASSIVE_LEVEL) static ebpf_result_t _ebpf_program_compute_pr // new fields, both here and in bpf2c. result = EBPF_CRYPTOGRAPHIC_HASH_APPEND_STR( - cryptographic_hash, type_specific_program_info->program_type_descriptor.name); + cryptographic_hash, type_specific_program_info->program_type_descriptor->name); if (result != EBPF_SUCCESS) { goto Exit; } result = EBPF_CRYPTOGRAPHIC_HASH_APPEND_VALUE( - cryptographic_hash, *type_specific_program_info->program_type_descriptor.context_descriptor); + cryptographic_hash, *type_specific_program_info->program_type_descriptor->context_descriptor); if (result != EBPF_SUCCESS) { goto Exit; } result = EBPF_CRYPTOGRAPHIC_HASH_APPEND_VALUE( - cryptographic_hash, type_specific_program_info->program_type_descriptor.program_type); + cryptographic_hash, type_specific_program_info->program_type_descriptor->program_type); if (result != EBPF_SUCCESS) { goto Exit; } result = EBPF_CRYPTOGRAPHIC_HASH_APPEND_VALUE( - cryptographic_hash, type_specific_program_info->program_type_descriptor.bpf_prog_type); + cryptographic_hash, type_specific_program_info->program_type_descriptor->bpf_prog_type); if (result != EBPF_SUCCESS) { goto Exit; } result = EBPF_CRYPTOGRAPHIC_HASH_APPEND_VALUE( - cryptographic_hash, type_specific_program_info->program_type_descriptor.is_privileged); + cryptographic_hash, type_specific_program_info->program_type_descriptor->is_privileged); if (result != EBPF_SUCCESS) { goto Exit; } @@ -2158,7 +2177,7 @@ _IRQL_requires_max_(PASSIVE_LEVEL) static ebpf_result_t _ebpf_program_compute_pr typedef struct _ebpf_program_test_run_context { const ebpf_program_t* program; - ebpf_program_data_t* program_data; + const ebpf_program_data_t* program_data; ebpf_program_test_run_options_t* options; uint8_t required_irql; bool canceled; @@ -2313,7 +2332,7 @@ ebpf_program_execute_test_run( ebpf_result_t return_value = EBPF_SUCCESS; ebpf_program_test_run_context_t* test_run_context = NULL; cxplat_preemptible_work_item_t* work_item = NULL; - ebpf_program_data_t* program_data = NULL; + const ebpf_program_data_t* program_data = NULL; bool provider_data_referenced = false; // Prevent the provider from detaching while the program is running. @@ -2328,7 +2347,7 @@ ebpf_program_execute_test_run( } provider_data_referenced = true; - program_data = (ebpf_program_data_t*)program->info_extension_provider_data->data; + program_data = program->extension_program_data; if (program_data->context_create == NULL || program_data->context_destroy == NULL) { return_value = EBPF_INVALID_ARGUMENT; diff --git a/libs/execution_context/unit/execution_context_unit_test.cpp b/libs/execution_context/unit/execution_context_unit_test.cpp index 42a836b073..d89aadf3b7 100644 --- a/libs/execution_context/unit/execution_context_unit_test.cpp +++ b/libs/execution_context/unit/execution_context_unit_test.cpp @@ -761,7 +761,9 @@ TEST_CASE("program", "[execution_context]") uint32_t test_function_ids[] = {(EBPF_MAX_GENERAL_HELPER_FUNCTION + 1)}; const void* helper_functions[] = {(void*)function_pointer1}; ebpf_helper_function_addresses_t helper_function_addresses = { - EBPF_COUNT_OF(helper_functions), (uint64_t*)helper_functions}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(helper_functions), + (uint64_t*)helper_functions}; { ebpf_trampoline_table_t* local_table = nullptr; diff --git a/libs/runtime/unit/platform_unit_test.cpp b/libs/runtime/unit/platform_unit_test.cpp index c70971b5f3..b535ab9063 100644 --- a/libs/runtime/unit/platform_unit_test.cpp +++ b/libs/runtime/unit/platform_unit_test.cpp @@ -621,13 +621,17 @@ TEST_CASE("trampoline_test", "[platform]") const void* helper_functions1[] = {(void*)function_pointer1}; const uint32_t provider_helper_function_ids[] = {(uint32_t)(EBPF_MAX_GENERAL_HELPER_FUNCTION + 1)}; ebpf_helper_function_addresses_t helper_function_addresses1 = { - EBPF_COUNT_OF(helper_functions1), (uint64_t*)helper_functions1}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(helper_functions1), + (uint64_t*)helper_functions1}; auto provider_function2 = []() { return EBPF_OBJECT_ALREADY_EXISTS; }; ebpf_result_t (*function_pointer2)() = provider_function2; const void* helper_functions2[] = {(void*)function_pointer2}; ebpf_helper_function_addresses_t helper_function_addresses2 = { - EBPF_COUNT_OF(helper_functions1), (uint64_t*)helper_functions2}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(helper_functions1), + (uint64_t*)helper_functions2}; ebpf_trampoline_table_t* local_table = nullptr; REQUIRE(ebpf_allocate_trampoline_table(1, &local_table) == EBPF_SUCCESS); @@ -799,11 +803,13 @@ TEST_CASE("serialize_program_info_test", "[platform]") test_helper.initialize(); ebpf_helper_function_prototype_t helper_prototype[] = { - {1000, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + 1000, "helper_0", EBPF_RETURN_TYPE_PTR_TO_MAP_VALUE_OR_NULL, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY}}, - {1001, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + 1001, "helper_1", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_MAP, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_KEY, EBPF_ARGUMENT_TYPE_PTR_TO_MAP_VALUE}}}; @@ -811,8 +817,16 @@ TEST_CASE("serialize_program_info_test", "[platform]") // and have no effect on the test. ebpf_context_descriptor_t context_descriptor = {32, 0, 8, -1}; GUID program_type_test = {0x7ebe418c, 0x76dd, 0x4c2c, {0x99, 0xbc, 0x5c, 0x48, 0xa2, 0x30, 0x4b, 0x90}}; - ebpf_program_type_descriptor_t program_type = {"unit_test_program", &context_descriptor, program_type_test}; - ebpf_program_info_t in_program_info = {program_type, EBPF_COUNT_OF(helper_prototype), helper_prototype}; + ebpf_program_type_descriptor_t program_type = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "unit_test_program", + &context_descriptor, + program_type_test}; + ebpf_program_info_t in_program_info = { + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &program_type, + EBPF_COUNT_OF(helper_prototype), + helper_prototype}; size_t buffer_length = 0; size_t required_length; @@ -843,21 +857,23 @@ TEST_CASE("serialize_program_info_test", "[platform]") REQUIRE(ebpf_deserialize_program_info(serialized_length, unique_buffer.get(), &out_program_info) == EBPF_SUCCESS); // Verify de-serialized program info matches input. + REQUIRE(in_program_info.program_type_descriptor != nullptr); REQUIRE( - in_program_info.program_type_descriptor.program_type == out_program_info->program_type_descriptor.program_type); + in_program_info.program_type_descriptor->program_type == + out_program_info->program_type_descriptor->program_type); REQUIRE( - in_program_info.program_type_descriptor.is_privileged == - out_program_info->program_type_descriptor.is_privileged); - REQUIRE(in_program_info.program_type_descriptor.context_descriptor != nullptr); + in_program_info.program_type_descriptor->is_privileged == + out_program_info->program_type_descriptor->is_privileged); + REQUIRE(in_program_info.program_type_descriptor->context_descriptor != nullptr); REQUIRE( memcmp( - in_program_info.program_type_descriptor.context_descriptor, - out_program_info->program_type_descriptor.context_descriptor, + in_program_info.program_type_descriptor->context_descriptor, + out_program_info->program_type_descriptor->context_descriptor, sizeof(ebpf_context_descriptor_t)) == 0); REQUIRE( strncmp( - in_program_info.program_type_descriptor.name, - out_program_info->program_type_descriptor.name, + in_program_info.program_type_descriptor->name, + out_program_info->program_type_descriptor->name, EBPF_MAX_PROGRAM_DESCRIPTOR_NAME_LENGTH) == 0); REQUIRE( in_program_info.count_of_program_type_specific_helpers == diff --git a/libs/shared/ebpf_serialize.c b/libs/shared/ebpf_serialize.c index 5df3cd2f77..732da0ba83 100644 --- a/libs/shared/ebpf_serialize.c +++ b/libs/shared/ebpf_serialize.c @@ -13,6 +13,7 @@ typedef struct _ebpf_serialized_program_type_descriptor { size_t size; + ebpf_extension_header_t header; ebpf_context_descriptor_t context_descriptor; GUID program_type; unsigned char is_privileged; @@ -26,6 +27,7 @@ typedef struct _ebpf_serialized_program_type_descriptor typedef struct _ebpf_serialized_helper_function_prototype { size_t size; + ebpf_extension_header_t header; uint32_t helper_id; ebpf_return_type_t return_type; ebpf_argument_type_t arguments[5]; @@ -39,6 +41,7 @@ typedef struct _ebpf_serialized_helper_function_prototype typedef struct _ebpf_serialized_helper_function_prototype_array { size_t size; + ebpf_extension_header_t header; uint32_t helper_function_count; uint8_t prototypes[1]; } ebpf_serialized_helper_function_prototype_array_t; @@ -255,8 +258,11 @@ ebpf_program_info_free(_In_opt_ _Post_invalid_ ebpf_program_info_t* program_info { EBPF_LOG_ENTRY(); if (program_info != NULL) { - ebpf_free((void*)program_info->program_type_descriptor.context_descriptor); - ebpf_free((void*)program_info->program_type_descriptor.name); + if (program_info->program_type_descriptor != NULL) { + ebpf_free((void*)program_info->program_type_descriptor->context_descriptor); + ebpf_free((void*)program_info->program_type_descriptor->name); + ebpf_free((void*)program_info->program_type_descriptor); + } if (program_info->program_type_specific_helper_prototype != NULL) { for (uint32_t i = 0; i < program_info->count_of_program_type_specific_helpers; i++) { const ebpf_helper_function_prototype_t* helper_prototype = @@ -302,7 +308,12 @@ ebpf_serialize_program_info( *serialized_data_length = 0; // Perform sanity check on input program info. - program_type_descriptor = &program_info->program_type_descriptor; + program_type_descriptor = program_info->program_type_descriptor; + if (program_type_descriptor == NULL) { + EBPF_LOG_MESSAGE(EBPF_TRACELOG_LEVEL_WARNING, EBPF_TRACELOG_KEYWORD_BASE, "program_type_descriptor is NULL"); + result = EBPF_INVALID_ARGUMENT; + goto Exit; + } if (program_type_descriptor->name == NULL) { EBPF_LOG_MESSAGE( @@ -426,6 +437,7 @@ ebpf_serialize_program_info( if (program_type_descriptor->context_descriptor != NULL) { serialized_program_type_descriptor->context_descriptor = *program_type_descriptor->context_descriptor; } + serialized_program_type_descriptor->header = program_type_descriptor->header; serialized_program_type_descriptor->program_type = program_type_descriptor->program_type; serialized_program_type_descriptor->is_privileged = program_type_descriptor->is_privileged; serialized_program_type_descriptor->name_length = program_type_descriptor_name_length; @@ -457,6 +469,7 @@ ebpf_serialize_program_info( // Serialize individual helper function prototypes. serialized_helper_prototype->size = EBPF_OFFSET_OF(ebpf_serialized_helper_function_prototype_t, name) + helper_function_name_length; + serialized_helper_prototype->header = helper_prototype->header; serialized_helper_prototype->helper_id = helper_prototype->helper_id; serialized_helper_prototype->return_type = helper_prototype->return_type; for (uint16_t index = 0; index < EBPF_COUNT_OF(helper_prototype->arguments); index++) { @@ -501,12 +514,18 @@ ebpf_deserialize_program_info( result = EBPF_NO_MEMORY; goto Exit; } - local_program_type_descriptor = &local_program_info->program_type_descriptor; current = input_buffer; buffer_left = input_buffer_length; - // Deserialize program type descriptor. + // Allocate and deserialize program type descriptor. + local_program_type_descriptor = + (ebpf_program_type_descriptor_t*)ebpf_allocate(sizeof(ebpf_program_type_descriptor_t)); + if (local_program_type_descriptor == NULL) { + result = EBPF_NO_MEMORY; + goto Exit; + } + local_program_info->program_type_descriptor = local_program_type_descriptor; // Check if sufficient input buffer remaining. if (buffer_left < sizeof(ebpf_serialized_program_type_descriptor_t)) { @@ -516,6 +535,7 @@ ebpf_deserialize_program_info( serialized_program_type_descriptor = (const ebpf_serialized_program_type_descriptor_t*)current; + local_program_type_descriptor->header = serialized_program_type_descriptor->header; local_program_type_descriptor->program_type = serialized_program_type_descriptor->program_type; local_program_type_descriptor->is_privileged = serialized_program_type_descriptor->is_privileged; @@ -627,7 +647,8 @@ ebpf_deserialize_program_info( goto Exit; } - // Serialize helper prototype. + // De-serialize helper prototype. + helper_prototype->header = serialized_helper_prototype->header; helper_prototype->helper_id = serialized_helper_prototype->helper_id; helper_prototype->return_type = serialized_helper_prototype->return_type; for (int i = 0; i < EBPF_COUNT_OF(helper_prototype->arguments); i++) { diff --git a/libs/shared/ebpf_shared_framework.h b/libs/shared/ebpf_shared_framework.h index 9b508e736e..790d57f532 100644 --- a/libs/shared/ebpf_shared_framework.h +++ b/libs/shared/ebpf_shared_framework.h @@ -3,6 +3,7 @@ #pragma once #include "cxplat.h" +#include "ebpf_program_types.h" #include "ebpf_result.h" #include "shared_context.h" @@ -13,6 +14,8 @@ CXPLAT_EXTERN_C_BEGIN #define EBPF_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0])) #define EBPF_OFFSET_OF(s, m) (((size_t) & ((s*)0)->m)) +#define EBPF_FIELD_SIZE(s, m) (sizeof(((s*)0)->m)) +#define EBPF_SIZE_INCLUDING_FIELD(s, m) (EBPF_OFFSET_OF(s, m) + EBPF_FIELD_SIZE(s, m)) #define EBPF_FROM_FIELD(s, m, o) (s*)((uint8_t*)o - EBPF_OFFSET_OF(s, m)) #define EBPF_CACHE_LINE_SIZE 64 @@ -92,4 +95,17 @@ __forceinline __drv_allocatesMem(Mem) _Must_inspect_result_ ebpf_result_t ebpf_result_from_cxplat_status(cxplat_status_t status); +bool +ebpf_validate_program_data(_In_ const ebpf_program_data_t* program_data); + +bool +ebpf_validate_program_section_info(_In_ const ebpf_program_section_info_t* section_info); + +bool +ebpf_validate_program_info(_In_ const ebpf_program_info_t* program_info); + +bool +ebpf_validate_helper_function_prototype_array( + _In_reads_(count) const ebpf_helper_function_prototype_t* helper_prototype, uint32_t count); + CXPLAT_EXTERN_C_END diff --git a/libs/shared/shared_common.c b/libs/shared/shared_common.c index 6f2b7a495f..d1dac3b11f 100644 --- a/libs/shared/shared_common.c +++ b/libs/shared/shared_common.c @@ -1,8 +1,151 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#include "ebpf_program_types.h" #include "ebpf_shared_framework.h" +enum _extension_object_type +{ + EBPF_PROGRAM_TYPE_DESCRIPTOR = 0, + EBPF_HELPER_FUNCTION_PROTOTYPE, + EBPF_PROGRAM_INFO, + EBPF_PROGRAM_DATA, + EBPF_PROGRAM_SECTION, +}; + +// Supported version and sizes of the various extension data structures. + +uint16_t _supported_ebpf_extension_version[] = { + EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, + EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, + EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, + EBPF_PROGRAM_DATA_CURRENT_VERSION, + EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, +}; + +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_SIZE_0 EBPF_OFFSET_OF(ebpf_program_type_descriptor_t, is_privileged) + sizeof(char) +size_t _ebpf_program_type_descriptor_supported_size[] = {EBPF_PROGRAM_TYPE_DESCRIPTOR_SIZE_0}; + +#define EBPF_HELPER_FUNCTION_PROTOTYPE_SIZE_0 \ + EBPF_OFFSET_OF(ebpf_helper_function_prototype_t, arguments) + 5 * sizeof(ebpf_argument_type_t) +size_t _ebpf_helper_function_prototype_supported_size[] = {EBPF_HELPER_FUNCTION_PROTOTYPE_SIZE_0}; + +#define EBPF_PROGRAM_INFO_SIZE_0 \ + EBPF_OFFSET_OF(ebpf_program_info_t, global_helper_prototype) + sizeof(ebpf_helper_function_prototype_t*) +size_t _ebpf_program_info_supported_size[] = {EBPF_PROGRAM_INFO_SIZE_0}; + +#define EBPF_PROGRAM_DATA_SIZE_0 EBPF_OFFSET_OF(ebpf_program_data_t, required_irql) + sizeof(uint8_t) +size_t _ebpf_program_data_supported_size[] = {EBPF_PROGRAM_DATA_SIZE_0}; + +#define EBPF_PROGRAM_SECTION_SIZE_0 EBPF_OFFSET_OF(ebpf_program_section_info_t, bpf_attach_type) + sizeof(uint32_t) +size_t _ebpf_program_section_supported_size[] = {EBPF_PROGRAM_SECTION_SIZE_0}; + +struct _ebpf_extension_data_structure_supported_sizes +{ + size_t* supported_sizes; + uint16_t count; +}; +struct _ebpf_extension_data_structure_supported_sizes _ebpf_extension_type_supported_sizes[] = { + {_ebpf_program_type_descriptor_supported_size, EBPF_COUNT_OF(_ebpf_program_type_descriptor_supported_size)}, + {_ebpf_helper_function_prototype_supported_size, EBPF_COUNT_OF(_ebpf_helper_function_prototype_supported_size)}, + {_ebpf_program_info_supported_size, EBPF_COUNT_OF(_ebpf_program_info_supported_size)}, + {_ebpf_program_data_supported_size, EBPF_COUNT_OF(_ebpf_program_data_supported_size)}, + {_ebpf_program_section_supported_size, EBPF_COUNT_OF(_ebpf_program_section_supported_size)}, +}; + +static bool +_ebpf_is_size_supported(_In_count_(count) const size_t* supported_sizes, uint16_t count, size_t size) +{ + for (uint16_t i = 0; i < count; i++) { + if (size == supported_sizes[i]) { + return true; + } + } + return false; +} + +static bool +_ebpf_validate_extension_object_header( + enum _extension_object_type object_type, _In_ const ebpf_extension_header_t* header) +{ + size_t* supported_sizes = _ebpf_extension_type_supported_sizes[object_type].supported_sizes; + uint16_t count = _ebpf_extension_type_supported_sizes[object_type].count; + __analysis_assume(supported_sizes != NULL); + + return ( + (header->version == _supported_ebpf_extension_version[object_type]) && + (_ebpf_is_size_supported(supported_sizes, count, header->size))); +} + +static bool +_ebpf_validate_helper_function_prototype(const ebpf_helper_function_prototype_t* helper_prototype) +{ + return ( + (helper_prototype != NULL) && + _ebpf_validate_extension_object_header(EBPF_HELPER_FUNCTION_PROTOTYPE, &helper_prototype->header) && + (helper_prototype->name != NULL)); +} + +bool +ebpf_validate_helper_function_prototype_array( + _In_reads_(count) const ebpf_helper_function_prototype_t* helper_prototype, uint32_t count) +{ + if (count > 0) { + for (uint32_t i = 0; i < count; i++) { + if (!_ebpf_validate_helper_function_prototype(&helper_prototype[i])) { + return false; + } + } + } + return true; +} + +static bool +_ebpf_validate_context_descriptor(_In_ const ebpf_context_descriptor_t* context_descriptor) +{ + return ((context_descriptor != NULL) && (context_descriptor->size >= sizeof(ebpf_context_descriptor_t))); +} + +static bool +_ebpf_validate_program_type_descriptor(_In_ const ebpf_program_type_descriptor_t* program_type_descriptor) +{ + return ( + (program_type_descriptor != NULL) && + _ebpf_validate_extension_object_header(EBPF_PROGRAM_TYPE_DESCRIPTOR, &program_type_descriptor->header) && + (program_type_descriptor->name != NULL) && + _ebpf_validate_context_descriptor(program_type_descriptor->context_descriptor)); +} + +bool +ebpf_validate_program_info(_In_ const ebpf_program_info_t* program_info) +{ + return ( + (program_info != NULL) && _ebpf_validate_extension_object_header(EBPF_PROGRAM_INFO, &program_info->header) && + _ebpf_validate_program_type_descriptor(program_info->program_type_descriptor) && + ebpf_validate_helper_function_prototype_array( + program_info->program_type_specific_helper_prototype, + program_info->count_of_program_type_specific_helpers) && + ebpf_validate_helper_function_prototype_array( + program_info->global_helper_prototype, program_info->count_of_global_helpers)); +} + +bool +ebpf_validate_program_data(_In_ const ebpf_program_data_t* program_data) +{ + return ( + (program_data != NULL) && _ebpf_validate_extension_object_header(EBPF_PROGRAM_DATA, &program_data->header) && + ebpf_validate_program_info(program_data->program_info)); +} + +bool +ebpf_validate_program_section_info(_In_ const ebpf_program_section_info_t* section_info) +{ + return ( + (section_info != NULL) && _ebpf_validate_extension_object_header(EBPF_PROGRAM_SECTION, §ion_info->header) && + (section_info->section_name != NULL) && (section_info->program_type != NULL) && + (section_info->attach_type != NULL)); +} + ebpf_result_t ebpf_result_from_cxplat_status(cxplat_status_t status) { diff --git a/libs/store_helper/ebpf_store_helper.c b/libs/store_helper/ebpf_store_helper.c index 94f95537b8..7ba2f6e91b 100644 --- a/libs/store_helper/ebpf_store_helper.c +++ b/libs/store_helper/ebpf_store_helper.c @@ -3,11 +3,23 @@ #include "ebpf_program_types.h" #include "ebpf_registry_helper.h" +#include "ebpf_shared_framework.h" #include "ebpf_store_helper.h" #include "ebpf_windows.h" #define IS_SUCCESS(x) (x == EBPF_SUCCESS) +static ebpf_result_t +_ebpf_store_update_extension_header_information(ebpf_store_key_t key, _In_ const ebpf_extension_header_t* header) +{ + ebpf_result_t result; + result = ebpf_write_registry_value_dword(key, EBPF_EXTENSION_HEADER_VERSION, header->version); + if (!IS_SUCCESS(result)) + return result; + result = ebpf_write_registry_value_dword(key, EBPF_EXTENSION_HEADER_SIZE, (uint32_t)header->size); + return result; +} + static ebpf_result_t _ebpf_store_open_or_create_provider_registry_key(_Out_ ebpf_store_key_t* provider_key) { @@ -23,7 +35,7 @@ _ebpf_store_open_or_create_provider_registry_key(_Out_ ebpf_store_key_t* provide } // Open (or create) program data registry path. - result = ebpf_create_registry_key(root_key, EBPF_PROVIDERS_REGISTRY_PATH, REG_CREATE_FLAGS, provider_key); + result = ebpf_create_registry_key(root_key, EBPF_PROVIDERS_REGISTRY_KEY, REG_CREATE_FLAGS, provider_key); if (!IS_SUCCESS(result)) { goto Exit; } @@ -52,6 +64,12 @@ _ebpf_store_update_helper_prototype( goto Exit; } + // Save header information. + result = _ebpf_store_update_extension_header_information(helper_function_key, &helper_info->header); + if (!IS_SUCCESS(result)) { + goto Exit; + } + // Serialize the helper prototype. offset = 0; memcpy(serialized_data, &helper_info->helper_id, sizeof(helper_info->helper_id)); @@ -89,6 +107,11 @@ ebpf_store_update_global_helper_information( return result; } + if (!ebpf_validate_helper_function_prototype_array(helper_info, helper_info_count)) { + result = EBPF_INVALID_ARGUMENT; + goto Exit; + } + // Open (or create) provider registry path. result = _ebpf_store_open_or_create_provider_registry_key(&provider_key); if (!IS_SUCCESS(result)) { @@ -97,13 +120,12 @@ ebpf_store_update_global_helper_information( // Open (or create) global helpers registry path. result = - ebpf_create_registry_key(provider_key, EBPF_GLOBAL_HELPERS_REGISTRY_PATH, REG_CREATE_FLAGS, &helper_info_key); + ebpf_create_registry_key(provider_key, EBPF_GLOBAL_HELPERS_REGISTRY_KEY, REG_CREATE_FLAGS, &helper_info_key); if (!IS_SUCCESS(result)) { goto Exit; } for (uint32_t i = 0; i < helper_info_count; i++) { - result = _ebpf_store_update_helper_prototype(helper_info_key, &helper_info[i]); if (!IS_SUCCESS(result)) { goto Exit; @@ -136,7 +158,7 @@ ebpf_store_update_section_information( } // Open (or create) section data key. - result = ebpf_create_registry_key(provider_key, EBPF_SECTIONS_REGISTRY_PATH, REG_CREATE_FLAGS, §ion_info_key); + result = ebpf_create_registry_key(provider_key, EBPF_SECTIONS_REGISTRY_KEY, REG_CREATE_FLAGS, §ion_info_key); if (!IS_SUCCESS(result)) { goto Exit; } @@ -144,6 +166,11 @@ ebpf_store_update_section_information( for (uint32_t i = 0; i < section_info_count; i++) { ebpf_store_key_t section_key = NULL; + if (!ebpf_validate_program_section_info(§ion_info[i])) { + result = EBPF_INVALID_ARGUMENT; + goto Exit; + } + // Open or create the registry path. result = ebpf_create_registry_key(section_info_key, section_info[i].section_name, REG_CREATE_FLAGS, §ion_key); @@ -151,6 +178,9 @@ ebpf_store_update_section_information( goto Exit; } + // Save header information. + result = _ebpf_store_update_extension_header_information(section_key, §ion_info[i].header); + // Save program type. result = ebpf_write_registry_value_binary( section_key, @@ -199,13 +229,124 @@ ebpf_store_update_section_information( return result; } +static ebpf_result_t +_ebpf_store_update_program_descriptor( + ebpf_store_key_t descriptor_key, _In_ const ebpf_program_type_descriptor_t* program_type_descriptor) +{ + ebpf_result_t result = EBPF_SUCCESS; + + // Save header information. + result = _ebpf_store_update_extension_header_information(descriptor_key, &program_type_descriptor->header); + if (!IS_SUCCESS(result)) { + return result; + } + + // Save the friendly program type name. + wchar_t* wide_program_name = ebpf_get_wstring_from_string(program_type_descriptor->name); + if (wide_program_name == NULL) { + return EBPF_NO_MEMORY; + } + result = ebpf_write_registry_value_string(descriptor_key, EBPF_PROGRAM_DATA_NAME, wide_program_name); + if (!IS_SUCCESS(result)) { + ebpf_free_wstring(wide_program_name); + return result; + } + ebpf_free_wstring(wide_program_name); + + // Save context descriptor. + result = ebpf_write_registry_value_binary( + descriptor_key, + EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR, + (uint8_t*)program_type_descriptor->context_descriptor, + sizeof(ebpf_context_descriptor_t)); + if (!IS_SUCCESS(result)) { + return result; + } + + // Save bpf_prog_type. + result = ebpf_write_registry_value_dword( + descriptor_key, EBPF_DATA_BPF_PROG_TYPE, program_type_descriptor->bpf_prog_type); + if (!IS_SUCCESS(result)) { + return result; + } + + // Save "is_privileged". + result = ebpf_write_registry_value_dword( + descriptor_key, EBPF_PROGRAM_DATA_PRIVILEGED, program_type_descriptor->is_privileged); + if (!IS_SUCCESS(result)) { + return result; + } + + return result; +} + +static ebpf_result_t +_ebpf_store_update_program_info(ebpf_store_key_t program_key, _In_ const ebpf_program_info_t* program_info) +{ + ebpf_result_t result = EBPF_SUCCESS; + ebpf_store_key_t descriptor_key = {0}; + ebpf_store_key_t helper_info_key = {0}; + + // Save program info header information. + result = _ebpf_store_update_extension_header_information(program_key, &program_info->header); + if (!IS_SUCCESS(result)) { + goto Exit; + } + + // Create a subkey to store the program type descriptor. + result = ebpf_create_registry_key( + program_key, EBPF_PROGRAM_TYPE_DESCRIPTOR_REGISTRY_KEY, REG_CREATE_FLAGS, &descriptor_key); + if (!IS_SUCCESS(result)) { + goto Exit; + } + + // Save program type descriptor. + result = _ebpf_store_update_program_descriptor(descriptor_key, program_info->program_type_descriptor); + if (!IS_SUCCESS(result)) { + goto Exit; + } + + // Save helper count. + result = ebpf_write_registry_value_dword( + program_key, EBPF_PROGRAM_DATA_HELPER_COUNT, program_info->count_of_program_type_specific_helpers); + if (!IS_SUCCESS(result)) { + goto Exit; + } + + if (program_info->count_of_program_type_specific_helpers == 0) { + // No helpers to save. + goto Exit; + } + + // Create (or open) helper registry path. + result = ebpf_create_registry_key( + program_key, EBPF_PROGRAM_DATA_HELPERS_REGISTRY_KEY, REG_CREATE_FLAGS, &helper_info_key); + if (!IS_SUCCESS(result)) { + goto Exit; + } + + // Iterate over all the helper prototypes and save in registry. + for (uint32_t count = 0; count < program_info->count_of_program_type_specific_helpers; count++) { + result = _ebpf_store_update_helper_prototype( + helper_info_key, &(program_info->program_type_specific_helper_prototype[count])); + if (!IS_SUCCESS(result)) { + goto Exit; + } + } + +Exit: + ebpf_close_registry_key(helper_info_key); + ebpf_close_registry_key(descriptor_key); + return result; +} + ebpf_result_t -ebpf_store_update_program_information( +ebpf_store_update_program_information_array( _In_reads_(program_info_count) const ebpf_program_info_t* program_info, uint32_t program_info_count) { ebpf_result_t result = EBPF_SUCCESS; ebpf_store_key_t provider_key = NULL; - ebpf_store_key_t program_info_key = NULL; + ebpf_store_key_t program_data_key = NULL; if (program_info_count == 0) { return result; @@ -219,104 +360,44 @@ ebpf_store_update_program_information( // Open (or create) program data registry path. result = - ebpf_create_registry_key(provider_key, EBPF_PROGRAM_DATA_REGISTRY_PATH, REG_CREATE_FLAGS, &program_info_key); + ebpf_create_registry_key(provider_key, EBPF_PROGRAM_DATA_REGISTRY_KEY, REG_CREATE_FLAGS, &program_data_key); if (!IS_SUCCESS(result)) { goto Exit; } + // Populate the information for each program type. for (uint32_t i = 0; i < program_info_count; i++) { - ebpf_store_key_t program_key = {0}; - ebpf_store_key_t helper_info_key = {0}; - - // Convert program type GUID to string. - wchar_t guid_string[GUID_STRING_LENGTH + 1]; - result = ebpf_convert_guid_to_string( - &program_info[i].program_type_descriptor.program_type, guid_string, GUID_STRING_LENGTH + 1); - if (!IS_SUCCESS(result)) { - return result; - } - - result = ebpf_create_registry_key(program_info_key, guid_string, REG_CREATE_FLAGS, &program_key); - if (!IS_SUCCESS(result)) { - goto Exit; - } - - // Save the friendly program type name. - wchar_t* wide_program_name = ebpf_get_wstring_from_string(program_info[i].program_type_descriptor.name); - if (wide_program_name == NULL) { - result = EBPF_NO_MEMORY; - goto Exit; - } - result = ebpf_write_registry_value_string(program_key, EBPF_PROGRAM_DATA_NAME, wide_program_name); - if (!IS_SUCCESS(result)) { - ebpf_free_wstring(wide_program_name); - ebpf_close_registry_key(program_key); - goto Exit; - } - ebpf_free_wstring(wide_program_name); + ebpf_store_key_t program_info_key = {0}; - // Save context descriptor. - result = ebpf_write_registry_value_binary( - program_key, - EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR, - (uint8_t*)program_info[i].program_type_descriptor.context_descriptor, - sizeof(ebpf_context_descriptor_t)); - if (!IS_SUCCESS(result)) { - ebpf_close_registry_key(program_key); + if (!ebpf_validate_program_info(&program_info[i])) { + result = EBPF_INVALID_ARGUMENT; goto Exit; } - // Save bpf_prog_type. - result = ebpf_write_registry_value_dword( - program_key, EBPF_DATA_BPF_PROG_TYPE, program_info[i].program_type_descriptor.bpf_prog_type); + // Convert program type GUID to string. + wchar_t guid_string[GUID_STRING_LENGTH + 1]; + result = ebpf_convert_guid_to_string( + &program_info[i].program_type_descriptor->program_type, guid_string, GUID_STRING_LENGTH + 1); if (!IS_SUCCESS(result)) { - ebpf_close_registry_key(program_key); goto Exit; } - // Save "is_privileged". - result = ebpf_write_registry_value_dword( - program_key, EBPF_PROGRAM_DATA_PRIVILEGED, program_info[i].program_type_descriptor.is_privileged); + // Create program information key with the program type GUID as the name. + result = ebpf_create_registry_key(program_data_key, guid_string, REG_CREATE_FLAGS, &program_info_key); if (!IS_SUCCESS(result)) { - ebpf_close_registry_key(program_key); goto Exit; } - // Save helper count. - result = ebpf_write_registry_value_dword( - program_key, EBPF_PROGRAM_DATA_HELPER_COUNT, program_info[i].count_of_program_type_specific_helpers); + // Save program information. + result = _ebpf_store_update_program_info(program_info_key, &program_info[i]); + ebpf_close_registry_key(program_info_key); if (!IS_SUCCESS(result)) { - ebpf_close_registry_key(program_key); goto Exit; } - - if (program_info[i].count_of_program_type_specific_helpers != 0) { - // Create (or open) helper registry path. - result = ebpf_create_registry_key( - program_key, EBPF_PROGRAM_DATA_HELPERS_REGISTRY_PATH, REG_CREATE_FLAGS, &helper_info_key); - if (!IS_SUCCESS(result)) { - ebpf_close_registry_key(program_key); - goto Exit; - } - - // Iterate over all the helper prototypes and save in registry. - for (uint32_t count = 0; count < program_info[i].count_of_program_type_specific_helpers; count++) { - result = _ebpf_store_update_helper_prototype( - helper_info_key, &(program_info[i].program_type_specific_helper_prototype[count])); - if (!IS_SUCCESS(result)) { - ebpf_close_registry_key(program_key); - ebpf_close_registry_key(helper_info_key); - goto Exit; - } - } - - ebpf_close_registry_key(helper_info_key); - } - ebpf_close_registry_key(program_key); } Exit: - ebpf_close_registry_key(program_info_key); + ebpf_close_registry_key(program_data_key); ebpf_close_registry_key(provider_key); return result; @@ -336,7 +417,7 @@ ebpf_store_delete_program_information(_In_ const ebpf_program_info_t* program_in } // Open program data registry path. - result = ebpf_open_registry_key(provider_key, EBPF_PROGRAM_DATA_REGISTRY_PATH, REG_CREATE_FLAGS, &program_info_key); + result = ebpf_open_registry_key(provider_key, EBPF_PROGRAM_DATA_REGISTRY_KEY, REG_CREATE_FLAGS, &program_info_key); if (!IS_SUCCESS(result)) { goto Exit; } @@ -344,7 +425,7 @@ ebpf_store_delete_program_information(_In_ const ebpf_program_info_t* program_in // Convert program type GUID to string. wchar_t guid_string[GUID_STRING_LENGTH + 1]; result = ebpf_convert_guid_to_string( - &program_info->program_type_descriptor.program_type, guid_string, GUID_STRING_LENGTH + 1); + &program_info->program_type_descriptor->program_type, guid_string, GUID_STRING_LENGTH + 1); if (!IS_SUCCESS(result)) { goto Exit; } @@ -375,7 +456,7 @@ ebpf_store_delete_section_information(_In_ const ebpf_program_section_info_t* se } // Open (or create) section data key. - result = ebpf_open_registry_key(provider_key, EBPF_SECTIONS_REGISTRY_PATH, REG_DELETE_FLAGS, §ion_info_key); + result = ebpf_open_registry_key(provider_key, EBPF_SECTIONS_REGISTRY_KEY, REG_DELETE_FLAGS, §ion_info_key); if (!IS_SUCCESS(result)) { goto Exit; } diff --git a/libs/ubpf/kernel/ubpf_kernel.vcxproj b/libs/ubpf/kernel/ubpf_kernel.vcxproj index 86b3f0658c..13159212dc 100644 --- a/libs/ubpf/kernel/ubpf_kernel.vcxproj +++ b/libs/ubpf/kernel/ubpf_kernel.vcxproj @@ -83,7 +83,7 @@ _DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions);_NO_CRT_STDIO_INLINE=1 - $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\kernel;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\kernel;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winkernel;$(SolutionDir)libs\ubpf;$(SolutionDir)libs\ubpf\kernel;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm + $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\kernel;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\kernel;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winkernel;$(SolutionDir)libs\ubpf;$(SolutionDir)libs\ubpf\kernel;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;$(SolutionDir)external\ebpf-verifier\src %(DisableSpecificWarnings) false @@ -91,7 +91,7 @@ _DEBUG;WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions);_NO_CRT_STDIO_INLINE=1 - $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\kernel;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\kernel;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winkernel;$(SolutionDir)libs\ubpf;$(SolutionDir)libs\ubpf\kernel;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm + $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\kernel;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\kernel;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winkernel;$(SolutionDir)libs\ubpf;$(SolutionDir)libs\ubpf\kernel;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;$(SolutionDir)external\ebpf-verifier\src %(DisableSpecificWarnings) false @@ -102,7 +102,7 @@ WINAPI_FAMILY=WINAPI_FAMILY_DESKTOP_APP;WINAPI_PARTITION_DESKTOP=1;WINAPI_PARTITION_SYSTEM=1;WINAPI_PARTITION_APP=1;WINAPI_PARTITION_PC_APP=1;%(PreprocessorDefinitions);_NO_CRT_STDIO_INLINE=1;NDEBUG - $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\kernel;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\kernel;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winkernel;$(SolutionDir)libs\ubpf;$(SolutionDir)libs\ubpf\kernel;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm + $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\kernel;$(SolutionDir)libs\runtime;$(SolutionDir)libs\runtime\kernel;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winkernel;$(SolutionDir)libs\ubpf;$(SolutionDir)libs\ubpf\kernel;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;$(SolutionDir)external\ebpf-verifier\src %(DisableSpecificWarnings) false diff --git a/libs/ubpf/user/ubpf_user.vcxproj b/libs/ubpf/user/ubpf_user.vcxproj index a48a4abc3e..47de318954 100644 --- a/libs/ubpf/user/ubpf_user.vcxproj +++ b/libs/ubpf/user/ubpf_user.vcxproj @@ -84,7 +84,7 @@ true NotUsing pch.h - $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\ubpf;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;%(AdditionalIncludeDirectories) + $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\ubpf;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) false @@ -99,7 +99,7 @@ true NotUsing pch.h - $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\ubpf;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;%(AdditionalIncludeDirectories) + $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\ubpf;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) false @@ -117,7 +117,7 @@ true NotUsing pch.h - $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\ubpf;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;%(AdditionalIncludeDirectories) + $(SolutionDir)include;$(SolutionDir)libs\shared;$(SolutionDir)libs\shared\user;$(SolutionDir)external\usersim\inc;$(SolutionDir)external\usersim\cxplat\inc;$(SolutionDir)external\usersim\cxplat\inc\winuser;$(SolutionDir)libs\ubpf;$(SolutionDir)external\ubpf\vm;$(SolutionDir)external\ubpf\vm\inc;$(SolutionDir)external\ubpf\build\vm;$(SolutionDir)external\ebpf-verifier\src;%(AdditionalIncludeDirectories) false diff --git a/netebpfext/net_ebpf_ext_bind.c b/netebpfext/net_ebpf_ext_bind.c index 1c65c291c2..1292aca606 100644 --- a/netebpfext/net_ebpf_ext_bind.c +++ b/netebpfext/net_ebpf_ext_bind.c @@ -57,28 +57,30 @@ _ebpf_bind_context_destroy( // Bind Program Information NPI Provider. // static ebpf_program_data_t _ebpf_bind_program_data = { + .header = {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, .program_info = &_ebpf_bind_program_info, .context_create = _ebpf_bind_context_create, .context_destroy = _ebpf_bind_context_destroy, .required_irql = PASSIVE_LEVEL, }; -static ebpf_extension_data_t _ebpf_bind_program_info_provider_data = { - NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_bind_program_data), &_ebpf_bind_program_data}; - -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_bind_program_info_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +// Set the program type as the provider module id. +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_bind_program_info_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_PROGRAM_TYPE_BIND_GUID}; static net_ebpf_extension_program_info_provider_t* _ebpf_bind_program_info_provider_context = NULL; // // Bind Hook NPI Provider. // -ebpf_attach_provider_data_t _net_ebpf_bind_hook_provider_data; - -ebpf_extension_data_t _net_ebpf_extension_bind_hook_provider_data = { - EBPF_ATTACH_PROVIDER_DATA_VERSION, sizeof(_net_ebpf_bind_hook_provider_data), &_net_ebpf_bind_hook_provider_data}; +ebpf_attach_provider_data_t _net_ebpf_bind_hook_provider_data = { + {EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION, sizeof(_net_ebpf_bind_hook_provider_data)}, + EBPF_PROGRAM_TYPE_BIND_GUID, + BPF_ATTACH_TYPE_BIND, + BPF_LINK_TYPE_PLAIN}; -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_bind_hook_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_bind_hook_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_ATTACH_TYPE_BIND_GUID}; static net_ebpf_extension_hook_provider_t* _ebpf_bind_hook_provider_context = NULL; @@ -159,12 +161,10 @@ net_ebpf_ext_bind_register_providers() NET_EBPF_EXT_LOG_ENTRY(); const net_ebpf_extension_program_info_provider_parameters_t program_info_provider_parameters = { - &_ebpf_bind_program_info_provider_moduleid, &_ebpf_bind_program_info_provider_data}; + &_ebpf_bind_program_info_provider_moduleid, &_ebpf_bind_program_data}; const net_ebpf_extension_hook_provider_parameters_t hook_provider_parameters = { - &_ebpf_bind_hook_provider_moduleid, &_net_ebpf_extension_bind_hook_provider_data}; + &_ebpf_bind_hook_provider_moduleid, &_net_ebpf_bind_hook_provider_data}; - // Set the program type as the provider module id. - _ebpf_bind_program_info_provider_moduleid.Guid = EBPF_PROGRAM_TYPE_BIND; status = net_ebpf_extension_program_info_provider_register( &program_info_provider_parameters, &_ebpf_bind_program_info_provider_context); if (!NT_SUCCESS(status)) { @@ -176,11 +176,6 @@ net_ebpf_ext_bind_register_providers() goto Exit; } - _net_ebpf_bind_hook_provider_data.supported_program_type = EBPF_PROGRAM_TYPE_BIND; - // Set the attach type as the provider module id. - _ebpf_bind_hook_provider_moduleid.Guid = EBPF_ATTACH_TYPE_BIND; - _net_ebpf_bind_hook_provider_data.bpf_attach_type = BPF_ATTACH_TYPE_BIND; - _net_ebpf_bind_hook_provider_data.link_type = BPF_LINK_TYPE_PLAIN; status = net_ebpf_extension_hook_provider_register( &hook_provider_parameters, _net_ebpf_extension_bind_on_client_attach, diff --git a/netebpfext/net_ebpf_ext_hook_provider.h b/netebpfext/net_ebpf_ext_hook_provider.h index 6f02c78227..7aae0356b7 100644 --- a/netebpfext/net_ebpf_ext_hook_provider.h +++ b/netebpfext/net_ebpf_ext_hook_provider.h @@ -112,8 +112,8 @@ typedef void (*net_ebpf_extension_hook_on_client_detach)(_In_ const net_ebpf_ext */ typedef struct _net_ebpf_extension_hook_provider_parameters { - const NPI_MODULEID* provider_module_id; ///< NPI provider module ID. - const ebpf_extension_data_t* provider_data; ///< Hook provider data (contains supported program types). + const NPI_MODULEID* provider_module_id; ///< NPI provider module ID. + const ebpf_attach_provider_data_t* provider_data; ///< Hook provider data (contains supported program types). } net_ebpf_extension_hook_provider_parameters_t; /** diff --git a/netebpfext/net_ebpf_ext_prog_info_provider.h b/netebpfext/net_ebpf_ext_prog_info_provider.h index e89e2d6c83..4065494a60 100644 --- a/netebpfext/net_ebpf_ext_prog_info_provider.h +++ b/netebpfext/net_ebpf_ext_prog_info_provider.h @@ -12,8 +12,8 @@ typedef struct _net_ebpf_extension_program_info_provider net_ebpf_extension_prog */ typedef struct _net_ebpf_extension_program_info_provider_parameters { - const NPI_MODULEID* provider_module_id; ///< NPI provider module ID. - const ebpf_extension_data_t* provider_data; ///< Program info NPI provider data (contains ebpf_program_data_t). + const NPI_MODULEID* provider_module_id; ///< NPI provider module ID. + const ebpf_program_data_t* provider_data; ///< Program info NPI provider data. } net_ebpf_extension_program_info_provider_parameters_t; /** diff --git a/netebpfext/net_ebpf_ext_program_info.h b/netebpfext/net_ebpf_ext_program_info.h index b3aeccb204..7df896abca 100644 --- a/netebpfext/net_ebpf_ext_program_info.h +++ b/netebpfext/net_ebpf_ext_program_info.h @@ -11,7 +11,8 @@ // XDP_TEST helper function prototype descriptors. static const ebpf_helper_function_prototype_t _xdp_test_ebpf_extension_helper_function_prototype[] = { - {XDP_EXT_HELPER_FUNCTION_START + 1, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + XDP_EXT_HELPER_FUNCTION_START + 1, "bpf_xdp_adjust_head", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_ANYTHING}}}; @@ -23,13 +24,22 @@ static const ebpf_context_descriptor_t _ebpf_xdp_test_context_descriptor = { EBPF_OFFSET_OF(xdp_md_t, data_end), EBPF_OFFSET_OF(xdp_md_t, data_meta)}; +static const ebpf_program_type_descriptor_t _ebpf_xdp_test_program_type_descriptor = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "xdp_test", + &_ebpf_xdp_test_context_descriptor, + EBPF_PROGRAM_TYPE_XDP_TEST_GUID, + BPF_PROG_TYPE_XDP_TEST, + 0}; static const ebpf_program_info_t _ebpf_xdp_test_program_info = { - {"xdp_test", &_ebpf_xdp_test_context_descriptor, EBPF_PROGRAM_TYPE_XDP_TEST_GUID, BPF_PROG_TYPE_XDP_TEST}, + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_ebpf_xdp_test_program_type_descriptor, EBPF_COUNT_OF(_xdp_test_ebpf_extension_helper_function_prototype), _xdp_test_ebpf_extension_helper_function_prototype}; static const ebpf_program_section_info_t _ebpf_xdp_test_section_info[] = { - {(const wchar_t*)L"xdp_test", + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"xdp_test", &EBPF_PROGRAM_TYPE_XDP_TEST, &EBPF_ATTACH_TYPE_XDP_TEST, BPF_PROG_TYPE_XDP_TEST, @@ -39,30 +49,54 @@ static const ebpf_program_section_info_t _ebpf_xdp_test_section_info[] = { static const ebpf_context_descriptor_t _ebpf_bind_context_descriptor = { sizeof(bind_md_t), EBPF_OFFSET_OF(bind_md_t, app_id_start), EBPF_OFFSET_OF(bind_md_t, app_id_end), -1}; +static const ebpf_program_type_descriptor_t _ebpf_bind_program_type_descriptor = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "bind", + &_ebpf_bind_context_descriptor, + EBPF_PROGRAM_TYPE_BIND_GUID, + BPF_PROG_TYPE_BIND, + 0}; static const ebpf_program_info_t _ebpf_bind_program_info = { - {"bind", &_ebpf_bind_context_descriptor, EBPF_PROGRAM_TYPE_BIND_GUID, BPF_PROG_TYPE_BIND}, 0, NULL}; + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_ebpf_bind_program_type_descriptor, + 0, + NULL, + 0, + NULL}; static const ebpf_program_section_info_t _ebpf_bind_section_info[] = { - {L"bind", &EBPF_PROGRAM_TYPE_BIND, &EBPF_ATTACH_TYPE_BIND, BPF_PROG_TYPE_BIND, BPF_ATTACH_TYPE_BIND}}; + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"bind", + &EBPF_PROGRAM_TYPE_BIND, + &EBPF_ATTACH_TYPE_BIND, + BPF_PROG_TYPE_BIND, + BPF_ATTACH_TYPE_BIND}}; // CGROUP_SOCK_ADDR extension specific helper function prototypes. static const ebpf_helper_function_prototype_t _sock_addr_ebpf_extension_helper_function_prototype[] = { - {BPF_FUNC_sock_addr_get_current_pid_tgid, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_sock_addr_get_current_pid_tgid, "bpf_sock_addr_get_current_pid_tgid", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, - {BPF_FUNC_sock_addr_set_redirect_context, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_sock_addr_set_redirect_context, "bpf_sock_addr_set_redirect_context", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE}}}; // CGROUP_SOCK_ADDR global helper function prototypes. static const ebpf_helper_function_prototype_t _ebpf_sock_addr_global_helper_function_prototype[] = { - {BPF_FUNC_get_current_logon_id, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_get_current_logon_id, "bpf_get_current_logon_id", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, - {BPF_FUNC_is_current_admin, "bpf_is_current_admin", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}}; + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_is_current_admin, + "bpf_is_current_admin", + EBPF_RETURN_TYPE_INTEGER, + {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}}; // CGROUP_SOCK_ADDR program information. static const ebpf_context_descriptor_t _ebpf_sock_addr_context_descriptor = { @@ -72,33 +106,42 @@ static const ebpf_context_descriptor_t _ebpf_sock_addr_context_descriptor = { -1, // Offset into ctx struct for pointer to metadata, or -1 if none. }; +static const ebpf_program_type_descriptor_t _ebpf_sock_addr_program_type_desciptor = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "sock_addr", + &_ebpf_sock_addr_context_descriptor, + EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR_GUID, + BPF_PROG_TYPE_CGROUP_SOCK_ADDR, + 0}; static const ebpf_program_info_t _ebpf_sock_addr_program_info = { - {"sock_addr", - &_ebpf_sock_addr_context_descriptor, - EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR_GUID, - BPF_PROG_TYPE_CGROUP_SOCK_ADDR}, + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_ebpf_sock_addr_program_type_desciptor, EBPF_COUNT_OF(_sock_addr_ebpf_extension_helper_function_prototype), _sock_addr_ebpf_extension_helper_function_prototype, EBPF_COUNT_OF(_ebpf_sock_addr_global_helper_function_prototype), _ebpf_sock_addr_global_helper_function_prototype}; static const ebpf_program_section_info_t _ebpf_sock_addr_section_info[] = { - {L"cgroup/connect4", + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"cgroup/connect4", &EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR, &EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_CONNECT}, - {L"cgroup/connect6", + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"cgroup/connect6", &EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR, &EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET6_CONNECT}, - {L"cgroup/recv_accept4", + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"cgroup/recv_accept4", &EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR, &EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, BPF_CGROUP_INET4_RECV_ACCEPT}, - {L"cgroup/recv_accept6", + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"cgroup/recv_accept6", &EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR, &EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT, BPF_PROG_TYPE_CGROUP_SOCK_ADDR, @@ -112,11 +155,24 @@ static const ebpf_context_descriptor_t _ebpf_sock_ops_context_descriptor = { -1, // Offset into ctx struct for pointer to metadata, or -1 if none. }; +static const ebpf_program_type_descriptor_t _ebpf_sock_ops_program_type_descriptor = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "sockops", + &_ebpf_sock_ops_context_descriptor, + EBPF_PROGRAM_TYPE_SOCK_OPS_GUID, + BPF_PROG_TYPE_SOCK_OPS, + 0}; static const ebpf_program_info_t _ebpf_sock_ops_program_info = { - {"sockops", &_ebpf_sock_ops_context_descriptor, EBPF_PROGRAM_TYPE_SOCK_OPS_GUID, BPF_PROG_TYPE_SOCK_OPS}, 0, NULL}; + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_ebpf_sock_ops_program_type_descriptor, + 0, + NULL, + 0, + NULL}; static const ebpf_program_section_info_t _ebpf_sock_ops_section_info[] = { - {L"sockops", + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"sockops", &EBPF_PROGRAM_TYPE_SOCK_OPS, &EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS, BPF_PROG_TYPE_SOCK_OPS, diff --git a/netebpfext/net_ebpf_ext_sock_addr.c b/netebpfext/net_ebpf_ext_sock_addr.c index dbbd1b7c57..cd1808e845 100644 --- a/netebpfext/net_ebpf_ext_sock_addr.c +++ b/netebpfext/net_ebpf_ext_sock_addr.c @@ -470,15 +470,20 @@ static const void* _ebpf_sock_addr_specific_helper_functions[] = { (void*)_ebpf_sock_addr_get_current_pid_tgid, (void*)_ebpf_sock_addr_set_redirect_context}; static ebpf_helper_function_addresses_t _ebpf_sock_addr_specific_helper_function_address_table = { - EBPF_COUNT_OF(_ebpf_sock_addr_specific_helper_functions), (uint64_t*)_ebpf_sock_addr_specific_helper_functions}; + {EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_MAX_GENERAL_HELPER_FUNCTION}, + EBPF_COUNT_OF(_ebpf_sock_addr_specific_helper_functions), + (uint64_t*)_ebpf_sock_addr_specific_helper_functions}; static const void* _ebpf_sock_addr_global_helper_functions[] = { (void*)_ebpf_sock_addr_get_current_logon_id, (void*)_ebpf_sock_addr_is_current_admin}; static ebpf_helper_function_addresses_t _ebpf_sock_addr_global_helper_function_address_table = { - EBPF_COUNT_OF(_ebpf_sock_addr_global_helper_functions), (uint64_t*)_ebpf_sock_addr_global_helper_functions}; + {EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_MAX_GENERAL_HELPER_FUNCTION}, + EBPF_COUNT_OF(_ebpf_sock_addr_global_helper_functions), + (uint64_t*)_ebpf_sock_addr_global_helper_functions}; static ebpf_program_data_t _ebpf_sock_addr_program_data = { + .header = {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, .program_info = &_ebpf_sock_addr_program_info, .program_type_specific_helper_function_addresses = &_ebpf_sock_addr_specific_helper_function_address_table, .global_helper_function_addresses = &_ebpf_sock_addr_global_helper_function_address_table, @@ -487,10 +492,9 @@ static ebpf_program_data_t _ebpf_sock_addr_program_data = { .required_irql = DISPATCH_LEVEL, }; -static ebpf_extension_data_t _ebpf_sock_addr_program_info_provider_data = { - NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_sock_addr_program_data), &_ebpf_sock_addr_program_data}; - -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_addr_program_info_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +// Set the program type as the provider module id. +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_addr_program_info_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR_GUID}; static net_ebpf_extension_program_info_provider_t* _ebpf_sock_addr_program_info_provider_context = NULL; @@ -499,7 +503,6 @@ static net_ebpf_extension_program_info_provider_t* _ebpf_sock_addr_program_info_ // ebpf_attach_provider_data_t _net_ebpf_sock_addr_hook_provider_data[NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT] = {0}; -ebpf_extension_data_t _net_ebpf_extension_sock_addr_hook_provider_data[NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT] = {0}; NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_addr_hook_provider_moduleid[NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT] = {0}; static net_ebpf_extension_hook_provider_t* @@ -535,8 +538,8 @@ _net_ebpf_extension_sock_addr_on_client_attach( goto Exit; } - if (client_data->size > 0) { - if ((client_data->size != sizeof(uint32_t)) || (client_data->data == NULL)) { + if (client_data->header.size > 0) { + if ((client_data->header.size != sizeof(uint32_t)) || (client_data->data == NULL)) { NET_EBPF_EXT_LOG_MESSAGE( NET_EBPF_EXT_TRACELOG_LEVEL_ERROR, NET_EBPF_EXT_TRACELOG_KEYWORD_SOCK_ADDR, @@ -883,7 +886,7 @@ net_ebpf_ext_sock_addr_register_providers() NET_EBPF_EXT_LOG_ENTRY(); const net_ebpf_extension_program_info_provider_parameters_t program_info_provider_parameters = { - &_ebpf_sock_addr_program_info_provider_moduleid, &_ebpf_sock_addr_program_info_provider_data}; + &_ebpf_sock_addr_program_info_provider_moduleid, &_ebpf_sock_addr_program_data}; status = _net_ebpf_sock_addr_create_security_descriptor(); if (!NT_SUCCESS(status)) { @@ -898,8 +901,6 @@ net_ebpf_ext_sock_addr_register_providers() _net_ebpf_sock_addr_initialize_globals(); sock_addr_globals_initialized = TRUE; - // Set the program type as the provider module id. - _ebpf_sock_addr_program_info_provider_moduleid.Guid = EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR; status = net_ebpf_extension_program_info_provider_register( &program_info_provider_parameters, &_ebpf_sock_addr_program_info_provider_context); if (!NT_SUCCESS(status)) { @@ -913,15 +914,14 @@ net_ebpf_ext_sock_addr_register_providers() for (int i = 0; i < NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT; i++) { const net_ebpf_extension_hook_provider_parameters_t hook_provider_parameters = { - &_ebpf_sock_addr_hook_provider_moduleid[i], &_net_ebpf_extension_sock_addr_hook_provider_data[i]}; + &_ebpf_sock_addr_hook_provider_moduleid[i], &_net_ebpf_sock_addr_hook_provider_data[i]}; + _net_ebpf_sock_addr_hook_provider_data[i].header.version = EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION; + _net_ebpf_sock_addr_hook_provider_data[i].header.size = sizeof(ebpf_attach_provider_data_t); _net_ebpf_sock_addr_hook_provider_data[i].supported_program_type = EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR; _net_ebpf_sock_addr_hook_provider_data[i].bpf_attach_type = (bpf_attach_type_t)_net_ebpf_extension_sock_addr_bpf_attach_types[i]; _net_ebpf_sock_addr_hook_provider_data[i].link_type = BPF_LINK_TYPE_CGROUP; - _net_ebpf_extension_sock_addr_hook_provider_data[i].version = EBPF_ATTACH_PROVIDER_DATA_VERSION; - _net_ebpf_extension_sock_addr_hook_provider_data[i].data = &_net_ebpf_sock_addr_hook_provider_data[i]; - _net_ebpf_extension_sock_addr_hook_provider_data[i].size = sizeof(ebpf_attach_provider_data_t); // Set the attach type as the provider module id. _ebpf_sock_addr_hook_provider_moduleid[i].Length = sizeof(NPI_MODULEID); diff --git a/netebpfext/net_ebpf_ext_sock_ops.c b/netebpfext/net_ebpf_ext_sock_ops.c index 12a577399a..75749e3a86 100644 --- a/netebpfext/net_ebpf_ext_sock_ops.c +++ b/netebpfext/net_ebpf_ext_sock_ops.c @@ -79,16 +79,16 @@ _ebpf_sock_ops_context_destroy( _Inout_ size_t* context_size_out); static ebpf_program_data_t _ebpf_sock_ops_program_data = { + .header = {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, .program_info = &_ebpf_sock_ops_program_info, .context_create = &_ebpf_sock_ops_context_create, .context_destroy = &_ebpf_sock_ops_context_destroy, .required_irql = DISPATCH_LEVEL, }; -static ebpf_extension_data_t _ebpf_sock_ops_program_info_provider_data = { - NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_sock_ops_program_data), &_ebpf_sock_ops_program_data}; - -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_ops_program_info_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +// Set the program type as the provider module id. +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_ops_program_info_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_PROGRAM_TYPE_SOCK_OPS_GUID}; static net_ebpf_extension_program_info_provider_t* _ebpf_sock_ops_program_info_provider_context = NULL; @@ -96,14 +96,14 @@ static net_ebpf_extension_program_info_provider_t* _ebpf_sock_ops_program_info_p // SOCK_OPS Hook NPI Provider. // -ebpf_attach_provider_data_t _net_ebpf_sock_ops_hook_provider_data; - -ebpf_extension_data_t _net_ebpf_extension_sock_ops_hook_provider_data = { - EBPF_ATTACH_PROVIDER_DATA_VERSION, - sizeof(_net_ebpf_sock_ops_hook_provider_data), - &_net_ebpf_sock_ops_hook_provider_data}; +ebpf_attach_provider_data_t _net_ebpf_sock_ops_hook_provider_data = { + {EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION, sizeof(ebpf_attach_provider_data_t)}, + EBPF_PROGRAM_TYPE_SOCK_OPS_GUID, + BPF_CGROUP_SOCK_OPS, + BPF_LINK_TYPE_CGROUP}; -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_ops_hook_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_sock_ops_hook_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS_GUID}; static net_ebpf_extension_hook_provider_t* _ebpf_sock_ops_hook_provider_context = NULL; @@ -132,8 +132,8 @@ net_ebpf_extension_sock_ops_on_client_attach( goto Exit; } - if (client_data->size > 0) { - if ((client_data->size != sizeof(uint32_t)) || (client_data->data == NULL)) { + if (client_data->header.size > 0) { + if ((client_data->header.size != sizeof(uint32_t)) || (client_data->data == NULL)) { result = EBPF_INVALID_ARGUMENT; goto Exit; } @@ -255,15 +255,13 @@ net_ebpf_ext_sock_ops_register_providers() { NTSTATUS status = STATUS_SUCCESS; const net_ebpf_extension_hook_provider_parameters_t hook_provider_parameters = { - &_ebpf_sock_ops_hook_provider_moduleid, &_net_ebpf_extension_sock_ops_hook_provider_data}; + &_ebpf_sock_ops_hook_provider_moduleid, &_net_ebpf_sock_ops_hook_provider_data}; const net_ebpf_extension_program_info_provider_parameters_t program_info_provider_parameters = { - &_ebpf_sock_ops_program_info_provider_moduleid, &_ebpf_sock_ops_program_info_provider_data}; + &_ebpf_sock_ops_program_info_provider_moduleid, &_ebpf_sock_ops_program_data}; NET_EBPF_EXT_LOG_ENTRY(); - // Set the program type as the provider module id. - _ebpf_sock_ops_program_info_provider_moduleid.Guid = EBPF_PROGRAM_TYPE_SOCK_OPS; status = net_ebpf_extension_program_info_provider_register( &program_info_provider_parameters, &_ebpf_sock_ops_program_info_provider_context); if (!NT_SUCCESS(status)) { @@ -275,12 +273,6 @@ net_ebpf_ext_sock_ops_register_providers() goto Exit; } - _net_ebpf_sock_ops_hook_provider_data.supported_program_type = EBPF_PROGRAM_TYPE_SOCK_OPS; - _net_ebpf_sock_ops_hook_provider_data.bpf_attach_type = BPF_CGROUP_SOCK_OPS; - _net_ebpf_sock_ops_hook_provider_data.link_type = BPF_LINK_TYPE_CGROUP; - - // Set the attach type as the provider module id. - _ebpf_sock_ops_hook_provider_moduleid.Guid = EBPF_ATTACH_TYPE_CGROUP_SOCK_OPS; // Register the provider context and pass the pointer to the WFP filter parameters // corresponding to this hook type as custom data. status = net_ebpf_extension_hook_provider_register( diff --git a/netebpfext/net_ebpf_ext_xdp.c b/netebpfext/net_ebpf_ext_xdp.c index a9e68e8389..796151f5b5 100644 --- a/netebpfext/net_ebpf_ext_xdp.c +++ b/netebpfext/net_ebpf_ext_xdp.c @@ -83,9 +83,12 @@ _ebpf_xdp_context_delete( static const void* _ebpf_xdp_test_helper_functions[] = {(void*)&_net_ebpf_xdp_adjust_head}; static ebpf_helper_function_addresses_t _ebpf_xdp_test_helper_function_address_table = { - EBPF_COUNT_OF(_ebpf_xdp_test_helper_functions), (uint64_t*)_ebpf_xdp_test_helper_functions}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_ebpf_xdp_test_helper_functions), + (uint64_t*)_ebpf_xdp_test_helper_functions}; static ebpf_program_data_t _ebpf_xdp_test_program_data = { + .header = {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, .program_info = &_ebpf_xdp_test_program_info, .program_type_specific_helper_function_addresses = &_ebpf_xdp_test_helper_function_address_table, .context_create = _ebpf_xdp_context_create, @@ -93,10 +96,9 @@ static ebpf_program_data_t _ebpf_xdp_test_program_data = { .required_irql = DISPATCH_LEVEL, }; -static ebpf_extension_data_t _ebpf_xdp_test_program_info_provider_data = { - NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_xdp_test_program_data), &_ebpf_xdp_test_program_data}; - -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_xdp_test_program_info_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +// Set the program type as the provider module id. +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_xdp_test_program_info_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_PROGRAM_TYPE_XDP_TEST_GUID}; static net_ebpf_extension_program_info_provider_t* _ebpf_xdp_test_program_info_provider_context = NULL; @@ -104,14 +106,14 @@ static net_ebpf_extension_program_info_provider_t* _ebpf_xdp_test_program_info_p // XDP Hook NPI Provider. // -ebpf_attach_provider_data_t _net_ebpf_xdp_test_hook_provider_data; - -ebpf_extension_data_t _net_ebpf_extension_xdp_test_hook_provider_data = { - EBPF_ATTACH_PROVIDER_DATA_VERSION, - sizeof(_net_ebpf_xdp_test_hook_provider_data), - &_net_ebpf_xdp_test_hook_provider_data}; +ebpf_attach_provider_data_t _net_ebpf_xdp_test_hook_provider_data = { + {EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION, sizeof(ebpf_attach_provider_data_t)}, + EBPF_PROGRAM_TYPE_XDP_TEST_GUID, + BPF_XDP_TEST, + BPF_LINK_TYPE_XDP}; -NPI_MODULEID DECLSPEC_SELECTANY _ebpf_xdp_test_hook_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +NPI_MODULEID DECLSPEC_SELECTANY _ebpf_xdp_test_hook_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_ATTACH_TYPE_XDP_TEST_GUID}; static net_ebpf_extension_hook_provider_t* _ebpf_xdp_test_hook_provider_context = NULL; @@ -144,8 +146,8 @@ net_ebpf_extension_xdp_on_client_attach( goto Exit; } - if (client_data->size > 0) { - if ((client_data->size != sizeof(uint32_t)) || (client_data->data == NULL)) { + if (client_data->header.size > 0) { + if ((client_data->header.size != sizeof(uint32_t)) || (client_data->data == NULL)) { result = EBPF_INVALID_ARGUMENT; NET_EBPF_EXT_LOG_MESSAGE( NET_EBPF_EXT_TRACELOG_LEVEL_ERROR, @@ -251,14 +253,12 @@ net_ebpf_ext_xdp_register_providers() NTSTATUS status = STATUS_SUCCESS; const net_ebpf_extension_program_info_provider_parameters_t program_info_provider_parameters = { - &_ebpf_xdp_test_program_info_provider_moduleid, &_ebpf_xdp_test_program_info_provider_data}; + &_ebpf_xdp_test_program_info_provider_moduleid, &_ebpf_xdp_test_program_data}; const net_ebpf_extension_hook_provider_parameters_t hook_provider_parameters = { - &_ebpf_xdp_test_hook_provider_moduleid, &_net_ebpf_extension_xdp_test_hook_provider_data}; + &_ebpf_xdp_test_hook_provider_moduleid, &_net_ebpf_xdp_test_hook_provider_data}; NET_EBPF_EXT_LOG_ENTRY(); - // Set the program type as the provider module id. - _ebpf_xdp_test_program_info_provider_moduleid.Guid = EBPF_PROGRAM_TYPE_XDP_TEST; status = net_ebpf_extension_program_info_provider_register( &program_info_provider_parameters, &_ebpf_xdp_test_program_info_provider_context); if (!NT_SUCCESS(status)) { @@ -270,11 +270,6 @@ net_ebpf_ext_xdp_register_providers() goto Exit; } - _net_ebpf_xdp_test_hook_provider_data.supported_program_type = EBPF_PROGRAM_TYPE_XDP_TEST; - // Set the attach type as the provider module id. - _ebpf_xdp_test_hook_provider_moduleid.Guid = EBPF_ATTACH_TYPE_XDP_TEST; - _net_ebpf_xdp_test_hook_provider_data.bpf_attach_type = BPF_XDP_TEST; - _net_ebpf_xdp_test_hook_provider_data.link_type = BPF_LINK_TYPE_XDP; status = net_ebpf_extension_hook_provider_register( &hook_provider_parameters, net_ebpf_extension_xdp_on_client_attach, diff --git a/scripts/setup_ebpf_cicd_tests.ps1 b/scripts/setup_ebpf_cicd_tests.ps1 index 91593d84af..88ca9c4f84 100644 --- a/scripts/setup_ebpf_cicd_tests.ps1 +++ b/scripts/setup_ebpf_cicd_tests.ps1 @@ -2,13 +2,13 @@ # SPDX-License-Identifier: MIT param ([parameter(Mandatory=$false)][string] $Target = "TEST_VM", - [parameter(Mandatory=$true)][bool] $KmTracing, - [parameter(Mandatory=$true)][string] $KmTraceType, + [parameter(Mandatory=$false)][bool] $KmTracing = $true, + [parameter(Mandatory=$false)][string] $KmTraceType = "file", [parameter(Mandatory=$false)][string] $TestMode = "CI/CD", [parameter(Mandatory=$false)][string] $LogFileName = "TestLog.log", [parameter(Mandatory=$false)][string] $WorkingDirectory = $pwd.ToString(), [parameter(Mandatory=$false)][string] $TestExecutionJsonFileName = "test_execution.json", - [parameter(Mandatory=$false)][string] $SelfHostedRunnerName) + [parameter(Mandatory=$false)][string] $SelfHostedRunnerName = [System.Net.Dns]::GetHostName()) Push-Location $WorkingDirectory diff --git a/tests/end_to_end/end_to_end.cpp b/tests/end_to_end/end_to_end.cpp index 68994543ba..ae22828e39 100644 --- a/tests/end_to_end/end_to_end.cpp +++ b/tests/end_to_end/end_to_end.cpp @@ -3006,19 +3006,17 @@ extension_reload_test(ebpf_execution_type_t execution_type) // Reload the extension provider with missing helper function. { - ebpf_helper_function_addresses_t changed_helper_function_address_table = - _sample_ebpf_ext_helper_function_address_table; + ebpf_helper_function_addresses_t changed_helper_function_address_table = { + .header = {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + .helper_function_count = 0, + .helper_function_address = nullptr}; ebpf_program_data_t changed_program_data = _test_ebpf_sample_extension_program_data; changed_program_data.program_type_specific_helper_function_addresses = &changed_helper_function_address_table; - changed_helper_function_address_table.helper_function_count = 0; - - ebpf_extension_data_t changed_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(changed_program_data), &changed_program_data}; single_instance_hook_t hook(EBPF_PROGRAM_TYPE_SAMPLE, EBPF_ATTACH_TYPE_SAMPLE); REQUIRE(hook.initialize() == EBPF_SUCCESS); program_info_provider_t sample_program_info; - REQUIRE(sample_program_info.initialize(EBPF_PROGRAM_TYPE_SAMPLE, &changed_provider_data) == EBPF_SUCCESS); + REQUIRE(sample_program_info.initialize(EBPF_PROGRAM_TYPE_SAMPLE, &changed_program_data) == EBPF_SUCCESS); // Program should re-attach to the hook. @@ -3030,21 +3028,23 @@ extension_reload_test(ebpf_execution_type_t execution_type) // Reload the extension provider with changed helper function data. { + ebpf_helper_function_prototype_t helper_function_prototypes[3]; + std::copy( + _sample_ebpf_extension_helper_function_prototype, + _sample_ebpf_extension_helper_function_prototype + 3, + helper_function_prototypes); + // Change the return type of the helper function from EBPF_RETURN_TYPE_INTEGER to + // EBPF_RETURN_TYPE_PTR_TO_MAP_VALUE_OR_NULL. + helper_function_prototypes[0].return_type = EBPF_RETURN_TYPE_PTR_TO_MAP_VALUE_OR_NULL; ebpf_program_info_t changed_program_info = _sample_ebpf_extension_program_info; - ebpf_helper_function_prototype_t helper_function_prototypes[] = { - _sample_ebpf_extension_global_helper_function_prototype[0]}; - helper_function_prototypes[0].return_type = EBPF_RETURN_TYPE_INTEGER; changed_program_info.program_type_specific_helper_prototype = helper_function_prototypes; ebpf_program_data_t changed_program_data = _test_ebpf_sample_extension_program_data; changed_program_data.program_info = &changed_program_info; - ebpf_extension_data_t changed_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(changed_program_data), &changed_program_data}; - single_instance_hook_t hook(EBPF_PROGRAM_TYPE_SAMPLE, EBPF_ATTACH_TYPE_SAMPLE); REQUIRE(hook.initialize() == EBPF_SUCCESS); program_info_provider_t sample_program_info; - REQUIRE(sample_program_info.initialize(EBPF_PROGRAM_TYPE_SAMPLE, &changed_provider_data) == EBPF_SUCCESS); + REQUIRE(sample_program_info.initialize(EBPF_PROGRAM_TYPE_SAMPLE, &changed_program_data) == EBPF_SUCCESS); // Program should re-attach to the hook. diff --git a/tests/end_to_end/helpers.h b/tests/end_to_end/helpers.h index f8ef633754..8717c4329f 100644 --- a/tests/end_to_end/helpers.h +++ b/tests/end_to_end/helpers.h @@ -117,6 +117,8 @@ typedef class _single_instance_hook : public _hook_helper client_dispatch_table(nullptr), link_object(nullptr), client_registration_instance(nullptr), nmr_binding_handle(nullptr), nmr_provider_handle(nullptr) { + attach_provider_data.header.version = EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION; + attach_provider_data.header.size = sizeof(attach_provider_data); attach_provider_data.supported_program_type = program_type; attach_provider_data.bpf_attach_type = get_bpf_attach_type(&attach_type); this->attach_type = attach_type; @@ -308,8 +310,6 @@ typedef class _single_instance_hook : public _hook_helper ebpf_attach_type_t attach_type; ebpf_attach_provider_data_t attach_provider_data; - ebpf_extension_data_t provider_data = { - EBPF_ATTACH_PROVIDER_DATA_VERSION, sizeof(attach_provider_data), &attach_provider_data}; NPI_MODULEID module_id = { sizeof(NPI_MODULEID), MIT_GUID, @@ -321,12 +321,12 @@ typedef class _single_instance_hook : public _hook_helper (NPI_PROVIDER_DETACH_CLIENT_FN*)provider_detach_client_callback, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + 0, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_HOOK_EXTENSION_IID, &module_id, 0, - &provider_data, + &attach_provider_data, }, }; HANDLE nmr_provider_handle; @@ -621,51 +621,52 @@ _sample_test_context_destroy( static const void* _mock_xdp_helper_functions[] = {(void*)&test_xdp_helper_t::adjust_head}; static ebpf_helper_function_addresses_t _mock_xdp_helper_function_address_table = { - EBPF_COUNT_OF(_mock_xdp_helper_functions), (uint64_t*)_mock_xdp_helper_functions}; - + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_mock_xdp_helper_functions), + (uint64_t*)_mock_xdp_helper_functions}; + +static const ebpf_program_type_descriptor_t _mock_xdp_program_type_descriptor = { + EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, + EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE, + "xdp", + &_ebpf_xdp_test_context_descriptor, + EBPF_PROGRAM_TYPE_XDP_GUID, + BPF_PROG_TYPE_XDP, + 0}; static const ebpf_program_info_t _mock_xdp_program_info = { - {"xdp", &_ebpf_xdp_test_context_descriptor, EBPF_PROGRAM_TYPE_XDP_GUID, BPF_PROG_TYPE_XDP}, + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_mock_xdp_program_type_descriptor, EBPF_COUNT_OF(_xdp_test_ebpf_extension_helper_function_prototype), _xdp_test_ebpf_extension_helper_function_prototype}; static ebpf_program_data_t _mock_xdp_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, &_mock_xdp_program_info, &_mock_xdp_helper_function_address_table, nullptr, _xdp_context_create, _xdp_context_destroy}; -static ebpf_extension_data_t _mock_xdp_program_info_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_mock_xdp_program_data), &_mock_xdp_program_data}; - // XDP_TEST. static ebpf_program_data_t _ebpf_xdp_test_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, &_ebpf_xdp_test_program_info, &_mock_xdp_helper_function_address_table, nullptr, _xdp_context_create, _xdp_context_destroy}; -static ebpf_extension_data_t _ebpf_xdp_test_program_info_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_xdp_test_program_data), &_ebpf_xdp_test_program_data}; - // Bind. -static ebpf_program_data_t _ebpf_bind_program_data = {&_ebpf_bind_program_info, NULL}; - -static ebpf_extension_data_t _ebpf_bind_program_info_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_bind_program_data), &_ebpf_bind_program_data}; +static ebpf_program_data_t _ebpf_bind_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, &_ebpf_bind_program_info, NULL}; // CGROUP_SOCK_ADDR. -static ebpf_program_data_t _ebpf_sock_addr_program_data = {&_ebpf_sock_addr_program_info, NULL}; - -static ebpf_extension_data_t _ebpf_sock_addr_program_info_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_sock_addr_program_data), &_ebpf_sock_addr_program_data}; +static ebpf_program_data_t _ebpf_sock_addr_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, &_ebpf_sock_addr_program_info, NULL}; // SOCK_OPS. -static ebpf_program_data_t _ebpf_sock_ops_program_data = {&_ebpf_sock_ops_program_info, NULL}; - -static ebpf_extension_data_t _ebpf_sock_ops_program_info_provider_data = { - TEST_NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_sock_ops_program_data), &_ebpf_sock_ops_program_data}; +static ebpf_program_data_t _ebpf_sock_ops_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, &_ebpf_sock_ops_program_info, NULL}; // Sample extension. static const void* _sample_ebpf_ext_helper_functions[] = { @@ -674,14 +675,19 @@ static const void* _sample_ebpf_ext_helper_functions[] = { test_sample_helper_t::_sample_ebpf_extension_replace}; static ebpf_helper_function_addresses_t _sample_ebpf_ext_helper_function_address_table = { - EBPF_COUNT_OF(_sample_ebpf_ext_helper_functions), (uint64_t*)_sample_ebpf_ext_helper_functions}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_sample_ebpf_ext_helper_functions), + (uint64_t*)_sample_ebpf_ext_helper_functions}; static const void* _test_global_helper_functions[] = {test_global_helper_t::_sample_get_pid_tgid}; static ebpf_helper_function_addresses_t _test_global_helper_function_address_table = { - EBPF_COUNT_OF(_test_global_helper_functions), (uint64_t*)_test_global_helper_functions}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_test_global_helper_functions), + (uint64_t*)_test_global_helper_functions}; static ebpf_program_data_t _test_ebpf_sample_extension_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, &_sample_ebpf_extension_program_info, &_sample_ebpf_ext_helper_function_address_table, &_test_global_helper_function_address_table, @@ -690,46 +696,40 @@ static ebpf_program_data_t _test_ebpf_sample_extension_program_data = { #define TEST_EBPF_SAMPLE_EXTENSION_NPI_PROVIDER_VERSION 0 -static ebpf_extension_data_t _test_ebpf_sample_extension_program_info_provider_data = { - TEST_EBPF_SAMPLE_EXTENSION_NPI_PROVIDER_VERSION, - sizeof(_test_ebpf_sample_extension_program_data), - &_test_ebpf_sample_extension_program_data}; - typedef class _program_info_provider { public: - _program_info_provider() : provider_data(nullptr), nmr_provider_handle(INVALID_HANDLE_VALUE) + _program_info_provider() : program_data(nullptr), nmr_provider_handle(INVALID_HANDLE_VALUE) { memset(&_program_type, 0, sizeof(_program_type)); } ebpf_result_t - initialize(ebpf_program_type_t program_type, ebpf_extension_data_t* custom_provider_data = nullptr) + initialize(ebpf_program_type_t program_type, ebpf_program_data_t* custom_program_data = nullptr) { this->_program_type = program_type; - if (custom_provider_data != nullptr) { - provider_data = custom_provider_data; + if (custom_program_data != nullptr) { + program_data = custom_program_data; } else if (program_type == EBPF_PROGRAM_TYPE_XDP) { - provider_data = &_mock_xdp_program_info_provider_data; + program_data = &_mock_xdp_program_data; } else if (program_type == EBPF_PROGRAM_TYPE_XDP_TEST) { - provider_data = &_ebpf_xdp_test_program_info_provider_data; + program_data = &_ebpf_xdp_test_program_data; } else if (program_type == EBPF_PROGRAM_TYPE_BIND) { - provider_data = &_ebpf_bind_program_info_provider_data; + program_data = &_ebpf_bind_program_data; } else if (program_type == EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR) { - provider_data = &_ebpf_sock_addr_program_info_provider_data; + program_data = &_ebpf_sock_addr_program_data; } else if (program_type == EBPF_PROGRAM_TYPE_SOCK_OPS) { - provider_data = &_ebpf_sock_ops_program_info_provider_data; + program_data = &_ebpf_sock_ops_program_data; } else if (program_type == EBPF_PROGRAM_TYPE_SAMPLE) { - provider_data = &_test_ebpf_sample_extension_program_info_provider_data; + program_data = &_test_ebpf_sample_extension_program_data; } else { // Unsupported program type. return EBPF_INVALID_ARGUMENT; } - ebpf_program_data_t* program_data = (ebpf_program_data_t*)provider_data->data; - module_id.Guid = program_data->program_info->program_type_descriptor.program_type; - provider_characteristics.ProviderRegistrationInstance.NpiSpecificCharacteristics = provider_data; + module_id.Guid = program_data->program_info->program_type_descriptor->program_type; + provider_characteristics.ProviderRegistrationInstance.NpiSpecificCharacteristics = program_data; NTSTATUS status = NmrRegisterProvider(&provider_characteristics, this, &nmr_provider_handle); return (NT_SUCCESS(status)) ? EBPF_SUCCESS : EBPF_FAILED; @@ -780,8 +780,8 @@ typedef class _program_info_provider }; ebpf_program_type_t _program_type; + const ebpf_program_data_t* program_data; - const ebpf_extension_data_t* provider_data; NPI_MODULEID module_id = { sizeof(NPI_MODULEID), MIT_GUID, @@ -794,7 +794,7 @@ typedef class _program_info_provider (NPI_PROVIDER_DETACH_CLIENT_FN*)provider_detach_client_callback, NULL, { - EBPF_PROGRAM_INFORMATION_PROVIDER_DATA_VERSION, + 0, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_PROGRAM_INFO_EXTENSION_IID, &module_id, diff --git a/tests/libfuzzer/netebpfext_fuzzer/libfuzz_harness.cpp b/tests/libfuzzer/netebpfext_fuzzer/libfuzz_harness.cpp index 1b6ba9a40a..b41dc546b5 100644 --- a/tests/libfuzzer/netebpfext_fuzzer/libfuzz_harness.cpp +++ b/tests/libfuzzer/netebpfext_fuzzer/libfuzz_harness.cpp @@ -80,20 +80,21 @@ FUZZ_EXPORT int __cdecl LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) bpf_prog_type_t prog_type = (bpf_prog_type_t)metadata->prog_type; NET_IFINDEX if_index = 0; - ebpf_extension_data_t npi_specific_characteristics = {.size = sizeof(if_index), .data = &if_index}; + ebpf_extension_data_t npi_specific_characteristics = {.data = &if_index}; test_client_context_t client_context = {}; netebpf_ext_helper_t helper( &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_program, &client_context.base); + npi_specific_characteristics.header.size = sizeof(if_index); + // Look up the context descriptor for the requested program type. std::vector guids = helper.program_info_provider_guids(); for (const auto& guid : guids) { - ebpf_extension_data_t extension_data = helper.get_program_info_provider_data(guid); - auto& program_data = *reinterpret_cast(extension_data.data); - if (prog_type == (bpf_prog_type_t)program_data.program_info->program_type_descriptor.bpf_prog_type) { - client_context.ctx_descriptor = program_data.program_info->program_type_descriptor.context_descriptor; + auto& program_data = *helper.get_program_info_provider_data(guid); + if (prog_type == (bpf_prog_type_t)program_data.program_info->program_type_descriptor->bpf_prog_type) { + client_context.ctx_descriptor = program_data.program_info->program_type_descriptor->context_descriptor; break; } } diff --git a/tests/netebpfext_unit/netebpf_ext_helper.cpp b/tests/netebpfext_unit/netebpf_ext_helper.cpp index f63954f682..2fdc7b431c 100644 --- a/tests/netebpfext_unit/netebpf_ext_helper.cpp +++ b/tests/netebpfext_unit/netebpf_ext_helper.cpp @@ -134,7 +134,7 @@ _netebpf_ext_helper::program_info_provider_guids() return guids; } -ebpf_extension_data_t +ebpf_program_data_t* _netebpf_ext_helper::get_program_info_provider_data(_In_ const GUID& program_info_provider) { auto iter = program_info_providers.find(program_info_provider); @@ -142,7 +142,7 @@ _netebpf_ext_helper::get_program_info_provider_data(_In_ const GUID& program_inf // We might not find the provider if some allocation failed during initialization. REQUIRE(iter != program_info_providers.end()); - return *iter->second->provider_data; + return const_cast(iter->second->program_data); } NTSTATUS @@ -155,8 +155,8 @@ _netebpf_ext_helper::_program_info_client_attach_provider( auto client_binding_context = std::make_unique(); client_binding_context->module_id = *provider_registration_instance->ModuleId; client_binding_context->parent = &helper; - client_binding_context->provider_data = - reinterpret_cast(provider_registration_instance->NpiSpecificCharacteristics); + client_binding_context->program_data = + reinterpret_cast(provider_registration_instance->NpiSpecificCharacteristics); NTSTATUS status = NmrClientAttachProvider( nmr_binding_handle, @@ -199,9 +199,7 @@ _netebpf_ext_helper::_hook_client_attach_provider( } const ebpf_extension_dispatch_table_t client_dispatch_table = { .version = 1, .count = 1, .function = base_client_context->helper->hook_invoke_function}; - auto provider_characteristics = - (const ebpf_extension_data_t*)provider_registration_instance->NpiSpecificCharacteristics; - auto provider_data = (const ebpf_attach_provider_data_t*)provider_characteristics->data; + auto provider_data = (const ebpf_attach_provider_data_t*)provider_registration_instance->NpiSpecificCharacteristics; if (base_client_context->desired_attach_type != BPF_ATTACH_TYPE_UNSPEC && provider_data->bpf_attach_type != base_client_context->desired_attach_type) { return STATUS_ACCESS_DENIED; diff --git a/tests/netebpfext_unit/netebpf_ext_helper.h b/tests/netebpfext_unit/netebpf_ext_helper.h index f2f843f88a..c642350102 100644 --- a/tests/netebpfext_unit/netebpf_ext_helper.h +++ b/tests/netebpfext_unit/netebpf_ext_helper.h @@ -44,7 +44,7 @@ typedef class _netebpf_ext_helper std::vector program_info_provider_guids(); - ebpf_extension_data_t + ebpf_program_data_t* get_program_info_provider_data(_In_ const GUID& program_info_provider); FWP_ACTION_TYPE @@ -111,7 +111,7 @@ typedef class _netebpf_ext_helper NPI_MODULEID module_id; void* context; const void* dispatch; - const ebpf_extension_data_t* provider_data; + const ebpf_program_data_t* program_data; } program_info_provider_t; std::map, NPI_MODULEID_LESS> program_info_providers; diff --git a/tests/netebpfext_unit/netebpfext_unit.cpp b/tests/netebpfext_unit/netebpfext_unit.cpp index e748d112fe..ffc25a1b4c 100644 --- a/tests/netebpfext_unit/netebpfext_unit.cpp +++ b/tests/netebpfext_unit/netebpfext_unit.cpp @@ -64,9 +64,8 @@ TEST_CASE("query program info", "[netebpfext]") // Get the names of the program types. std::vector program_names; for (const auto& guid : guids) { - ebpf_extension_data_t extension_data = helper.get_program_info_provider_data(guid); - auto& program_data = *reinterpret_cast(extension_data.data); - program_names.push_back(program_data.program_info->program_type_descriptor.name); + auto& program_data = *helper.get_program_info_provider_data(guid); + program_names.push_back(program_data.program_info->program_type_descriptor->name); } // Make sure they match. @@ -118,10 +117,12 @@ netebpfext_unit_invoke_xdp_program( TEST_CASE("classify_packet", "[netebpfext]") { NET_IFINDEX if_index = 0; - ebpf_extension_data_t npi_specific_characteristics = {.size = sizeof(if_index), .data = &if_index}; + ebpf_extension_data_t npi_specific_characteristics = {.data = &if_index}; test_xdp_client_context_t client_context = {}; client_context.base.desired_attach_type = BPF_XDP_TEST; + npi_specific_characteristics.header.size = sizeof(if_index); + netebpf_ext_helper_t helper( &npi_specific_characteristics, (_ebpf_extension_dispatch_function)netebpfext_unit_invoke_xdp_program, @@ -151,8 +152,7 @@ TEST_CASE("classify_packet", "[netebpfext]") TEST_CASE("xdp_context", "[netebpfext]") { netebpf_ext_helper_t helper; - auto xdp_extension_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_XDP_TEST); - auto xdp_program_data = (ebpf_program_data_t*)xdp_extension_data.data; + auto xdp_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_XDP_TEST); std::vector input_data(100); std::vector output_data(100); @@ -258,8 +258,7 @@ TEST_CASE("bind_invoke", "[netebpfext]") TEST_CASE("bind_context", "[netebpfext]") { netebpf_ext_helper_t helper; - auto bind_extension_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_BIND); - auto bind_program_data = (ebpf_program_data_t*)bind_extension_data.data; + auto bind_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_BIND); std::vector input_data(100); std::vector output_data(100); @@ -367,9 +366,8 @@ netebpfext_unit_invoke_sock_addr_program( int action = SOCK_ADDR_TEST_ACTION_BLOCK; int32_t is_admin = 0; - ebpf_extension_data_t sock_addr_extension_data = + auto sock_addr_program_data = client_context->base.helper->get_program_info_provider_data(EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR); - auto sock_addr_program_data = (ebpf_program_data_t*)sock_addr_extension_data.data; // Test _ebpf_sock_addr_is_current_admin global helper function. // If the user is not admin, then the default action is to block. @@ -695,8 +693,7 @@ TEST_CASE("sock_addr_invoke_concurrent3", "[netebpfext_concurrent]") TEST_CASE("sock_addr_context", "[netebpfext]") { netebpf_ext_helper_t helper; - auto sock_addr_extension_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR); - auto sock_addr_program_data = (ebpf_program_data_t*)sock_addr_extension_data.data; + auto sock_addr_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR); size_t output_data_size = 0; bpf_sock_addr_t input_context = { @@ -815,8 +812,7 @@ TEST_CASE("sock_ops_invoke", "[netebpfext]") TEST_CASE("sock_ops_context", "[netebpfext]") { netebpf_ext_helper_t helper; - auto sock_ops_extension_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_SOCK_OPS); - auto sock_ops_program_data = (ebpf_program_data_t*)sock_ops_extension_data.data; + auto sock_ops_program_data = helper.get_program_info_provider_data(EBPF_PROGRAM_TYPE_SOCK_OPS); size_t output_data_size = 0; bpf_sock_ops_t input_context = { diff --git a/tools/bpf2c/bpf2c.cpp b/tools/bpf2c/bpf2c.cpp index 1afc40b7f2..ef1c1e7034 100644 --- a/tools/bpf2c/bpf2c.cpp +++ b/tools/bpf2c/bpf2c.cpp @@ -87,11 +87,11 @@ get_program_info_type_hash(const std::vector& actual_helper_ids, const // being hashed in _ebpf_program_verify_program_info_hash. If new fields are added to the program info, then the // hash must be updated to include the new fields, both here and in _ebpf_program_verify_program_info_hash. hash_t::byte_range_t byte_range; - hash_t::append_byte_range(byte_range, program_info->program_type_descriptor.name); - hash_t::append_byte_range(byte_range, *program_info->program_type_descriptor.context_descriptor); - hash_t::append_byte_range(byte_range, program_info->program_type_descriptor.program_type); - hash_t::append_byte_range(byte_range, program_info->program_type_descriptor.bpf_prog_type); - hash_t::append_byte_range(byte_range, program_info->program_type_descriptor.is_privileged); + hash_t::append_byte_range(byte_range, program_info->program_type_descriptor->name); + hash_t::append_byte_range(byte_range, *program_info->program_type_descriptor->context_descriptor); + hash_t::append_byte_range(byte_range, program_info->program_type_descriptor->program_type); + hash_t::append_byte_range(byte_range, program_info->program_type_descriptor->bpf_prog_type); + hash_t::append_byte_range(byte_range, program_info->program_type_descriptor->is_privileged); hash_t::append_byte_range(byte_range, actual_helper_id_count); // First, create a map of helper_id to index in the program_type_specific_helper_prototype array. diff --git a/tools/export_program_info/export_program_info.cpp b/tools/export_program_info/export_program_info.cpp index 4ecb7248d7..811004102b 100644 --- a/tools/export_program_info/export_program_info.cpp +++ b/tools/export_program_info/export_program_info.cpp @@ -16,8 +16,15 @@ #include "ebpf_general_helpers.c" // Export XDP program information to allow for our unit tests to mock the XDP API surface. +static const ebpf_program_type_descriptor_t _mock_xdp_program_type_descriptor = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "xdp", + &_ebpf_xdp_test_context_descriptor, + EBPF_PROGRAM_TYPE_XDP_GUID, + BPF_PROG_TYPE_XDP}; static const ebpf_program_info_t _mock_xdp_program_info = { - {"xdp", &_ebpf_xdp_test_context_descriptor, EBPF_PROGRAM_TYPE_XDP_GUID, BPF_PROG_TYPE_XDP}, + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_mock_xdp_program_type_descriptor, EBPF_COUNT_OF(_xdp_test_ebpf_extension_helper_function_prototype), _xdp_test_ebpf_extension_helper_function_prototype}; @@ -35,7 +42,12 @@ static const ebpf_program_info_t* _program_information_array[] = { &_ebpf_xdp_test_program_info}; ebpf_program_section_info_t _mock_xdp_section_info[] = { - {L"xdp", &EBPF_PROGRAM_TYPE_XDP, &EBPF_ATTACH_TYPE_XDP, BPF_PROG_TYPE_XDP, BPF_XDP}}; + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"xdp", + &EBPF_PROGRAM_TYPE_XDP, + &EBPF_ATTACH_TYPE_XDP, + BPF_PROG_TYPE_XDP, + BPF_XDP}}; static std::vector _section_information = { {&_ebpf_bind_section_info[0], _countof(_ebpf_bind_section_info)}, @@ -51,7 +63,7 @@ export_all_program_information() uint32_t status = ERROR_SUCCESS; size_t array_size = _countof(_program_information_array); for (uint32_t i = 0; i < array_size; i++) { - status = ebpf_store_update_program_information(_program_information_array[i], 1); + status = ebpf_store_update_program_information_array(_program_information_array[i], 1); if (status != ERROR_SUCCESS) { break; } diff --git a/tools/export_program_info/main.cpp b/tools/export_program_info/main.cpp index bb7d0b1be4..50eef348b9 100644 --- a/tools/export_program_info/main.cpp +++ b/tools/export_program_info/main.cpp @@ -33,24 +33,28 @@ main(int argc, char** argv) status = export_all_program_information(); if (status != ERROR_SUCCESS) { std::cout << "Failed export_all_program_information() - ERROR #" << status << std::endl; + return 1; } std::cout << "Exporting section information." << std::endl; status = export_all_section_information(); if (status != ERROR_SUCCESS) { std::cout << "Failed export_all_section_information() - ERROR #" << status << std::endl; + return 1; } std::cout << "Exporting global helper information." << std::endl; status = export_global_helper_information(); if (status != ERROR_SUCCESS) { std::cout << "Failed export_global_helper_information() - ERROR #" << status << std::endl; + return 1; } } else { std::cout << "Clearing eBPF store." << std::endl; status = clear_ebpf_store(); if (status != EBPF_SUCCESS) { std::cout << "Failed clear_ebpf_store() - ERROR #" << status << std::endl; + return 1; } } diff --git a/undocked/tests/sample/ext/drv/sample_ext.c b/undocked/tests/sample/ext/drv/sample_ext.c index 711a24f54b..6f5f8afe70 100644 --- a/undocked/tests/sample/ext/drv/sample_ext.c +++ b/undocked/tests/sample/ext/drv/sample_ext.c @@ -46,12 +46,16 @@ static const void* _sample_ebpf_extension_helpers[] = { (void*)&_sample_ebpf_extension_replace}; static const ebpf_helper_function_addresses_t _sample_ebpf_extension_helper_function_address_table = { - EBPF_COUNT_OF(_sample_ebpf_extension_helpers), (uint64_t*)_sample_ebpf_extension_helpers}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_sample_ebpf_extension_helpers), + (uint64_t*)_sample_ebpf_extension_helpers}; static const void* _sample_global_helpers[] = {(void*)&_sample_get_pid_tgid}; static const ebpf_helper_function_addresses_t _sample_global_helper_function_address_table = { - EBPF_COUNT_OF(_sample_global_helpers), (uint64_t*)_sample_global_helpers}; + {EBPF_HELPER_FUNCTION_ADDRESSES_CURRENT_VERSION, sizeof(ebpf_helper_function_addresses_t)}, + EBPF_COUNT_OF(_sample_global_helpers), + (uint64_t*)_sample_global_helpers}; static ebpf_result_t _sample_context_create( @@ -70,19 +74,15 @@ _sample_context_destroy( _Inout_ size_t* context_size_out); static ebpf_program_data_t _sample_ebpf_extension_program_data = { + {EBPF_PROGRAM_DATA_CURRENT_VERSION, EBPF_PROGRAM_DATA_CURRENT_VERSION_SIZE}, .program_info = &_sample_ebpf_extension_program_info, .program_type_specific_helper_function_addresses = &_sample_ebpf_extension_helper_function_address_table, .global_helper_function_addresses = &_sample_global_helper_function_address_table, .context_create = &_sample_context_create, .context_destroy = &_sample_context_destroy}; -static const ebpf_extension_data_t _sample_ebpf_extension_program_info_provider_data = { - SAMPLE_EBPF_EXTENSION_NPI_PROVIDER_VERSION, - sizeof(_sample_ebpf_extension_program_data), - &_sample_ebpf_extension_program_data}; - NPI_MODULEID DECLSPEC_SELECTANY _sample_ebpf_extension_program_info_provider_moduleid = { - sizeof(NPI_MODULEID), MIT_GUID, {0}}; + sizeof(NPI_MODULEID), MIT_GUID, EBPF_PROGRAM_TYPE_SAMPLE_GUID}; /** * @brief Callback invoked when an eBPF Program Information NPI client attaches. @@ -140,7 +140,7 @@ const NPI_PROVIDER_CHARACTERISTICS _sample_ebpf_extension_program_info_provider_ &EBPF_PROGRAM_INFO_EXTENSION_IID, &_sample_ebpf_extension_program_info_provider_moduleid, 0, - &_sample_ebpf_extension_program_info_provider_data}, + &_sample_ebpf_extension_program_data}, }; /** @@ -164,7 +164,8 @@ static sample_ebpf_extension_program_info_provider_t _sample_ebpf_extension_prog // Hook Provider. // -NPI_MODULEID DECLSPEC_SELECTANY _sample_ebpf_extension_hook_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; +NPI_MODULEID DECLSPEC_SELECTANY _sample_ebpf_extension_hook_provider_moduleid = { + sizeof(NPI_MODULEID), MIT_GUID, EBPF_ATTACH_TYPE_SAMPLE_GUID}; /** * @brief Callback invoked when a eBPF hook NPI client attaches. @@ -210,12 +211,11 @@ static void _sample_ebpf_extension_hook_provider_cleanup_binding_context(_Frees_ptr_ void* provider_binding_context); // Sample eBPF extension Hook NPI provider characteristics -ebpf_attach_provider_data_t _sample_ebpf_extension_attach_provider_data; - -ebpf_extension_data_t _sample_ebpf_extension_hook_provider_data = { - EBPF_ATTACH_PROVIDER_DATA_VERSION, - sizeof(_sample_ebpf_extension_attach_provider_data), - &_sample_ebpf_extension_attach_provider_data}; +ebpf_attach_provider_data_t _sample_ebpf_extension_attach_provider_data = { + {EBPF_ATTACH_PROVIDER_DATA_CURRENT_VERSION, sizeof(ebpf_attach_provider_data_t)}, + EBPF_PROGRAM_TYPE_SAMPLE_GUID, + BPF_ATTACH_TYPE_SAMPLE, + BPF_LINK_TYPE_UNSPEC}; const NPI_PROVIDER_CHARACTERISTICS _sample_ebpf_extension_hook_provider_characteristics = { 0, @@ -228,7 +228,7 @@ const NPI_PROVIDER_CHARACTERISTICS _sample_ebpf_extension_hook_provider_characte &EBPF_HOOK_EXTENSION_IID, &_sample_ebpf_extension_hook_provider_moduleid, 0, - &_sample_ebpf_extension_hook_provider_data}, + &_sample_ebpf_extension_attach_provider_data}, }; typedef struct _sample_ebpf_extension_hook_provider sample_ebpf_extension_hook_provider_t; @@ -338,16 +338,8 @@ NTSTATUS sample_ebpf_extension_program_info_provider_register() { sample_ebpf_extension_program_info_provider_t* local_provider_context; - ebpf_extension_data_t* extension_data; - ebpf_program_data_t* program_data; - NTSTATUS status = STATUS_SUCCESS; - extension_data = (ebpf_extension_data_t*)_sample_ebpf_extension_program_info_provider_characteristics - .ProviderRegistrationInstance.NpiSpecificCharacteristics; - program_data = (ebpf_program_data_t*)extension_data->data; - _sample_ebpf_extension_program_info_provider_moduleid.Guid = EBPF_PROGRAM_TYPE_SAMPLE; - local_provider_context = &_sample_ebpf_extension_program_info_provider_context; status = NmrRegisterProvider( @@ -487,10 +479,6 @@ sample_ebpf_extension_hook_provider_register() sample_ebpf_extension_hook_provider_t* local_provider_context; NTSTATUS status = STATUS_SUCCESS; - _sample_ebpf_extension_attach_provider_data.supported_program_type = EBPF_PROGRAM_TYPE_SAMPLE; - _sample_ebpf_extension_attach_provider_data.bpf_attach_type = BPF_ATTACH_TYPE_SAMPLE; - _sample_ebpf_extension_hook_provider_moduleid.Guid = EBPF_ATTACH_TYPE_SAMPLE; - local_provider_context = &_sample_ebpf_extension_hook_provider_context; status = NmrRegisterProvider( diff --git a/undocked/tests/sample/ext/inc/sample_ext_program_info.h b/undocked/tests/sample/ext/inc/sample_ext_program_info.h index 556af60d9d..747cf735a8 100644 --- a/undocked/tests/sample/ext/inc/sample_ext_program_info.h +++ b/undocked/tests/sample/ext/inc/sample_ext_program_info.h @@ -15,6 +15,8 @@ #define EBPF_COUNT_OF(arr) (sizeof(arr) / sizeof(arr[0])) #define EBPF_OFFSET_OF(s, m) (((size_t) & ((s*)0)->m)) +#define EBPF_FIELD_SIZE(s, m) (sizeof(((s*)0)->m)) +#define EBPF_SIZE_INCLUDING_FIELD(s, m) (EBPF_OFFSET_OF(s, m) + EBPF_FIELD_SIZE(s, m)) static const ebpf_context_descriptor_t _sample_ebpf_context_descriptor = { sizeof(sample_program_context_t), @@ -24,18 +26,21 @@ static const ebpf_context_descriptor_t _sample_ebpf_context_descriptor = { // Sample Extension Helper function prototype descriptors. static const ebpf_helper_function_prototype_t _sample_ebpf_extension_helper_function_prototype[] = { - {SAMPLE_EXT_HELPER_FUNCTION_START + 1, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + SAMPLE_EXT_HELPER_FUNCTION_START + 1, "sample_ebpf_extension_helper_function1", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, - {SAMPLE_EXT_HELPER_FUNCTION_START + 2, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + SAMPLE_EXT_HELPER_FUNCTION_START + 2, "sample_ebpf_extension_find", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE, EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE}}, - {SAMPLE_EXT_HELPER_FUNCTION_START + 3, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + SAMPLE_EXT_HELPER_FUNCTION_START + 3, "sample_ebpf_extension_replace", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, @@ -46,10 +51,21 @@ static const ebpf_helper_function_prototype_t _sample_ebpf_extension_helper_func // Global helper function prototype descriptors. static const ebpf_helper_function_prototype_t _sample_ebpf_extension_global_helper_function_prototype[] = { - {BPF_FUNC_get_current_pid_tgid, "bpf_get_current_pid_tgid", EBPF_RETURN_TYPE_INTEGER, {0}}}; + {{EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION, EBPF_HELPER_FUNCTION_PROTOTYPE_CURRENT_VERSION_SIZE}, + BPF_FUNC_get_current_pid_tgid, + "bpf_get_current_pid_tgid", + EBPF_RETURN_TYPE_INTEGER, + {0}}}; +static const ebpf_program_type_descriptor_t _sample_ebpf_extension_program_type_descriptor = { + {EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION, EBPF_PROGRAM_TYPE_DESCRIPTOR_CURRENT_VERSION_SIZE}, + "sample", + &_sample_ebpf_context_descriptor, + EBPF_PROGRAM_TYPE_SAMPLE_GUID, + BPF_PROG_TYPE_SAMPLE}; static const ebpf_program_info_t _sample_ebpf_extension_program_info = { - {"sample", &_sample_ebpf_context_descriptor, EBPF_PROGRAM_TYPE_SAMPLE_GUID, BPF_PROG_TYPE_SAMPLE}, + {EBPF_PROGRAM_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_INFORMATION_CURRENT_VERSION_SIZE}, + &_sample_ebpf_extension_program_type_descriptor, EBPF_COUNT_OF(_sample_ebpf_extension_helper_function_prototype), _sample_ebpf_extension_helper_function_prototype, EBPF_COUNT_OF(_sample_ebpf_extension_global_helper_function_prototype), diff --git a/undocked/tools/export_program_info_sample/export_program_info_sample.cpp b/undocked/tools/export_program_info_sample/export_program_info_sample.cpp index bccd414b9d..ff2da23270 100644 --- a/undocked/tools/export_program_info_sample/export_program_info_sample.cpp +++ b/undocked/tools/export_program_info_sample/export_program_info_sample.cpp @@ -25,7 +25,12 @@ typedef struct _ebpf_program_section_info_with_count static const ebpf_program_info_t* _program_information_array[] = {&_sample_ebpf_extension_program_info}; ebpf_program_section_info_t _sample_ext_section_info[] = { - {L"sample_ext", &EBPF_PROGRAM_TYPE_SAMPLE, &EBPF_ATTACH_TYPE_SAMPLE, BPF_PROG_TYPE_SAMPLE, BPF_ATTACH_TYPE_SAMPLE}}; + {{EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION, EBPF_PROGRAM_SECTION_INFORMATION_CURRENT_VERSION_SIZE}, + L"sample_ext", + &EBPF_PROGRAM_TYPE_SAMPLE, + &EBPF_ATTACH_TYPE_SAMPLE, + BPF_PROG_TYPE_SAMPLE, + BPF_ATTACH_TYPE_SAMPLE}}; static std::vector _section_information = { {&_sample_ext_section_info[0], _countof(_sample_ext_section_info)}, @@ -37,7 +42,7 @@ export_program_information() uint32_t status = ERROR_SUCCESS; size_t array_size = _countof(_program_information_array); for (uint32_t i = 0; i < array_size; i++) { - status = ebpf_store_update_program_information(_program_information_array[i], 1); + status = ebpf_store_update_program_information_array(_program_information_array[i], 1); if (status != ERROR_SUCCESS) { break; }