-
Notifications
You must be signed in to change notification settings - Fork 241
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Signed-off-by: Alan Jowett <[email protected]>
- Loading branch information
1 parent
1aa11e8
commit bdd71d2
Showing
13 changed files
with
374 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,252 @@ | ||
// Copyright (c) Microsoft Corporation | ||
// SPDX-License-Identifier: MIT | ||
|
||
/** | ||
* @file | ||
* @brief This file implements the process program type hook on eBPF for Windows. | ||
*/ | ||
|
||
#include "ebpf_shared_framework.h" | ||
#include "net_ebpf_ext_process.h" | ||
|
||
static ebpf_result_t | ||
_ebpf_process_context_create( | ||
_In_reads_bytes_opt_(data_size_in) const uint8_t* data_in, | ||
size_t data_size_in, | ||
_In_reads_bytes_opt_(context_size_in) const uint8_t* context_in, | ||
size_t context_size_in, | ||
_Outptr_ void** context); | ||
|
||
static void | ||
_ebpf_process_context_destroy( | ||
_In_opt_ void* context, | ||
_Out_writes_bytes_to_(*data_size_out, *data_size_out) uint8_t* data_out, | ||
_Inout_ size_t* data_size_out, | ||
_Out_writes_bytes_to_(*context_size_out, *context_size_out) uint8_t* context_out, | ||
_Inout_ size_t* context_size_out); | ||
|
||
// | ||
// Process Program Information NPI Provider. | ||
// | ||
static ebpf_program_data_t _ebpf_process_program_data = { | ||
.program_info = &_ebpf_process_program_info, | ||
.context_create = _ebpf_process_context_create, | ||
.context_destroy = _ebpf_process_context_destroy, | ||
.required_irql = PASSIVE_LEVEL, | ||
}; | ||
|
||
static ebpf_extension_data_t _ebpf_process_program_info_provider_data = { | ||
NET_EBPF_EXTENSION_NPI_PROVIDER_VERSION, sizeof(_ebpf_process_program_data), &_ebpf_process_program_data}; | ||
|
||
NPI_MODULEID DECLSPEC_SELECTANY _ebpf_process_program_info_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; | ||
|
||
static net_ebpf_extension_program_info_provider_t* _ebpf_process_program_info_provider_context = NULL; | ||
|
||
// | ||
// Process Hook NPI Provider. | ||
// | ||
ebpf_attach_provider_data_t _net_ebpf_process_hook_provider_data; | ||
|
||
ebpf_extension_data_t _net_ebpf_extension_process_hook_provider_data = { | ||
EBPF_ATTACH_PROVIDER_DATA_VERSION, | ||
sizeof(_net_ebpf_process_hook_provider_data), | ||
&_net_ebpf_process_hook_provider_data}; | ||
|
||
NPI_MODULEID DECLSPEC_SELECTANY _ebpf_process_hook_provider_moduleid = {sizeof(NPI_MODULEID), MIT_GUID, {0}}; | ||
|
||
static net_ebpf_extension_hook_provider_t* _ebpf_process_hook_provider_context = NULL; | ||
|
||
// | ||
// Client attach/detach handler routines. | ||
// | ||
|
||
static ebpf_result_t | ||
_net_ebpf_extension_process_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; | ||
|
||
NET_EBPF_EXT_LOG_ENTRY(); | ||
|
||
UNREFERENCED_PARAMETER(attaching_client); | ||
|
||
// Process hook allows only one client at a time. | ||
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; | ||
} | ||
|
||
result = EBPF_SUCCESS; | ||
|
||
Exit: | ||
NET_EBPF_EXT_RETURN_RESULT(result); | ||
} | ||
|
||
static void | ||
_net_ebpf_extension_process_on_client_detach(_In_ const net_ebpf_extension_hook_client_t* detaching_client) | ||
{ | ||
UNREFERENCED_PARAMETER(detaching_client); | ||
} | ||
|
||
// | ||
// NMR Registration Helper Routines. | ||
// | ||
|
||
NTSTATUS | ||
net_ebpf_ext_process_register_providers() | ||
{ | ||
NTSTATUS status = STATUS_SUCCESS; | ||
|
||
NET_EBPF_EXT_LOG_ENTRY(); | ||
|
||
const net_ebpf_extension_program_info_provider_parameters_t program_info_provider_parameters = { | ||
&_ebpf_process_program_info_provider_moduleid, &_ebpf_process_program_info_provider_data}; | ||
const net_ebpf_extension_hook_provider_parameters_t hook_provider_parameters = { | ||
&_ebpf_process_hook_provider_moduleid, &_net_ebpf_extension_process_hook_provider_data}; | ||
|
||
// Set the program type as the provider module id. | ||
_ebpf_process_program_info_provider_moduleid.Guid = EBPF_PROGRAM_TYPE_PROCESS; | ||
status = net_ebpf_extension_program_info_provider_register( | ||
&program_info_provider_parameters, &_ebpf_process_program_info_provider_context); | ||
if (!NT_SUCCESS(status)) { | ||
NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS( | ||
NET_EBPF_EXT_TRACELOG_LEVEL_ERROR, | ||
NET_EBPF_EXT_TRACELOG_KEYWORD_PROCESS, | ||
"net_ebpf_extension_program_info_provider_register", | ||
status); | ||
goto Exit; | ||
} | ||
|
||
_net_ebpf_process_hook_provider_data.supported_program_type = EBPF_PROGRAM_TYPE_PROCESS; | ||
// Set the attach type as the provider module id. | ||
_ebpf_process_hook_provider_moduleid.Guid = EBPF_ATTACH_TYPE_PROCESS; | ||
_net_ebpf_process_hook_provider_data.bpf_attach_type = BPF_ATTACH_TYPE_PROCESS; | ||
_net_ebpf_process_hook_provider_data.link_type = BPF_LINK_TYPE_PLAIN; | ||
status = net_ebpf_extension_hook_provider_register( | ||
&hook_provider_parameters, | ||
_net_ebpf_extension_process_on_client_attach, | ||
_net_ebpf_extension_process_on_client_detach, | ||
NULL, | ||
&_ebpf_process_hook_provider_context); | ||
if (status != EBPF_SUCCESS) { | ||
NET_EBPF_EXT_LOG_MESSAGE_NTSTATUS( | ||
NET_EBPF_EXT_TRACELOG_LEVEL_ERROR, | ||
NET_EBPF_EXT_TRACELOG_KEYWORD_PROCESS, | ||
"net_ebpf_extension_hook_provider_register", | ||
status); | ||
goto Exit; | ||
} | ||
|
||
Exit: | ||
if (!NT_SUCCESS(status)) { | ||
net_ebpf_ext_process_unregister_providers(); | ||
} | ||
NET_EBPF_EXT_RETURN_NTSTATUS(status); | ||
} | ||
|
||
void | ||
net_ebpf_ext_process_unregister_providers() | ||
{ | ||
if (_ebpf_process_hook_provider_context) { | ||
net_ebpf_extension_hook_provider_unregister(_ebpf_process_hook_provider_context); | ||
_ebpf_process_hook_provider_context = NULL; | ||
} | ||
if (_ebpf_process_program_info_provider_context) { | ||
net_ebpf_extension_program_info_provider_unregister(_ebpf_process_program_info_provider_context); | ||
_ebpf_process_program_info_provider_context = NULL; | ||
} | ||
} | ||
|
||
static ebpf_result_t | ||
_ebpf_process_context_create( | ||
_In_reads_bytes_opt_(data_size_in) const uint8_t* data_in, | ||
size_t data_size_in, | ||
_In_reads_bytes_opt_(context_size_in) const uint8_t* context_in, | ||
size_t context_size_in, | ||
_Outptr_ void** context) | ||
{ | ||
NET_EBPF_EXT_LOG_ENTRY(); | ||
ebpf_result_t result; | ||
process_md_t* process_context = NULL; | ||
|
||
*context = NULL; | ||
|
||
if (context_in == NULL || context_size_in < sizeof(process_md_t)) { | ||
NET_EBPF_EXT_LOG_MESSAGE( | ||
NET_EBPF_EXT_TRACELOG_LEVEL_ERROR, NET_EBPF_EXT_TRACELOG_KEYWORD_PROCESS, "Context is required"); | ||
result = EBPF_INVALID_ARGUMENT; | ||
goto Exit; | ||
} | ||
|
||
process_context = | ||
(process_md_t*)ExAllocatePoolUninitialized(NonPagedPoolNx, sizeof(process_md_t), NET_EBPF_EXTENSION_POOL_TAG); | ||
NET_EBPF_EXT_BAIL_ON_ALLOC_FAILURE_RESULT( | ||
NET_EBPF_EXT_TRACELOG_KEYWORD_PROCESS, process_context, "process_context", result); | ||
|
||
// Copy the context from the caller. | ||
memcpy(process_context, context_in, sizeof(process_md_t)); | ||
|
||
// Replace the process_id_start and process_id_end with pointers to data_in. | ||
process_context->process_id_end = (uint8_t*)data_in; | ||
process_context->process_id_end = (uint8_t*)data_in + data_size_in; | ||
|
||
*context = process_context; | ||
process_context = NULL; | ||
result = EBPF_SUCCESS; | ||
|
||
Exit: | ||
if (process_context) { | ||
ExFreePool(process_context); | ||
process_context = NULL; | ||
} | ||
NET_EBPF_EXT_RETURN_RESULT(result); | ||
} | ||
|
||
static void | ||
_ebpf_process_context_destroy( | ||
_In_opt_ void* context, | ||
_Out_writes_bytes_to_(*data_size_out, *data_size_out) uint8_t* data_out, | ||
_Inout_ size_t* data_size_out, | ||
_Out_writes_bytes_to_(*context_size_out, *context_size_out) uint8_t* context_out, | ||
_Inout_ size_t* context_size_out) | ||
{ | ||
NET_EBPF_EXT_LOG_ENTRY(); | ||
|
||
process_md_t* process_context = (process_md_t*)context; | ||
process_md_t* process_context_out = (process_md_t*)context_out; | ||
|
||
if (!process_context) { | ||
goto Exit; | ||
} | ||
|
||
if (context_out != NULL && *context_size_out >= sizeof(process_md_t)) { | ||
// Copy the context to the caller. | ||
memcpy(process_context_out, process_context, sizeof(process_md_t)); | ||
|
||
// Zero out the process_id_start and process_id_end. | ||
process_context_out->process_id_start = 0; | ||
process_context_out->process_id_end = 0; | ||
*context_size_out = sizeof(process_md_t); | ||
} else { | ||
*context_size_out = 0; | ||
} | ||
|
||
// Copy the process_id to the data_out. | ||
if (data_out != NULL && | ||
*data_size_out >= (size_t)(process_context->process_id_end - process_context->process_id_start)) { | ||
memcpy( | ||
data_out, | ||
process_context->process_id_start, | ||
process_context->process_id_end - process_context->process_id_start); | ||
*data_size_out = process_context->process_id_end - process_context->process_id_start; | ||
} else { | ||
*data_size_out = 0; | ||
} | ||
|
||
ExFreePool(process_context); | ||
|
||
Exit: | ||
NET_EBPF_EXT_LOG_EXIT(); | ||
} |
Oops, something went wrong.