* remove dependabot from the fork.

* Revert "remove dependabot from the fork."

This reverts commit c542c6cd44.

* Program info and hook NPI providers for sock_addr.

* fix analysis break.

* PR Feedback.

* PR Feedback 2.
This commit is contained in:
Shankar Seal 2022-04-05 16:37:34 -07:00 коммит произвёл GitHub
Родитель 68a740223c
Коммит 04582d3f50
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
10 изменённых файлов: 537 добавлений и 50 удалений

Просмотреть файл

@ -33,7 +33,8 @@ extern "C"
/** @brief The programs attached to the INETx_CONNECT hook will be invoked for
* connect() calls on TCP or UDP sockets or when a UDP socket calls sendto() to
* a unique remote address/port tuple. May be scoped to a network compartment.
* a unique remote address/port tuple. May be scoped to a network compartment. The programs return 1 to permit a
* connection, and 0 to block it.
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT = {
0xa82e37b1, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}};
@ -43,7 +44,8 @@ extern "C"
/** @brief The programs attached to the INETx_RECV_ACCEPT hook will get invoked for
* TCP accept() calls or for the first unicast UDP packet from a unique remote
* address/port tuple. May be scoped to a network compartment.
* address/port tuple. May be scoped to a network compartment. The programs return 1 to permit a connection, and
* 0 to block it.
*/
__declspec(selectany) ebpf_attach_type_t EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT = {
0xa82e37b3, 0xaee7, 0x11ec, {0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee}};

Просмотреть файл

@ -19,6 +19,7 @@ Environment:
#include "net_ebpf_ext.h"
#include "net_ebpf_ext_bind.h"
#include "net_ebpf_ext_sock_addr.h"
#include "net_ebpf_ext_xdp.h"
// Globals.
@ -106,6 +107,46 @@ static net_ebpf_ext_wfp_callout_state_t _net_ebpf_ext_wfp_callout_state[] = {
L"Resource Release eBPF Callout v6",
L"Resource Release callout for eBPF",
FWP_ACTION_CALLOUT_TERMINATING,
},
{
&EBPF_HOOK_ALE_AUTH_CONNECT_V4_CALLOUT,
&FWPM_LAYER_ALE_AUTH_CONNECT_V4,
net_ebpf_ext_authorize_connection_classify,
_net_ebpf_ext_filter_change_notify,
_net_ebpf_ext_flow_delete,
L"ALE Authorize Connect eBPF Callout v4",
L"ALE Authorize Connect callout for eBPF",
FWP_ACTION_CALLOUT_TERMINATING,
},
{
&EBPF_HOOK_ALE_AUTH_CONNECT_V6_CALLOUT,
&FWPM_LAYER_ALE_AUTH_CONNECT_V6,
net_ebpf_ext_authorize_connection_classify,
_net_ebpf_ext_filter_change_notify,
_net_ebpf_ext_flow_delete,
L"ALE Authorize Connect eBPF Callout v6",
L"ALE Authorize Connect callout for eBPF",
FWP_ACTION_CALLOUT_TERMINATING,
},
{
&EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V4_CALLOUT,
&FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
net_ebpf_ext_authorize_connection_classify,
_net_ebpf_ext_filter_change_notify,
_net_ebpf_ext_flow_delete,
L"ALE Authorize Receive or Accept eBPF Callout v4",
L"ALE Authorize Receive or Accept callout for eBPF",
FWP_ACTION_CALLOUT_TERMINATING,
},
{
&EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V6_CALLOUT,
&FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
net_ebpf_ext_authorize_connection_classify,
_net_ebpf_ext_filter_change_notify,
_net_ebpf_ext_flow_delete,
L"ALE Authorize Receive or Accept eBPF Callout v6",
L"ALE Authorize Receive or Accept callout for eBPF",
FWP_ACTION_CALLOUT_TERMINATING,
}};
// WFP globals
@ -456,6 +497,10 @@ net_ebpf_ext_register_providers()
if (status != STATUS_SUCCESS)
goto Exit;
status = net_ebpf_ext_sock_addr_register_providers();
if (status != STATUS_SUCCESS)
goto Exit;
Exit:
return status;
}
@ -465,4 +510,5 @@ net_ebpf_ext_unregister_providers()
{
net_ebpf_ext_xdp_unregister_providers();
net_ebpf_ext_bind_unregister_providers();
net_ebpf_ext_sock_addr_unregister_providers();
}

Просмотреть файл

@ -11,7 +11,7 @@
#include "net_ebpf_ext_bind.h"
//
// WFP bind layer filter related globals.
// WFP filter related globals for bind hook.
//
const net_ebpf_extension_wfp_filter_parameters_t _net_ebpf_extension_bind_wfp_filter_parameters[] = {
@ -65,12 +65,15 @@ static net_ebpf_extension_hook_provider_t* _ebpf_bind_hook_provider_context = NU
//
static ebpf_result_t
_net_ebpf_extension_bind_on_client_attach(_In_ const net_ebpf_extension_hook_client_t* attaching_client)
_net_ebpf_extension_bind_on_client_attach(
_In_ const net_ebpf_extension_hook_client_t* attaching_client,
_In_ const net_ebpf_extension_hook_provider_t* provider_context)
{
ebpf_result_t result = EBPF_SUCCESS;
// Bind hook allows only one client at a time.
if (net_ebpf_extension_hook_get_next_attached_client(_ebpf_bind_hook_provider_context, NULL) != NULL) {
if (net_ebpf_extension_hook_get_next_attached_client((net_ebpf_extension_hook_provider_t*)provider_context, NULL) !=
NULL) {
result = EBPF_ACCESS_DENIED;
goto Exit;
}
@ -128,6 +131,7 @@ net_ebpf_ext_bind_register_providers()
&hook_provider_parameters,
_net_ebpf_extension_bind_on_client_attach,
_net_ebpf_extension_bind_on_client_detach,
NULL,
&_ebpf_bind_hook_provider_context);
if (status != EBPF_SUCCESS) {
goto Exit;

Просмотреть файл

@ -60,9 +60,10 @@ typedef struct _net_ebpf_extension_hook_provider
net_ebpf_extension_hook_execution_t execution_type; ///< Hook execution type (PASSIVE or DISPATCH).
EX_PUSH_LOCK lock; ///< Lock for synchronization.
net_ebpf_extension_hook_on_client_attach attach_callback; /*!< Pointer to hook specific callback to be invoked
when a client attaches. */
when a client attaches. */
net_ebpf_extension_hook_on_client_detach detach_callback; /*!< Pointer to hook specific callback to be invoked
when a client detaches. */
when a client detaches. */
const void* custom_data; ///< Opaque pointer to hook specific data associated for this provider.
_Guarded_by_(lock)
LIST_ENTRY attached_clients_list; ///< Linked list of hook NPI clients that are attached to this provider.
} net_ebpf_extension_hook_provider_t;
@ -219,6 +220,12 @@ net_ebpf_extension_hook_client_get_provider_data(_In_ const net_ebpf_extension_h
return hook_client->provider_data;
}
const void*
net_ebpf_extension_hook_provider_get_custom_data(_In_ const net_ebpf_extension_hook_provider_t* provider_context)
{
return provider_context->custom_data;
}
ebpf_result_t
net_ebpf_extension_hook_invoke_program(
_In_ const net_ebpf_extension_hook_client_t* client, _In_ void* context, _Out_ uint32_t* result)
@ -229,6 +236,58 @@ net_ebpf_extension_hook_invoke_program(
return invoke_program(client_binding_context, context, result);
}
ebpf_result_t
net_ebpf_extension_hook_check_attach_parameter(
size_t attach_parameter_size,
_In_reads_(attach_parameter_size) const void* attach_parameter,
_In_reads_(attach_parameter_size) const void* wild_card_attach_parameter,
_In_ net_ebpf_extension_hook_provider_t* provider_context)
{
ebpf_result_t result = EBPF_SUCCESS;
bool using_wild_card_attach_parameter = FALSE;
bool lock_held = FALSE;
if (memcmp(attach_parameter, wild_card_attach_parameter, attach_parameter_size) == 0)
using_wild_card_attach_parameter = TRUE;
ExAcquirePushLockShared(&provider_context->lock);
lock_held = TRUE;
if (using_wild_card_attach_parameter) {
// Client requested wild card attach parameter. This will only be allowed if there are no other clients
// attached.
if (!IsListEmpty(&provider_context->attached_clients_list)) {
result = EBPF_ACCESS_DENIED;
goto Exit;
}
} else {
// Ensure there are no other clients with wild card attach parameter or with the same attach parameter as the
// requesting client.
LIST_ENTRY* link = provider_context->attached_clients_list.Flink;
while (link != &provider_context->attached_clients_list) {
net_ebpf_extension_hook_client_t* next_client =
(net_ebpf_extension_hook_client_t*)CONTAINING_RECORD(link, net_ebpf_extension_hook_client_t, link);
const ebpf_extension_data_t* next_client_data = next_client->client_data;
void* next_client_attach_parameter =
(next_client_data->data == NULL) ? wild_card_attach_parameter : next_client_data->data;
if (((memcmp(wild_card_attach_parameter, next_client_attach_parameter, attach_parameter_size) == 0)) ||
(memcmp(attach_parameter, next_client_attach_parameter, attach_parameter_size) == 0)) {
result = EBPF_ACCESS_DENIED;
goto Exit;
}
link = link->Flink;
}
}
Exit:
if (lock_held)
ExReleasePushLockShared(&provider_context->lock);
return result;
}
/**
* @brief Callback invoked when an eBPF hook NPI client (a.k.a eBPF link object) attaches.
*
@ -290,7 +349,7 @@ net_ebpf_extension_hook_provider_attach_client(
hook_client->execution_type = local_provider_context->execution_type;
// Invoke the hook specific callback to process client attach.
result = local_provider_context->attach_callback(hook_client);
result = local_provider_context->attach_callback(hook_client, local_provider_context);
if (result == EBPF_SUCCESS) {
status = _ebpf_ext_attach_init_rundown(hook_client);
@ -372,6 +431,7 @@ net_ebpf_extension_hook_provider_register(
_In_ const net_ebpf_extension_hook_provider_parameters_t* parameters,
_In_ net_ebpf_extension_hook_on_client_attach attach_callback,
_In_ net_ebpf_extension_hook_on_client_detach detach_callback,
_In_opt_ const void* custom_data,
_Outptr_ net_ebpf_extension_hook_provider_t** provider_context)
{
NTSTATUS status = STATUS_SUCCESS;
@ -400,6 +460,7 @@ net_ebpf_extension_hook_provider_register(
local_provider_context->execution_type = parameters->execution_type;
local_provider_context->attach_callback = attach_callback;
local_provider_context->detach_callback = detach_callback;
local_provider_context->custom_data = custom_data;
status = NmrRegisterProvider(characteristics, local_provider_context, &local_provider_context->nmr_provider_handle);
if (!NT_SUCCESS(status))

Просмотреть файл

@ -53,7 +53,7 @@ net_ebpf_extension_hook_client_get_client_data(_In_ const net_ebpf_extension_hoo
* @brief Set the hook-specific provider data for the attached client.
*
* @param[in] hook_client Pointer to attached hook NPI client.
* @returns hook-specific provider data.
* @param[in] data hook-specific provider data.
*
*/
void
@ -64,7 +64,7 @@ net_ebpf_extension_hook_client_set_provider_data(_In_ net_ebpf_extension_hook_cl
*
* @param[in] hook_client Pointer to attached hook NPI client.
*
* @returns Hook-specific provider data.
* @returns Pointer to hook-specific provider data for the attached client.
*/
const void*
net_ebpf_extension_hook_client_get_provider_data(_In_ const net_ebpf_extension_hook_client_t* hook_client);
@ -74,6 +74,17 @@ net_ebpf_extension_hook_client_get_provider_data(_In_ const net_ebpf_extension_h
*/
typedef struct _net_ebpf_extension_hook_provider net_ebpf_extension_hook_provider_t;
/**
* @brief Get the hook-specific custom data from the provider.
*
* @param[in] provider_context Pointer to hook NPI provider.
*
* @returns Pointer to the hook-specific custom data from the provider.
*
*/
const void*
net_ebpf_extension_hook_provider_get_custom_data(_In_ const net_ebpf_extension_hook_provider_t* provider_context);
/**
* @brief Unregister the hook NPI provider.
*
@ -87,13 +98,15 @@ net_ebpf_extension_hook_provider_unregister(_Frees_ptr_opt_ net_ebpf_extension_h
* is attempting to attach to the hook NPI provider. The hook NPI client is allowed to attach only if the API returns
* success.
* @param attaching_client Pointer to context of the hook NPI client that is requesting to be attached.
* @param provider_context Pointer to the hook NPI provider context to which the client is being attached.
*
* @retval EBPF_SUCCESS The operation succeeded.
* @retval EBPF_ACCESS_DENIED Request to attach client is denied by the provider.
* @retval EBPF_INVALID_ARGUMENT One or more parameters are incorrect.
*/
typedef ebpf_result_t (*net_ebpf_extension_hook_on_client_attach)(
_In_ const net_ebpf_extension_hook_client_t* attaching_client);
_In_ const net_ebpf_extension_hook_client_t* attaching_client,
_In_ const net_ebpf_extension_hook_provider_t* provider_context);
/**
* @brief This callback function should be implemented by hook modules. This callback is invoked when a hook NPI client
@ -119,6 +132,7 @@ typedef struct _net_ebpf_extension_hook_provider_parameters
* @param[in] parameters Pointer to the NPI provider characteristics struct.
* @param[in] attach_callback Pointer to callback function to be invoked when a client attaches.
* @param[in] detach_callback Pointer to callback function to be invoked when a client detaches.
* @param[in] custom_data (Optional) Opaque pointer to hook-specific custom data.
* @param[in,out] provider_context Pointer to the provider context being registered.
*
* @retval STATUS_SUCCESS Operation succeeded.
@ -129,6 +143,7 @@ net_ebpf_extension_hook_provider_register(
_In_ const net_ebpf_extension_hook_provider_parameters_t* parameters,
_In_ net_ebpf_extension_hook_on_client_attach attach_callback,
_In_ net_ebpf_extension_hook_on_client_detach detach_callback,
_In_opt_ const void* custom_data,
_Outptr_ net_ebpf_extension_hook_provider_t** provider_context);
/**
@ -167,3 +182,21 @@ net_ebpf_extension_hook_client_t*
net_ebpf_extension_hook_get_next_attached_client(
_In_ net_ebpf_extension_hook_provider_t* provider_context,
_In_opt_ const net_ebpf_extension_hook_client_t* client_context);
/**
* @brief Utility function called from net_ebpf_extension_hook_on_client_attach callback of hook providers, that
* determines if the attach parameter provided by an attaching client is compatible with the existing clients.
* @param[in] attach_parameter_size The expected length (in bytes) of attach parameter for this type of hook.
* @param[in] attach_parameter The attach parameter supplied by the client requesting to be attached.
* @param[in] wild_card_attach_parameter Pointer to wild card parameter for this type of hook.
* @param[in] provider_context Provider module's context.
* @retval EBPF_SUCCESS The operation succeeded.
* @retval EBPF_ACCESS_DENIED Request to attach client is denied by the provider.
* @retval EBPF_INVALID_ARGUMENT One or more parameters are incorrect.
*/
ebpf_result_t
net_ebpf_extension_hook_check_attach_parameter(
size_t attach_parameter_size,
_In_reads_(attach_parameter_size) const void* attach_parameter,
_In_reads_(attach_parameter_size) const void* wild_card_attach_parameter,
_In_ net_ebpf_extension_hook_provider_t* provider_context);

Просмотреть файл

@ -0,0 +1,283 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
/**
* @file This file implements the hook for the CGROUP_SOCK_ADDR program type and associated attach types, on eBPF for
* Windows.
*
*/
#define INITGUID
#include "net_ebpf_ext_sock_addr.h"
//
// WFP filter related types & globals for SOCK_ADDR hook.
//
const ebpf_attach_type_t* _net_ebpf_extension_sock_addr_attach_types[] = {
&EBPF_ATTACH_TYPE_CGROUP_INET4_CONNECT,
&EBPF_ATTACH_TYPE_CGROUP_INET4_RECV_ACCEPT,
&EBPF_ATTACH_TYPE_CGROUP_INET6_CONNECT,
&EBPF_ATTACH_TYPE_CGROUP_INET6_RECV_ACCEPT};
#define NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT EBPF_COUNT_OF(_net_ebpf_extension_sock_addr_attach_types)
const net_ebpf_extension_wfp_filter_parameters_t _net_ebpf_extension_sock_addr_wfp_filter_parameters[] = {
{&FWPM_LAYER_ALE_AUTH_CONNECT_V4,
&EBPF_HOOK_ALE_AUTH_CONNECT_V4_CALLOUT,
L"net eBPF sock_addr hook",
L"net eBPF sock_addr hook WFP filter"},
{&FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V4,
&EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V4_CALLOUT,
L"net eBPF sock_addr hook",
L"net eBPF sock_addr hook WFP filter"},
{&FWPM_LAYER_ALE_AUTH_CONNECT_V6,
&EBPF_HOOK_ALE_AUTH_CONNECT_V6_CALLOUT,
L"net eBPF sock_addr hook",
L"net eBPF sock_addr hook WFP filter"},
{&FWPM_LAYER_ALE_AUTH_RECV_ACCEPT_V6,
&EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V6_CALLOUT,
L"net eBPF sock_addr hook",
L"net eBPF sock_addr hook WFP filter"}};
typedef struct _net_ebpf_extension_sock_addr_wfp_filter_context
{
const net_ebpf_extension_hook_client_t* client_context;
uint32_t compartment_id;
uint64_t filter_id;
} net_ebpf_extension_sock_addr_wfp_filter_context_t;
//
// SOCK_ADDR Program Information NPI Provider.
//
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 = {
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}};
static net_ebpf_extension_program_info_provider_t* _ebpf_sock_addr_program_info_provider_context = NULL;
//
// SOCK_ADDR Hook NPI Provider.
//
ebpf_attach_provider_data_t _net_ebpf_sock_addr_hook_provider_data;
ebpf_extension_data_t _net_ebpf_extension_sock_addr_hook_provider_data = {
EBPF_ATTACH_PROVIDER_DATA_VERSION,
sizeof(_net_ebpf_sock_addr_hook_provider_data),
&_net_ebpf_sock_addr_hook_provider_data};
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*
_ebpf_sock_addr_hook_provider_context[NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT] = {0};
//
// NMR Registration Helper Routines.
//
static ebpf_result_t
net_ebpf_extension_sock_addr_on_client_attach(
_In_ const net_ebpf_extension_hook_client_t* attaching_client,
_In_ const net_ebpf_extension_hook_provider_t* provider_context)
{
ebpf_result_t result = EBPF_SUCCESS;
const ebpf_extension_data_t* client_data = net_ebpf_extension_hook_client_get_client_data(attaching_client);
uint32_t compartment_id;
uint32_t wild_card_compartment_id = UNSPECIFIED_COMPARTMENT_ID;
net_ebpf_extension_wfp_filter_parameters_t* filter_parameters = NULL;
FWPM_FILTER_CONDITION condition = {0};
net_ebpf_extension_sock_addr_wfp_filter_context_t* filter_context = NULL;
// SOCK_ADDR hook clients must always provide data.
if (client_data == NULL) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (client_data->size > 0) {
if ((client_data->size != sizeof(uint32_t)) || (client_data->data == NULL)) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
compartment_id = *(uint32_t*)client_data->data;
} else {
// If the client did not specify any attach parameters, we treat that as a wildcard interface index.
compartment_id = wild_card_compartment_id;
}
result = net_ebpf_extension_hook_check_attach_parameter(
sizeof(compartment_id),
&compartment_id,
&wild_card_compartment_id,
(net_ebpf_extension_hook_provider_t*)provider_context);
if (result != EBPF_SUCCESS)
goto Exit;
if (client_data->data != NULL)
compartment_id = *(uint32_t*)client_data->data;
// Set compartment id (if not UNSPECIFIED_COMPARTMENT_ID) as WFP filter condition.
if (compartment_id != UNSPECIFIED_COMPARTMENT_ID) {
condition.fieldKey = FWPM_CONDITION_COMPARTMENT_ID;
condition.matchType = FWP_MATCH_EQUAL;
condition.conditionValue.type = FWP_UINT32;
condition.conditionValue.uint32 = compartment_id;
}
// Allocate buffer for WFP filter context.
filter_context = (net_ebpf_extension_sock_addr_wfp_filter_context_t*)ExAllocatePoolUninitialized(
NonPagedPoolNx, sizeof(net_ebpf_extension_sock_addr_wfp_filter_context_t), NET_EBPF_EXTENSION_POOL_TAG);
if (filter_context == NULL) {
result = EBPF_NO_MEMORY;
goto Exit;
}
memset(filter_context, 0, sizeof(net_ebpf_extension_sock_addr_wfp_filter_context_t));
filter_context->client_context = attaching_client;
filter_context->compartment_id = compartment_id;
// Get the WFP filter parameters for this hook type.
filter_parameters =
(net_ebpf_extension_wfp_filter_parameters_t*)net_ebpf_extension_hook_provider_get_custom_data(provider_context);
ASSERT(filter_parameters != NULL);
// Add a single WFP filter at the WFP layer corresponding to the hook type, and set the hook NPI client as the
// filter's raw context.
result = net_ebpf_extension_add_wfp_filters(
1, // filter_count
filter_parameters,
(compartment_id == UNSPECIFIED_COMPARTMENT_ID) ? 0 : 1,
(compartment_id == UNSPECIFIED_COMPARTMENT_ID) ? NULL : &condition,
filter_context,
&filter_context->filter_id);
if (result != EBPF_SUCCESS)
goto Exit;
// Set the filter context as the client context's provider data.
net_ebpf_extension_hook_client_set_provider_data(
(net_ebpf_extension_hook_client_t*)attaching_client, filter_context);
Exit:
if (result != EBPF_SUCCESS) {
if (filter_context != NULL)
ExFreePool(filter_context);
}
return result;
}
static void
_net_ebpf_extension_sock_addr_on_client_detach(_In_ const net_ebpf_extension_hook_client_t* detaching_client)
{
net_ebpf_extension_sock_addr_wfp_filter_context_t* filter_context =
(net_ebpf_extension_sock_addr_wfp_filter_context_t*)net_ebpf_extension_hook_client_get_provider_data(
detaching_client);
ASSERT(filter_context != NULL);
net_ebpf_extension_delete_wfp_filters(1, &filter_context->filter_id);
ExFreePool(filter_context);
}
NTSTATUS
net_ebpf_ext_sock_addr_register_providers()
{
NTSTATUS status = STATUS_SUCCESS;
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.program_type_descriptor.program_type = EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR;
// 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 (status != STATUS_SUCCESS)
goto Exit;
_net_ebpf_sock_addr_hook_provider_data.supported_program_type = EBPF_PROGRAM_TYPE_CGROUP_SOCK_ADDR;
for (int i = 0; i < NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT; i++) {
// Set the attach type as the provider module id.
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,
EXECUTION_DISPATCH};
// Set the attach type as the provider module id.
_ebpf_sock_addr_hook_provider_moduleid[i].Length = sizeof(NPI_MODULEID);
_ebpf_sock_addr_hook_provider_moduleid[i].Type = MIT_GUID;
_ebpf_sock_addr_hook_provider_moduleid[i].Guid = *_net_ebpf_extension_sock_addr_attach_types[i];
// 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(
&hook_provider_parameters,
net_ebpf_extension_sock_addr_on_client_attach,
_net_ebpf_extension_sock_addr_on_client_detach,
&_net_ebpf_extension_sock_addr_wfp_filter_parameters[i],
&_ebpf_sock_addr_hook_provider_context[i]);
}
if (status != EBPF_SUCCESS)
goto Exit;
Exit:
return status;
}
void
net_ebpf_ext_sock_addr_unregister_providers()
{
for (int i = 0; i < NET_EBPF_SOCK_ADDR_HOOK_PROVIDER_COUNT; i++)
net_ebpf_extension_hook_provider_unregister(_ebpf_sock_addr_hook_provider_context[i]);
net_ebpf_extension_program_info_provider_unregister(_ebpf_sock_addr_program_info_provider_context);
}
//
// WFP callout callback functions.
//
void
net_ebpf_ext_authorize_connection_classify(
_In_ const FWPS_INCOMING_VALUES* incoming_fixed_values,
_In_ const FWPS_INCOMING_METADATA_VALUES* incoming_metadata_values,
_Inout_opt_ void* layer_data,
_In_opt_ const void* classify_context,
_In_ const FWPS_FILTER* filter,
uint64_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output)
{
SOCKADDR_IN addr = {AF_INET};
uint32_t result;
net_ebpf_extension_hook_client_t* attached_client = NULL;
bpf_sock_addr_t sock_addr_ctx = {0};
UNREFERENCED_PARAMETER(incoming_metadata_values);
UNREFERENCED_PARAMETER(layer_data);
UNREFERENCED_PARAMETER(classify_context);
UNREFERENCED_PARAMETER(flow_context);
attached_client = (net_ebpf_extension_hook_client_t*)filter->context;
ASSERT(attached_client != NULL);
if (attached_client == NULL)
goto Exit;
if (!net_ebpf_extension_hook_client_enter_rundown(attached_client, EXECUTION_PASSIVE)) {
classify_output->actionType = FWP_ACTION_PERMIT;
goto Exit;
}
addr.sin_port = incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_PORT].value.uint16;
addr.sin_addr.S_un.S_addr =
incoming_fixed_values->incomingValue[FWPS_FIELD_ALE_AUTH_CONNECT_V4_IP_LOCAL_ADDRESS].value.uint32;
net_ebpf_extension_hook_invoke_program(attached_client, &sock_addr_ctx, &result);
classify_output->actionType = FWP_ACTION_PERMIT;
Exit:
if (attached_client)
net_ebpf_extension_hook_client_leave_rundown(attached_client, EXECUTION_PASSIVE);
return;
}

Просмотреть файл

@ -0,0 +1,77 @@
// Copyright (c) Microsoft Corporation
// SPDX-License-Identifier: MIT
#pragma once
#include "net_ebpf_ext.h"
// Callout and sublayer GUIDs
// 98849e0b-b07d-11ec-9a30-18602489beee
DEFINE_GUID(
EBPF_HOOK_ALE_AUTH_CONNECT_V4_CALLOUT, 0x98849e0b, 0xb07d, 0x11ec, 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee);
// 98849e0c-b07d-11ec-9a30-18602489beee
DEFINE_GUID(
EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V4_CALLOUT,
0x98849e0c,
0xb07d,
0x11ec,
0x9a,
0x30,
0x18,
0x60,
0x24,
0x89,
0xbe,
0xee);
// 98849e0d-b07d-11ec-9a30-18602489beee
DEFINE_GUID(
EBPF_HOOK_ALE_AUTH_CONNECT_V6_CALLOUT, 0x98849e0d, 0xb07d, 0x11ec, 0x9a, 0x30, 0x18, 0x60, 0x24, 0x89, 0xbe, 0xee);
// 98849e0e-b07d-11ec-9a30-18602489beee
DEFINE_GUID(
EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V6_CALLOUT,
0x98849e0e,
0xb07d,
0x11ec,
0x9a,
0x30,
0x18,
0x60,
0x24,
0x89,
0xbe,
0xee);
/**
* @brief WFP classifyFn callback for EBPF_HOOK_ALE_AUTH_CONNECT_V4/6_CALLOUT &
* EBPF_HOOK_ALE_AUTH_RECV_ACCEPT_V4/6_CALLOUT.
*
*/
void
net_ebpf_ext_authorize_connection_classify(
_In_ const FWPS_INCOMING_VALUES* incoming_fixed_values,
_In_ const FWPS_INCOMING_METADATA_VALUES* incoming_metadata_values,
_Inout_opt_ void* layer_data,
_In_opt_ const void* classify_context,
_In_ const FWPS_FILTER* filter,
uint64_t flow_context,
_Inout_ FWPS_CLASSIFY_OUT* classify_output);
/**
* @brief Unregister CGROUP_SOCK_ADDR NPI providers.
*
*/
void
net_ebpf_ext_sock_addr_unregister_providers();
/**
* @brief Register CGROUP_SOCK_ADDR NPI providers.
*
* @retval STATUS_SUCCESS Operation succeeded.
* @retval STATUS_UNSUCCESSFUL Operation failed.
*/
NTSTATUS
net_ebpf_ext_sock_addr_register_providers();

Просмотреть файл

@ -34,7 +34,7 @@ Exit:
}
//
// WFP XDP layer filter related types & globals.
// WFP filter related types & globals for XDP hook.
//
const net_ebpf_extension_wfp_filter_parameters_t _net_ebpf_extension_xdp_wfp_filter_parameters[] = {
@ -95,11 +95,14 @@ static net_ebpf_extension_hook_provider_t* _ebpf_xdp_hook_provider_context = NUL
//
static ebpf_result_t
net_ebpf_extension_xdp_on_client_attach(_In_ const net_ebpf_extension_hook_client_t* attaching_client)
net_ebpf_extension_xdp_on_client_attach(
_In_ const net_ebpf_extension_hook_client_t* attaching_client,
_In_ const net_ebpf_extension_hook_provider_t* provider_context)
{
ebpf_result_t result = EBPF_SUCCESS;
const ebpf_extension_data_t* client_data = net_ebpf_extension_hook_client_get_client_data(attaching_client);
uint32_t if_index;
uint32_t wild_card_if_index = 0;
uint32_t filter_count;
FWPM_FILTER_CONDITION condition = {0};
net_ebpf_extension_xdp_wfp_filter_context_t* filter_context = NULL;
@ -110,49 +113,24 @@ net_ebpf_extension_xdp_on_client_attach(_In_ const net_ebpf_extension_hook_clien
goto Exit;
}
// Validate client data.
if (client_data->version != EBPF_ATTACH_CLIENT_DATA_VERSION) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if (client_data->size > 0) {
if ((client_data->size < sizeof(uint32_t)) || (client_data->data == NULL)) {
if ((client_data->size != sizeof(uint32_t)) || (client_data->data == NULL)) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
if_index = *(uint32_t*)client_data->data;
} else {
// If the client did not specify any attach parameters, we treat that as a wildcard interface index.
if_index = 0;
if_index = wild_card_if_index;
}
if (if_index == 0) {
// Client requested wildcard interface. This will only be allowed if there are no other clients attached.
if (net_ebpf_extension_hook_get_next_attached_client(_ebpf_xdp_hook_provider_context, NULL) != NULL) {
result = EBPF_ACCESS_DENIED;
goto Exit;
}
} else {
if (!NT_SUCCESS(_net_ebpf_extension_xdp_validate_if_index(if_index))) {
result = EBPF_INVALID_ARGUMENT;
goto Exit;
}
// Ensure there are no other clients with interface index 0 or with the same interface index as the
// requesting client.
net_ebpf_extension_hook_client_t* next_client =
net_ebpf_extension_hook_get_next_attached_client(_ebpf_xdp_hook_provider_context, NULL);
while (next_client != NULL) {
const ebpf_extension_data_t* next_client_data = net_ebpf_extension_hook_client_get_client_data(next_client);
uint32_t next_client_if_index = (next_client_data->data == NULL) ? 0 : *(uint32_t*)next_client_data->data;
if ((next_client_if_index == 0) || (if_index == next_client_if_index)) {
result = EBPF_ACCESS_DENIED;
goto Exit;
}
next_client =
net_ebpf_extension_hook_get_next_attached_client(_ebpf_xdp_hook_provider_context, next_client);
}
}
result = net_ebpf_extension_hook_check_attach_parameter(
sizeof(if_index), &if_index, &wild_card_if_index, (net_ebpf_extension_hook_provider_t*)provider_context);
if (result != EBPF_SUCCESS)
goto Exit;
if (client_data->data != NULL)
if_index = *(uint32_t*)client_data->data;
// Set interface index (if non-zero) as WFP filter condition.
if (if_index != 0) {
@ -233,6 +211,7 @@ net_ebpf_ext_xdp_register_providers()
&hook_provider_parameters,
net_ebpf_extension_xdp_on_client_attach,
_net_ebpf_extension_xdp_on_client_detach,
NULL,
&_ebpf_xdp_hook_provider_context);
if (status != EBPF_SUCCESS)

Просмотреть файл

@ -132,6 +132,7 @@
<ClCompile Include="net_ebpf_ext_drv.c" />
<ClCompile Include="net_ebpf_ext_hook_provider.c" />
<ClCompile Include="net_ebpf_ext_prog_info_provider.c"/>
<ClCompile Include="net_ebpf_ext_sock_addr.c" />
<ClCompile Include="net_ebpf_ext_xdp.c" />
</ItemGroup>
<ItemGroup>
@ -143,11 +144,12 @@
<ItemGroup>
<ClInclude Include="net_ebpf_ext.h" />
<ClInclude Include="net_ebpf_ext_bind.h" />
<ClInclude Include="net_ebpf_ext_xdp.h" />
<ClInclude Include="net_ebpf_ext_helpers.h" />
<ClInclude Include="net_ebpf_ext_hook_provider.h" />
<ClInclude Include="net_ebpf_ext_program_info.h" />
<ClInclude Include="net_ebpf_ext_prog_info_provider.h"/>
<ClInclude Include="net_ebpf_ext_sock_addr.h" />
<ClInclude Include="net_ebpf_ext_xdp.h" />
<ClInclude Include="resource.h" />
</ItemGroup>
<ItemGroup>

Просмотреть файл

@ -44,7 +44,7 @@ authorize_v4(bpf_sock_addr_t* ctx)
verdict = bpf_map_lookup_elem(&connection_policy_map, &tuple_key);
return (verdict != NULL) ? *verdict : 0;
return (verdict != NULL) ? *verdict : 1;
}
__inline int
@ -60,7 +60,7 @@ authorize_v6(bpf_sock_addr_t* ctx)
verdict = bpf_map_lookup_elem(&connection_policy_map, &tuple_key);
return (verdict != NULL) ? *verdict : 0;
return (verdict != NULL) ? *verdict : 1;
}
SEC("cgroup/connect4")