Skip to content

Commit

Permalink
Switch to utf-8 to save space
Browse files Browse the repository at this point in the history
Signed-off-by: Alan Jowett <[email protected]>
  • Loading branch information
Alan Jowett committed Mar 4, 2024
1 parent dc6bf0a commit c57dc57
Show file tree
Hide file tree
Showing 6 changed files with 213 additions and 86 deletions.
31 changes: 29 additions & 2 deletions include/ebpf_nethooks.h
Original file line number Diff line number Diff line change
Expand Up @@ -273,8 +273,8 @@ typedef enum _process_operation

typedef struct _process_md
{
uint8_t* command_start; ///< Pointer to start of the command line.
uint8_t* command_end; ///< Pointer to end of the command line.
uint8_t* command_start; ///< Pointer to start of the command line as UTF-8 string.
uint8_t* command_end; ///< Pointer to end of the command line as UTF-8 string.
uint64_t process_id; ///< Process ID.
uint64_t parent_process_id; ///< Parent process ID.
uint64_t creating_process_id; ///< Creating process ID.
Expand All @@ -298,6 +298,33 @@ typedef struct _process_md
typedef int
process_hook_t(process_md_t* context);

// Process helper functions.
#define PROCESS_EXT_HELPER_FN_BASE 0xFFFF

#ifndef __doxygen
#define EBPF_HELPER(return_type, name, args) typedef return_type(*name##_t) args
#endif

typedef enum
{
BPF_FUNC_process_get_image_path = PROCESS_EXT_HELPER_FN_BASE + 1,
} ebpf_process_helper_id_t;

/**
* @brief Get the image path of the process.
*
* @param[in] context Process metadata.
* @param[out] path Buffer to store the image path.
* @param[in] path_length Length of the buffer.
*
* @retval >=0 The length of the image path.
* @retval <0 A failure occurred.
*/
EBPF_HELPER(int, bpf_process_get_image_path, (process_md_t * ctx, uint8_t* path, uint32_t path_length));
#ifndef __doxygen
#define bpf_process_get_image_path ((bpf_process_get_image_path_t)BPF_FUNC_process_get_image_path)
#endif

#ifdef _MSC_VER
#pragma warning(pop)
#endif
72 changes: 59 additions & 13 deletions netebpfext/net_ebpf_ext_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "ebpf_shared_framework.h"
#include "net_ebpf_ext_process.h"

#include <errno.h>

static ebpf_result_t
_ebpf_process_context_create(
_In_reads_bytes_opt_(data_size_in) const uint8_t* data_in,
Expand All @@ -29,11 +31,20 @@ void
_ebpf_process_create_process_notify_routine_ex(
_Inout_ PEPROCESS process, _In_ HANDLE process_id, _Inout_opt_ PPS_CREATE_NOTIFY_INFO create_info);

static int32_t
_ebpf_process_get_image_path(_In_ process_md_t* process_md, _Out_ uint8_t* path, uint32_t path_length);

static const void* _ebpf_process_helper_functions[] = {(void*)&_ebpf_process_get_image_path};

static ebpf_helper_function_addresses_t _ebpf_process_helper_function_address_table = {
EBPF_COUNT_OF(_ebpf_process_helper_functions), (uint64_t*)_ebpf_process_helper_functions};

//
// Process Program Information NPI Provider.
//
static ebpf_program_data_t _ebpf_process_program_data = {
.program_info = &_ebpf_process_program_info,
.program_type_specific_helper_function_addresses = &_ebpf_process_helper_function_address_table,
.context_create = _ebpf_process_context_create,
.context_destroy = _ebpf_process_context_destroy,
.required_irql = PASSIVE_LEVEL,
Expand Down Expand Up @@ -304,6 +315,8 @@ typedef struct _process_notify_context
process_md_t process_md;
PEPROCESS process;
PPS_CREATE_NOTIFY_INFO create_info;
UTF8_STRING command_line_utf8;
UTF8_STRING image_file_name_utf8;
} process_notify_context_t;

void
Expand All @@ -315,22 +328,27 @@ _ebpf_process_create_process_notify_routine_ex(

NET_EBPF_EXT_LOG_ENTRY();

if (create_info != NULL && create_info->CommandLine != NULL) {
process_notify_context.process_md.command_start = (uint8_t*)create_info->CommandLine->Buffer;
if (create_info != NULL) {
if (create_info->CommandLine != NULL) {
RtlUnicodeStringToUTF8String(&process_notify_context.command_line_utf8, create_info->CommandLine, TRUE);
}
if (create_info->ImageFileName != NULL) {
RtlUnicodeStringToUTF8String(
&process_notify_context.image_file_name_utf8, create_info->ImageFileName, TRUE);
}
process_notify_context.process_md.operation = PROCESS_OPERATION_CREATE;
process_notify_context.process_md.process_id = (uint64_t)process_id;
process_notify_context.process_md.parent_process_id = (uint64_t)create_info->ParentProcessId;
process_notify_context.process_md.creating_process_id = (uint64_t)create_info->CreatingThreadId.UniqueProcess;
process_notify_context.process_md.creating_thread_id = (uint64_t)create_info->CreatingThreadId.UniqueThread;
process_notify_context.process_md.command_start = (uint8_t*)process_notify_context.command_line_utf8.Buffer;
process_notify_context.process_md.command_end =
(uint8_t*)create_info->CommandLine->Buffer + create_info->CommandLine->Length;
(uint8_t*)process_notify_context.command_line_utf8.Buffer + process_notify_context.command_line_utf8.Length;
} else {
process_notify_context.process_md.operation = PROCESS_OPERATION_DELETE;
process_notify_context.process_md.process_id = (uint64_t)process_id;
}

process_notify_context.process_md.operation =
(create_info != NULL) ? PROCESS_OPERATION_CREATE : PROCESS_OPERATION_DELETE;
process_notify_context.process_md.process_id = (uint64_t)process_id;
process_notify_context.process_md.parent_process_id =
(create_info != NULL) ? (uint64_t)create_info->ParentProcessId : 0;
process_notify_context.process_md.creating_process_id =
(create_info != NULL) ? (uint64_t)create_info->CreatingThreadId.UniqueProcess : 0;
process_notify_context.process_md.creating_thread_id =
(create_info != NULL) ? (uint64_t)create_info->CreatingThreadId.UniqueThread : 0;

// For each attached client call the process hook.
ebpf_result_t result;
net_ebpf_extension_hook_client_t* client_context =
Expand Down Expand Up @@ -363,5 +381,33 @@ _ebpf_process_create_process_notify_routine_ex(
net_ebpf_extension_hook_get_next_attached_client(_ebpf_process_hook_provider_context, client_context);
}

if (process_notify_context.command_line_utf8.Buffer != NULL) {
RtlFreeUTF8String(&process_notify_context.command_line_utf8);
}

if (process_notify_context.image_file_name_utf8.Buffer != NULL) {
RtlFreeUTF8String(&process_notify_context.image_file_name_utf8);
}

NET_EBPF_EXT_LOG_EXIT();
}

static int32_t
_ebpf_process_get_image_path(_In_ process_md_t* process_md, _Out_ uint8_t* path, uint32_t path_length)
{
process_notify_context_t* process_notify_context = (process_notify_context_t*)process_md;
int32_t result = 0;
if (process_notify_context->image_file_name_utf8.Length > path_length) {
return -EINVAL;
}
if (process_notify_context->image_file_name_utf8.Buffer != NULL) {
if (path_length >= process_notify_context->image_file_name_utf8.Length) {
memcpy(
path,
process_notify_context->image_file_name_utf8.Buffer,
process_notify_context->image_file_name_utf8.Length);
result = process_notify_context->image_file_name_utf8.Length;
}
}
return result;
}
26 changes: 19 additions & 7 deletions netebpfext/net_ebpf_ext_program_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,27 @@ static const ebpf_program_section_info_t _ebpf_sock_ops_section_info[] = {
BPF_PROG_TYPE_SOCK_OPS,
BPF_CGROUP_SOCK_OPS}};

// Process program information.
static const ebpf_helper_function_prototype_t _process_ebpf_extension_helper_function_prototype[] = {
{XDP_EXT_HELPER_FUNCTION_START + 1,
"bpf_process_get_image_path",
EBPF_RETURN_TYPE_INTEGER,
{EBPF_ARGUMENT_TYPE_PTR_TO_CTX, EBPF_ARGUMENT_TYPE_PTR_TO_WRITABLE_MEM, EBPF_ARGUMENT_TYPE_CONST_SIZE}},
};

static const ebpf_context_descriptor_t _ebpf_process_context_descriptor = {
sizeof(process_md_t), EBPF_OFFSET_OF(process_md_t, command_start), EBPF_OFFSET_OF(process_md_t, command_end), -1};
sizeof(process_md_t),
EBPF_OFFSET_OF(process_md_t, command_start),
EBPF_OFFSET_OF(process_md_t, command_end),
-1,
};

static const ebpf_program_info_t _ebpf_process_program_info = {
{"process", &_ebpf_process_context_descriptor, EBPF_PROGRAM_TYPE_PROCESS_GUID, BPF_PROG_TYPE_PROCESS}, 0, NULL};
{"process", &_ebpf_process_context_descriptor, EBPF_PROGRAM_TYPE_PROCESS_GUID, BPF_PROG_TYPE_PROCESS},
EBPF_COUNT_OF(_process_ebpf_extension_helper_function_prototype),
_process_ebpf_extension_helper_function_prototype,
};

static const ebpf_program_section_info_t _ebpf_process_section_info[] = {
{L"process",
&EBPF_PROGRAM_TYPE_PROCESS,
&EBPF_ATTACH_TYPE_PROCESS,
BPF_PROG_TYPE_PROCESS,
BPF_ATTACH_TYPE_PROCESS}};
{L"process", &EBPF_PROGRAM_TYPE_PROCESS, &EBPF_ATTACH_TYPE_PROCESS, BPF_PROG_TYPE_PROCESS, BPF_ATTACH_TYPE_PROCESS},
};
71 changes: 39 additions & 32 deletions tests/sample/process_monitor.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,33 +19,37 @@
#include "bpf_helpers.h"
#include "ebpf_nethooks.h"

// The non variable fields from the process_md_t struct.
typedef struct
{
uint64_t process_id;
uint64_t parent_process_id;
uint8_t command_line[256];
} proces_entry_t;
uint64_t creating_process_id;
uint64_t creating_thread_id;
uint64_t operation;
} process_info_t;

typedef struct
{
uint64_t process_id;
proces_entry_t entry;
} process_create_event_t;
#define MAX_PATH (496 - sizeof(process_info_t))

typedef struct
// LRU hash for storing the image path of a process.
struct
{
uint64_t process_id;
} process_delete_event_t;
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, uint64_t);
__type(value, char[MAX_PATH]);
__uint(max_entries, 1024);
} process_map SEC(".maps");

// Map for running processes.
// LRU hash for storing the command line of a process.
struct
{
__uint(type, BPF_MAP_TYPE_HASH);
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__type(key, uint64_t);
__type(value, proces_entry_t);
__type(value, char[MAX_PATH]);
__uint(max_entries, 1024);
} process_map SEC(".maps");
} command_map SEC(".maps");

// Ringbuffer for process events.
// Ring-buffer for process_info_t.
struct
{
__uint(type, BPF_MAP_TYPE_RINGBUF);
Expand All @@ -61,26 +65,29 @@ SEC("process")
int
ProcessMonitor(process_md_t* ctx)
{
process_info_t process_info = {
.process_id = ctx->process_id,
.parent_process_id = ctx->parent_process_id,
.creating_process_id = ctx->creating_process_id,
.creating_thread_id = ctx->creating_thread_id,
.operation = ctx->operation,
};

if (ctx->operation == PROCESS_OPERATION_CREATE) {
process_create_event_t create_event;
__builtin_memset(&create_event, 0, sizeof(create_event));
create_event.entry.parent_process_id = ctx->parent_process_id;
create_event.process_id = ctx->process_id;
uint64_t process_id = ctx->process_id;
uint8_t buffer[MAX_PATH];

memset(buffer, sizeof(buffer), 0);

memcpy_s(buffer, sizeof(buffer), ctx->command_start, ctx->command_end - ctx->command_start);
bpf_map_update_elem(&command_map, &process_info.process_id, buffer, BPF_ANY);

memcpy_s(
create_event.entry.command_line,
sizeof(create_event.entry.command_line),
ctx->command_start,
(uint32_t)(ctx->command_end - ctx->command_start));
// Reset the buffer.
memset(buffer, sizeof(buffer), 0);

bpf_map_update_elem(&process_map, &process_id, &create_event.entry, BPF_ANY);
bpf_ringbuf_output(&process_ringbuf, &create_event, sizeof(create_event), 0);
} else if (ctx->operation == PROCESS_OPERATION_DELETE) {
process_delete_event_t delete_event = {.process_id = ctx->process_id};
uint64_t process_id = ctx->process_id;
bpf_map_delete_elem(&process_map, &process_id);
bpf_ringbuf_output(&process_ringbuf, &delete_event, sizeof(delete_event), 0);
// Copy image path into the LRU hash.
bpf_process_get_image_path(ctx, buffer, sizeof(buffer));
bpf_map_update_elem(&process_map, &process_info.process_id, buffer, BPF_ANY);
}
bpf_ringbuf_output(&process_ringbuf, &process_info, sizeof(process_info), 0);
return 0;
}
31 changes: 19 additions & 12 deletions tests/unit/libbpf_test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3424,7 +3424,9 @@ _process_hook_test(ebpf_execution_type_t execution_type)
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_PROCESS, EBPF_ATTACH_TYPE_PROCESS);
REQUIRE(hook.initialize() == EBPF_SUCCESS);
program_info_provider_t sample_program_info;
REQUIRE(sample_program_info.initialize(EBPF_PROGRAM_TYPE_PROCESS) == EBPF_SUCCESS);
REQUIRE(
sample_program_info.initialize(EBPF_PROGRAM_TYPE_PROCESS, &_test_process_program_info_provider_data) ==
EBPF_SUCCESS);

const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? dll_name : obj_name);
struct bpf_object* process_object = bpf_object__open(file_name);
Expand All @@ -3439,6 +3441,9 @@ _process_hook_test(ebpf_execution_type_t execution_type)
struct bpf_map* process_map = bpf_object__find_map_by_name(process_object, "process_map");
REQUIRE(process_map != nullptr);

struct bpf_map* command_map = bpf_object__find_map_by_name(process_object, "command_map");
REQUIRE(command_map != nullptr);

bpf_link_ptr link(bpf_program__attach(caller));
REQUIRE(link != nullptr);

Expand All @@ -3447,27 +3452,29 @@ _process_hook_test(ebpf_execution_type_t execution_type)
ctx.process_id = 1234;
ctx.operation = PROCESS_OPERATION_CREATE;
ctx.parent_process_id = 5678;
ctx.command_start = (uint8_t*)"test_process";
ctx.command_start = (uint8_t*)"notepad foo.bar.txt";
ctx.command_end = ctx.command_start + strlen((char*)ctx.command_start);

uint32_t result;
REQUIRE(hook.fire(&ctx, &result) == EBPF_SUCCESS);

// Check if the entry was added to the map.
uint64_t key = 1234;
proces_entry_t value;
REQUIRE(bpf_map_lookup_elem(bpf_map__fd(process_map), &key, &value) == 0);
uint8_t value[512] = {0};
bpf_map_lookup_elem(bpf_map__fd(command_map), &key, &value);

// Verify the entry.
REQUIRE(value.parent_process_id == 5678);
REQUIRE(strcmp((char*)value.command_line, "test_process") == 0);
std::string returned_command = (char*)value;

// Test process termination.
ctx.operation = PROCESS_OPERATION_DELETE;
REQUIRE(hook.fire(&ctx, &result) == EBPF_SUCCESS);
// Verify the result.
REQUIRE(returned_command == "notepad foo.bar.txt");

// Check if the entry was removed from the map.
REQUIRE(bpf_map_lookup_elem(bpf_map__fd(process_map), &key, &value) != 0);
// Get the image path.
bpf_map_lookup_elem(bpf_map__fd(process_map), &key, &value);

returned_command = (char*)value;

// Verify the result.
REQUIRE(returned_command == "C:\\Windows\\System32\\notepad.exe");

result = bpf_link__destroy(link.release());
REQUIRE(result == 0);
Expand Down
Loading

0 comments on commit c57dc57

Please sign in to comment.