diff --git a/docs/eBpfExtensions.md b/docs/eBpfExtensions.md index 567232c239..073ca13245 100644 --- a/docs/eBpfExtensions.md +++ b/docs/eBpfExtensions.md @@ -62,8 +62,14 @@ 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. + #### `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 +83,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 +102,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 +133,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 +199,14 @@ 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. New fields can be added to the end of a data structure to maintain backward compatibility +with the existing extensions. In such cases, the size field of the header will be updated but the version of the structure *will not change*. +If the change in data structure is such that it is no longer backward compatible (such as change field type or position), +then the version number will be updated. All previous versions of extension structure will continue to be supported. +The set of supported version numbers for the various extension structures are listed in `ebpf_windows.h`. + +### 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 +215,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 +237,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 +263,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 +347,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 +373,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`. @@ -381,7 +398,7 @@ To operate on the eBPF store, the user mode application needs to link with eBPFA _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/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..744fc602ad 100644 --- a/include/ebpf_program_types.h +++ b/include/ebpf_program_types.h @@ -4,22 +4,15 @@ #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 typedef struct _ebpf_program_type_descriptor { + ebpf_extension_header_t header; + // The following fields are available in version EBPF_PROGRAM_TYPE_DESCRIPTOR_VERSION_0 and later. const char* name; const ebpf_context_descriptor_t* context_descriptor; GUID program_type; @@ -29,6 +22,8 @@ typedef struct _ebpf_program_type_descriptor typedef struct _ebpf_helper_function_prototype { + ebpf_extension_header_t header; + // The following fields are available in version EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0 and later. uint32_t helper_id; const char* name; ebpf_return_type_t return_type; @@ -37,7 +32,8 @@ typedef struct _ebpf_helper_function_prototype 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; @@ -46,6 +42,7 @@ typedef struct _ebpf_program_info 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; @@ -66,6 +63,7 @@ typedef void (*ebpf_program_context_destroy_t)( 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 @@ -79,6 +77,7 @@ typedef struct _ebpf_program_data 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_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..27162404f5 100644 --- a/include/ebpf_windows.h +++ b/include/ebpf_windows.h @@ -5,16 +5,24 @@ #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" @@ -49,3 +57,30 @@ 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 0 of the eBPF extension data structures. +#define EBPF_ATTACH_CLIENT_DATA_VERSION_0 0 +#define EBPF_ATTACH_PROVIDER_DATA_VERSION_0 0 +#define EBPF_PROGRAM_INFORMATION_CLIENT_DATA_VERSION_0 0 +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_VERSION_0 0 +#define EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0 0 +#define EBPF_PROGRAM_INFORMATION_VERSION_0 0 +#define EBPF_HELPER_FUNCTION_ADDRESSES_VERSION_0 0 +#define EBPF_PROGRAM_SECTION_INFORMATION_VERSION_0 0 +#define EBPF_PROGRAM_DATA_VERSION_0 0 +#define EBPF_PROGRAM_SECTION_VERSION_0 0 + +/** + * @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 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..e568f53f96 100644 --- a/libs/api_common/store_helper_internal.cpp +++ b/libs/api_common/store_helper_internal.cpp @@ -100,6 +100,7 @@ _load_program_data_information( 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; @@ -174,16 +175,25 @@ _load_program_data_information( goto Exit; } - program_information->program_type_descriptor.name = cxplat_duplicate_string(program_type_name_string.c_str()); - if (program_information->program_type_descriptor.name == nullptr) { + program_information->program_type_descriptor = + (ebpf_program_type_descriptor_t*)ebpf_allocate(sizeof(ebpf_program_type_descriptor_t)); + if (program_information->program_type_descriptor == nullptr) { result = EBPF_NO_MEMORY; goto Exit; } - program_information->program_type_descriptor.context_descriptor = descriptor; + program_type_descriptor = + const_cast(program_information->program_type_descriptor); + + program_type_descriptor->name = cxplat_duplicate_string(program_type_name_string.c_str()); + if (program_type_descriptor->name == nullptr) { + result = EBPF_NO_MEMORY; + goto Exit; + } + 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; + program_type_descriptor->is_privileged = !!is_privileged; + program_type_descriptor->bpf_prog_type = bpf_program_type; + program_type_descriptor->program_type = *program_type; if (helper_count > 0) { // Read the helper functions prototypes. 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..67180c904b 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; } } @@ -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..71410805de 100644 --- a/libs/execution_context/ebpf_core.c +++ b/libs/execution_context/ebpf_core.c @@ -101,7 +101,15 @@ _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_VERSION_0, sizeof(ebpf_program_type_descriptor_t), "global_helper", NULL, {0}, 0, 0}; +static ebpf_program_info_t _ebpf_global_helper_program_info = { + {EBPF_PROGRAM_INFORMATION_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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 +145,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_VERSION_0, 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_VERSION_0, sizeof(ebpf_program_data_t)}, + &_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 +163,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_VERSION_0, 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..529b746854 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + BPF_FUNC_get_prandom_u32, + "bpf_get_prandom_u32", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + BPF_FUNC_ktime_get_boot_ns, + "bpf_ktime_get_boot_ns", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + BPF_FUNC_get_smp_processor_id, + "bpf_get_smp_processor_id", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + BPF_FUNC_ktime_get_ns, + "bpf_ktime_get_ns", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + BPF_FUNC_trace_printk5, "bpf_trace_printk5", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, @@ -76,25 +103,33 @@ 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + BPF_FUNC_get_current_pid_tgid, + "bpf_get_current_pid_tgid", + EBPF_RETURN_TYPE_INTEGER, + {0}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, BPF_FUNC_is_current_admin, "bpf_is_current_admin", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_CTX}}, + {{EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, BPF_FUNC_memcpy, "bpf_memcpy", EBPF_RETURN_TYPE_INTEGER, { @@ -103,7 +138,7 @@ 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, BPF_FUNC_memcmp, "bpf_memcmp", EBPF_RETURN_TYPE_INTEGER, { @@ -112,11 +147,11 @@ 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, 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 3dd78d5dcf..93ef65c452 100644 --- a/libs/execution_context/ebpf_link.c +++ b/libs/execution_context/ebpf_link.c @@ -32,6 +32,10 @@ typedef enum _ebpf_link_state EBPF_LINK_STATE_DETACHED, ///< Program is detached from a provider. } ebpf_link_state_t; +// Latest version of the eBPF extension attach/hook data structures. +#define EBPF_ATTACH_CLIENT_DATA_VERSION EBPF_ATTACH_CLIENT_DATA_VERSION_0 +#define EBPF_ATTACH_PROVIDER_DATA_VERSION EBPF_ATTACH_PROVIDER_DATA_VERSION_0 + typedef struct _ebpf_link { ebpf_core_object_t object; @@ -59,7 +63,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_VERSION, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_HOOK_EXTENSION_IID, NULL, @@ -121,8 +125,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 +136,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_VERSION_0 || + 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 +254,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); @@ -434,7 +436,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: @@ -569,8 +571,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 d7683eb4ac..fc2933f6b1 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_VERSION_0, 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_VERSION_0, sizeof(NPI_REGISTRATION_INSTANCE), &EBPF_PROGRAM_INFO_EXTENSION_IID, NULL, @@ -182,61 +183,153 @@ _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; + } + + // Verify that that the program information version is supported. + if (program_data->header.version > EBPF_PROGRAM_DATA_VERSION_LATEST || + program_data->header.size < sizeof(ebpf_program_data_t)) { + EBPF_LOG_MESSAGE( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "Program information provider version not supported."); + goto Done; + } + + if (program_data->header.size < EBPF_PROGRAM_DATA_MINIMUM_SIZE) { + EBPF_LOG_MESSAGE_GUID( + EBPF_TRACELOG_LEVEL_ERROR, + EBPF_TRACELOG_KEYWORD_PROGRAM, + "Program information provider data size too small.", + &npi_module_id->Guid); + goto Done; + } + + if (!is_general_helper_program_data) { + 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 +338,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 +362,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 +379,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 +390,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 +404,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 +459,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 +471,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 +480,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 +496,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 +513,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 +535,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 +560,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 +817,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 +1102,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 +1121,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 +1401,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 +1463,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 +1483,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 +1602,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 +1627,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 +1657,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 +1687,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 +1700,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 +1748,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 +1768,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 +1779,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 +2014,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 +2023,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 +2100,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 +2188,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 +2343,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 +2358,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..2466df543a 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_VERSION_0, 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..65382d0767 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_VERSION_0, 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_VERSION_0, 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "unit_test_program", + &context_descriptor, + program_type_test}; + ebpf_program_info_t in_program_info = { + {EBPF_PROGRAM_INFORMATION_VERSION_0, sizeof(ebpf_program_info_t)}, + &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..d77f38766d 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" @@ -24,6 +25,25 @@ CXPLAT_EXTERN_C_BEGIN #define EBPF_SYMBOLIC_DEVICE_NAME L"\\GLOBAL??\\EbpfIoDevice" #define EBPF_DEVICE_WIN32_NAME L"\\\\.\\EbpfIoDevice" +// Latest version of the eBPF extension program information data structures. +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_VERSION_LATEST EBPF_PROGRAM_TYPE_DESCRIPTOR_VERSION_0 +#define EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_LATEST EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_0 +#define EBPF_PROGRAM_INFORMATION_VERSION_LATEST EBPF_PROGRAM_INFORMATION_VERSION_0 +#define EBPF_HELPER_FUNCTION_ADDRESSES_VERSION_LATEST EBPF_HELPER_FUNCTION_ADDRESSES_VERSION_0 +#define EBPF_PROGRAM_DATA_VERSION_LATEST EBPF_PROGRAM_DATA_VERSION_0 +#define EBPF_PROGRAM_SECTION_VERSION_LATEST EBPF_PROGRAM_SECTION_VERSION_0 + +// Minumum length of the eBPF extension program information data structures. +#define EBPF_PROGRAM_DATA_MINIMUM_SIZE (EBPF_OFFSET_OF(ebpf_program_data_t, required_irql) + sizeof(uint8_t)) +#define EBPF_PROGRAM_INFO_MINIMUM_SIZE \ + (EBPF_OFFSET_OF(ebpf_program_info_t, global_helper_prototype) + sizeof(ebpf_helper_function_prototype_t*)) +#define EBPF_PROGRAM_TYPE_DESCRIPTOR_MINIMUM_SIZE \ + (EBPF_OFFSET_OF(ebpf_program_type_descriptor_t, is_privileged) + sizeof(char)) +#define EBPF_CONTEXT_DESCRIPTOR_MINIMUM_SIZE \ + (EBPF_OFFSET_OF(ebpf_context_descriptor_t, context_destroy) + sizeof(ebpf_program_context_destroy_t)) +#define EBPF_HELPER_FUNCTION_PROTOTYPE_MINIMUM_SIZE \ + (EBPF_OFFSET_OF(ebpf_helper_function_prototype_t, arguments) + 5 * sizeof(ebpf_argument_type_t)) + // Macro locally suppresses "Unreferenced variable" warning, which in 'Release' builds is treated as an error. #define ebpf_assert_success(x) \ _Pragma("warning(push)") _Pragma("warning(disable : 4189)") do \ @@ -92,4 +112,14 @@ __forceinline __drv_allocatesMem(Mem) _Must_inspect_result_ ebpf_result_t ebpf_result_from_cxplat_status(cxplat_status_t status); +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..d0c102a634 100644 --- a/libs/shared/shared_common.c +++ b/libs/shared/shared_common.c @@ -1,8 +1,72 @@ // Copyright (c) Microsoft Corporation // SPDX-License-Identifier: MIT +#include "ebpf_program_types.h" #include "ebpf_shared_framework.h" +static bool +_ebpf_validate_helper_function_prototype(const ebpf_helper_function_prototype_t* helper_prototype) +{ + return ( + (helper_prototype != NULL) && (helper_prototype->header.size >= EBPF_HELPER_FUNCTION_PROTOTYPE_MINIMUM_SIZE) && + (helper_prototype->header.version <= EBPF_HELPER_FUNCTION_PROTOTYPE_VERSION_LATEST) && + (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) && + (program_type_descriptor->header.size >= EBPF_PROGRAM_TYPE_DESCRIPTOR_MINIMUM_SIZE) && + (program_type_descriptor->header.version <= EBPF_PROGRAM_TYPE_DESCRIPTOR_VERSION_LATEST) && + (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) && (program_info->header.size >= EBPF_PROGRAM_INFO_MINIMUM_SIZE) && + (program_info->header.version <= EBPF_PROGRAM_INFORMATION_VERSION_LATEST) && + _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_section_info(_In_ const ebpf_program_section_info_t* section_info) +{ + return ( + (section_info != NULL) && (section_info->header.size >= sizeof(ebpf_program_section_info_t)) && + (section_info->header.version <= EBPF_PROGRAM_SECTION_VERSION_LATEST) && (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..4f3bd81229 100644 --- a/libs/store_helper/ebpf_store_helper.c +++ b/libs/store_helper/ebpf_store_helper.c @@ -3,6 +3,7 @@ #include "ebpf_program_types.h" #include "ebpf_registry_helper.h" +#include "ebpf_shared_framework.h" #include "ebpf_store_helper.h" #include "ebpf_windows.h" @@ -89,6 +90,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)) { @@ -103,7 +109,6 @@ ebpf_store_update_global_helper_information( } 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; @@ -144,6 +149,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); @@ -228,10 +238,15 @@ ebpf_store_update_program_information( ebpf_store_key_t program_key = {0}; ebpf_store_key_t helper_info_key = {0}; + if (!ebpf_validate_program_info(&program_info[i])) { + result = EBPF_INVALID_ARGUMENT; + goto Exit; + } + // 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); + &program_info[i].program_type_descriptor->program_type, guid_string, GUID_STRING_LENGTH + 1); if (!IS_SUCCESS(result)) { return result; } @@ -242,7 +257,7 @@ ebpf_store_update_program_information( } // Save the friendly program type name. - wchar_t* wide_program_name = ebpf_get_wstring_from_string(program_info[i].program_type_descriptor.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; @@ -259,7 +274,7 @@ ebpf_store_update_program_information( result = ebpf_write_registry_value_binary( program_key, EBPF_PROGRAM_DATA_CONTEXT_DESCRIPTOR, - (uint8_t*)program_info[i].program_type_descriptor.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); @@ -268,7 +283,7 @@ ebpf_store_update_program_information( // 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); + program_key, EBPF_DATA_BPF_PROG_TYPE, program_info[i].program_type_descriptor->bpf_prog_type); if (!IS_SUCCESS(result)) { ebpf_close_registry_key(program_key); goto Exit; @@ -276,7 +291,7 @@ ebpf_store_update_program_information( // Save "is_privileged". result = ebpf_write_registry_value_dword( - program_key, EBPF_PROGRAM_DATA_PRIVILEGED, program_info[i].program_type_descriptor.is_privileged); + program_key, EBPF_PROGRAM_DATA_PRIVILEGED, program_info[i].program_type_descriptor->is_privileged); if (!IS_SUCCESS(result)) { ebpf_close_registry_key(program_key); goto Exit; @@ -344,7 +359,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; } 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..2f4c580783 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_VERSION_0, sizeof(ebpf_program_data_t)}, .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_VERSION_0, 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..66b7d9e366 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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..e626ad7410 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_VERSION_0, 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_VERSION_0, 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_VERSION_0, sizeof(ebpf_program_data_t)}, .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_VERSION_0; + _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..d51ba94df1 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_VERSION_0, sizeof(ebpf_program_data_t)}, .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_VERSION_0, 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..785392ec70 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_VERSION_0, 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_VERSION_0, sizeof(ebpf_program_data_t)}, .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_VERSION_0, 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 5b8d1d863f..6dc42d7318 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..25949a6c7a 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_VERSION_0, 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..fc6a05a02b 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_VERSION_0; + 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_VERSION_0, 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_VERSION_0, + sizeof(ebpf_program_type_descriptor_t), + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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_VERSION_0, sizeof(ebpf_program_data_t)}, &_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_VERSION_0, sizeof(ebpf_program_data_t)}, &_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_VERSION_0, sizeof(ebpf_program_data_t)}, &_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_VERSION_0, sizeof(ebpf_program_data_t)}, &_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_VERSION_0, sizeof(ebpf_program_data_t)}, &_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_VERSION_0, 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_VERSION_0, 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_VERSION_0, sizeof(ebpf_program_data_t)}, &_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..f0a1e3ba85 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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)}, diff --git a/undocked/tests/sample/ext/drv/sample_ext.c b/undocked/tests/sample/ext/drv/sample_ext.c index 711a24f54b..2944b3e0dc 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_VERSION_0, 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_VERSION_0, 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_VERSION_0, sizeof(ebpf_program_data_t)}, .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_VERSION_0, 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..e9a85f02b8 100644 --- a/undocked/tests/sample/ext/inc/sample_ext_program_info.h +++ b/undocked/tests/sample/ext/inc/sample_ext_program_info.h @@ -24,18 +24,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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + SAMPLE_EXT_HELPER_FUNCTION_START + 3, "sample_ebpf_extension_replace", EBPF_RETURN_TYPE_INTEGER, {EBPF_ARGUMENT_TYPE_PTR_TO_READABLE_MEM, @@ -46,10 +49,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_VERSION_0, sizeof(ebpf_helper_function_prototype_t)}, + 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_VERSION_0, sizeof(ebpf_program_type_descriptor_t)}, + "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_VERSION_0, sizeof(ebpf_program_info_t)}, + &_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..7f94475c72 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_VERSION_0, sizeof(ebpf_program_section_info_t)}, + 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)},