Enable leak_detection for "fault_injection" test case. (#2192)
* fix leaks * update cicd * fix tests * fix * fix * fix * add sal
This commit is contained in:
Родитель
282134fc34
Коммит
aec1c4060c
|
@ -363,6 +363,7 @@ jobs:
|
||||||
code_coverage: true
|
code_coverage: true
|
||||||
gather_dumps: true
|
gather_dumps: true
|
||||||
fault_injection: true
|
fault_injection: true
|
||||||
|
leak_detection: true
|
||||||
|
|
||||||
# Run the low memory simulator for netebpfext_unit tests.
|
# Run the low memory simulator for netebpfext_unit tests.
|
||||||
fault_injection_netebpfext_unit:
|
fault_injection_netebpfext_unit:
|
||||||
|
@ -402,6 +403,7 @@ jobs:
|
||||||
code_coverage: false
|
code_coverage: false
|
||||||
gather_dumps: true
|
gather_dumps: true
|
||||||
fault_injection: true
|
fault_injection: true
|
||||||
|
leak_detection: true
|
||||||
|
|
||||||
# Run the complete fault injection simulator for netebpfext in GitHub.
|
# Run the complete fault injection simulator for netebpfext in GitHub.
|
||||||
# Runs on a schedule as this takes a long time to run.
|
# Runs on a schedule as this takes a long time to run.
|
||||||
|
|
|
@ -391,11 +391,12 @@ ebpf_api_elf_enumerate_sections(
|
||||||
|
|
||||||
*infos = nullptr;
|
*infos = nullptr;
|
||||||
*error_message = nullptr;
|
*error_message = nullptr;
|
||||||
|
ebpf_section_info_t* info = nullptr;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
auto raw_programs = read_elf(file, section ? std::string(section) : std::string(), &verifier_options, platform);
|
auto raw_programs = read_elf(file, section ? std::string(section) : std::string(), &verifier_options, platform);
|
||||||
for (const auto& raw_program : raw_programs) {
|
for (const auto& raw_program : raw_programs) {
|
||||||
ebpf_section_info_t* info = (ebpf_section_info_t*)ebpf_allocate(sizeof(*info));
|
info = (ebpf_section_info_t*)ebpf_allocate(sizeof(*info));
|
||||||
if (info == nullptr) {
|
if (info == nullptr) {
|
||||||
throw std::runtime_error("Out of memory");
|
throw std::runtime_error("Out of memory");
|
||||||
}
|
}
|
||||||
|
@ -418,24 +419,29 @@ ebpf_api_elf_enumerate_sections(
|
||||||
}
|
}
|
||||||
|
|
||||||
info->section_name = ebpf_duplicate_string(raw_program.section.c_str());
|
info->section_name = ebpf_duplicate_string(raw_program.section.c_str());
|
||||||
|
if (info->section_name == nullptr) {
|
||||||
|
throw std::runtime_error("Out of memory");
|
||||||
|
}
|
||||||
info->program_type_name = ebpf_duplicate_string(raw_program.info.type.name.c_str());
|
info->program_type_name = ebpf_duplicate_string(raw_program.info.type.name.c_str());
|
||||||
|
if (info->program_type_name == nullptr) {
|
||||||
|
throw std::runtime_error("Out of memory");
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<uint8_t> raw_data = convert_ebpf_program_to_bytes(raw_program.prog);
|
std::vector<uint8_t> raw_data = convert_ebpf_program_to_bytes(raw_program.prog);
|
||||||
info->raw_data_size = raw_data.size();
|
info->raw_data_size = raw_data.size();
|
||||||
info->raw_data = (char*)ebpf_allocate(info->raw_data_size);
|
info->raw_data = (char*)ebpf_allocate(info->raw_data_size);
|
||||||
if (info->raw_data == nullptr || info->section_name == nullptr || info->program_type_name == nullptr) {
|
if (info->raw_data == nullptr) {
|
||||||
ebpf_free((void*)info->section_name);
|
|
||||||
ebpf_free((void*)info->program_type_name);
|
|
||||||
ebpf_free((void*)info->raw_data);
|
|
||||||
ebpf_free(info);
|
|
||||||
throw std::runtime_error("Out of memory");
|
throw std::runtime_error("Out of memory");
|
||||||
}
|
}
|
||||||
memcpy(info->raw_data, raw_data.data(), info->raw_data_size);
|
memcpy(info->raw_data, raw_data.data(), info->raw_data_size);
|
||||||
|
|
||||||
info->next = *infos;
|
info->next = *infos;
|
||||||
*infos = info;
|
*infos = info;
|
||||||
|
info = nullptr;
|
||||||
}
|
}
|
||||||
} catch (std::runtime_error e) {
|
} catch (std::runtime_error e) {
|
||||||
|
ebpf_free_sections(*infos);
|
||||||
|
ebpf_free_sections(info);
|
||||||
str << "error: " << e.what();
|
str << "error: " << e.what();
|
||||||
*error_message = allocate_string(str.str());
|
*error_message = allocate_string(str.str());
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -15,6 +15,19 @@
|
||||||
|
|
||||||
#define PAGE_SIZE 4096
|
#define PAGE_SIZE 4096
|
||||||
|
|
||||||
|
typedef struct _free_trampoline_table
|
||||||
|
{
|
||||||
|
void
|
||||||
|
operator()(_In_opt_ _Post_invalid_ ebpf_trampoline_table_t* table)
|
||||||
|
{
|
||||||
|
if (table != nullptr) {
|
||||||
|
ebpf_free_trampoline_table(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} free_trampoline_table_t;
|
||||||
|
|
||||||
|
typedef std::unique_ptr<ebpf_trampoline_table_t, free_trampoline_table_t> ebpf_trampoline_table_ptr;
|
||||||
|
|
||||||
typedef class _ebpf_async_wrapper
|
typedef class _ebpf_async_wrapper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -680,7 +693,7 @@ TEST_CASE("program", "[execution_context]")
|
||||||
REQUIRE(ebpf_program_associate_maps(program.get(), maps, EBPF_COUNT_OF(maps)) == EBPF_SUCCESS);
|
REQUIRE(ebpf_program_associate_maps(program.get(), maps, EBPF_COUNT_OF(maps)) == EBPF_SUCCESS);
|
||||||
REQUIRE(((ebpf_core_object_t*)map.get())->base.reference_count == 2);
|
REQUIRE(((ebpf_core_object_t*)map.get())->base.reference_count == 2);
|
||||||
|
|
||||||
ebpf_trampoline_table_t* table = NULL;
|
ebpf_trampoline_table_ptr table;
|
||||||
ebpf_result_t (*test_function)();
|
ebpf_result_t (*test_function)();
|
||||||
auto provider_function1 = []() { return (ebpf_result_t)TEST_FUNCTION_RETURN; };
|
auto provider_function1 = []() { return (ebpf_result_t)TEST_FUNCTION_RETURN; };
|
||||||
ebpf_result_t (*function_pointer1)() = provider_function1;
|
ebpf_result_t (*function_pointer1)() = provider_function1;
|
||||||
|
@ -689,13 +702,19 @@ TEST_CASE("program", "[execution_context]")
|
||||||
ebpf_helper_function_addresses_t helper_function_addresses = {
|
ebpf_helper_function_addresses_t helper_function_addresses = {
|
||||||
EBPF_COUNT_OF(helper_functions), (uint64_t*)helper_functions};
|
EBPF_COUNT_OF(helper_functions), (uint64_t*)helper_functions};
|
||||||
|
|
||||||
REQUIRE(ebpf_allocate_trampoline_table(1, &table) == EBPF_SUCCESS);
|
{
|
||||||
|
ebpf_trampoline_table_t* local_table = nullptr;
|
||||||
|
REQUIRE(ebpf_allocate_trampoline_table(1, &local_table) == EBPF_SUCCESS);
|
||||||
|
table.reset(local_table);
|
||||||
|
}
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
ebpf_update_trampoline_table(
|
ebpf_update_trampoline_table(
|
||||||
table, EBPF_COUNT_OF(test_function_ids), test_function_ids, &helper_function_addresses) == EBPF_SUCCESS);
|
table.get(), EBPF_COUNT_OF(test_function_ids), test_function_ids, &helper_function_addresses) ==
|
||||||
|
EBPF_SUCCESS);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
ebpf_get_trampoline_function(
|
ebpf_get_trampoline_function(
|
||||||
table, EBPF_MAX_GENERAL_HELPER_FUNCTION + 1, reinterpret_cast<void**>(&test_function)) == EBPF_SUCCESS);
|
table.get(), EBPF_MAX_GENERAL_HELPER_FUNCTION + 1, reinterpret_cast<void**>(&test_function)) ==
|
||||||
|
EBPF_SUCCESS);
|
||||||
|
|
||||||
// Size of the actual function is unknown, but we know the allocation is on page granularity.
|
// Size of the actual function is unknown, but we know the allocation is on page granularity.
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
|
@ -800,7 +819,7 @@ TEST_CASE("program", "[execution_context]")
|
||||||
|
|
||||||
link.reset();
|
link.reset();
|
||||||
|
|
||||||
ebpf_free_trampoline_table(table);
|
ebpf_free_trampoline_table(table.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("name size", "[execution_context]")
|
TEST_CASE("name size", "[execution_context]")
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
#include "ebpf_ring_buffer.h"
|
#include "ebpf_ring_buffer.h"
|
||||||
#include "ebpf_serialize.h"
|
#include "ebpf_serialize.h"
|
||||||
#include "ebpf_state.h"
|
#include "ebpf_state.h"
|
||||||
|
#include "helpers.h"
|
||||||
|
|
||||||
#include <winsock2.h>
|
#include <winsock2.h>
|
||||||
#include <Windows.h>
|
#include <Windows.h>
|
||||||
|
@ -25,6 +26,19 @@
|
||||||
extern ebpf_helper_function_prototype_t* ebpf_core_helper_function_prototype;
|
extern ebpf_helper_function_prototype_t* ebpf_core_helper_function_prototype;
|
||||||
extern uint32_t ebpf_core_helper_functions_count;
|
extern uint32_t ebpf_core_helper_functions_count;
|
||||||
|
|
||||||
|
typedef struct _free_ebpf_pinning_table
|
||||||
|
{
|
||||||
|
void
|
||||||
|
operator()(_In_opt_ _Post_invalid_ ebpf_pinning_table_t* table)
|
||||||
|
{
|
||||||
|
if (table != nullptr) {
|
||||||
|
ebpf_pinning_table_free(table);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} free_ebpf_pinning_table_t;
|
||||||
|
|
||||||
|
typedef std::unique_ptr<ebpf_pinning_table_t, free_ebpf_pinning_table_t> ebpf_pinning_table_ptr;
|
||||||
|
|
||||||
class _test_helper
|
class _test_helper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -276,21 +290,25 @@ TEST_CASE("pinning_test", "[platform]")
|
||||||
ebpf_object_initialize(
|
ebpf_object_initialize(
|
||||||
&another_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS);
|
&another_object.object, EBPF_OBJECT_MAP, [](ebpf_core_object_t*) {}, NULL) == EBPF_SUCCESS);
|
||||||
|
|
||||||
ebpf_pinning_table_t* pinning_table = nullptr;
|
ebpf_pinning_table_ptr pinning_table;
|
||||||
REQUIRE(ebpf_pinning_table_allocate(&pinning_table) == EBPF_SUCCESS);
|
{
|
||||||
|
ebpf_pinning_table_t* local_pinning_table = nullptr;
|
||||||
|
REQUIRE(ebpf_pinning_table_allocate(&local_pinning_table) == EBPF_SUCCESS);
|
||||||
|
pinning_table.reset(local_pinning_table);
|
||||||
|
}
|
||||||
|
|
||||||
REQUIRE(ebpf_pinning_table_insert(pinning_table, &foo, &an_object.object) == EBPF_SUCCESS);
|
REQUIRE(ebpf_pinning_table_insert(pinning_table.get(), &foo, &an_object.object) == EBPF_SUCCESS);
|
||||||
REQUIRE(an_object.object.base.reference_count == 2);
|
REQUIRE(an_object.object.base.reference_count == 2);
|
||||||
REQUIRE(ebpf_pinning_table_insert(pinning_table, &bar, &another_object.object) == EBPF_SUCCESS);
|
REQUIRE(ebpf_pinning_table_insert(pinning_table.get(), &bar, &another_object.object) == EBPF_SUCCESS);
|
||||||
REQUIRE(another_object.object.base.reference_count == 2);
|
REQUIRE(another_object.object.base.reference_count == 2);
|
||||||
REQUIRE(ebpf_pinning_table_find(pinning_table, &foo, (ebpf_core_object_t**)&some_object) == EBPF_SUCCESS);
|
REQUIRE(ebpf_pinning_table_find(pinning_table.get(), &foo, (ebpf_core_object_t**)&some_object) == EBPF_SUCCESS);
|
||||||
REQUIRE(an_object.object.base.reference_count == 3);
|
REQUIRE(an_object.object.base.reference_count == 3);
|
||||||
REQUIRE(some_object == &an_object);
|
REQUIRE(some_object == &an_object);
|
||||||
ebpf_object_release_reference(&some_object->object);
|
ebpf_object_release_reference(&some_object->object);
|
||||||
REQUIRE(ebpf_pinning_table_delete(pinning_table, &foo) == EBPF_SUCCESS);
|
REQUIRE(ebpf_pinning_table_delete(pinning_table.get(), &foo) == EBPF_SUCCESS);
|
||||||
REQUIRE(another_object.object.base.reference_count == 2);
|
REQUIRE(another_object.object.base.reference_count == 2);
|
||||||
|
|
||||||
ebpf_pinning_table_free(pinning_table);
|
ebpf_pinning_table_free(pinning_table.release());
|
||||||
REQUIRE(an_object.object.base.reference_count == 1);
|
REQUIRE(an_object.object.base.reference_count == 1);
|
||||||
REQUIRE(another_object.object.base.reference_count == 1);
|
REQUIRE(another_object.object.base.reference_count == 1);
|
||||||
|
|
||||||
|
@ -457,6 +475,7 @@ TEST_CASE("extension_test", "[platform]")
|
||||||
ebpf_extension_data_t client_data{};
|
ebpf_extension_data_t client_data{};
|
||||||
ebpf_extension_data_t provider_data{};
|
ebpf_extension_data_t provider_data{};
|
||||||
GUID interface_id;
|
GUID interface_id;
|
||||||
|
ebpf_result_t result;
|
||||||
|
|
||||||
const ebpf_extension_dispatch_table_t* returned_provider_dispatch_table;
|
const ebpf_extension_dispatch_table_t* returned_provider_dispatch_table;
|
||||||
const ebpf_extension_data_t* returned_provider_data;
|
const ebpf_extension_data_t* returned_provider_data;
|
||||||
|
@ -485,8 +504,7 @@ TEST_CASE("extension_test", "[platform]")
|
||||||
(NPI_PROVIDER_DETACH_CLIENT_FN*)test_provider_detach_client,
|
(NPI_PROVIDER_DETACH_CLIENT_FN*)test_provider_detach_client,
|
||||||
nullptr) == EBPF_SUCCESS);
|
nullptr) == EBPF_SUCCESS);
|
||||||
|
|
||||||
REQUIRE(
|
result = ebpf_extension_load(
|
||||||
ebpf_extension_load(
|
|
||||||
&client_context,
|
&client_context,
|
||||||
&interface_id,
|
&interface_id,
|
||||||
&provider_module_id,
|
&provider_module_id,
|
||||||
|
@ -497,13 +515,20 @@ TEST_CASE("extension_test", "[platform]")
|
||||||
&provider_binding_context,
|
&provider_binding_context,
|
||||||
&returned_provider_data,
|
&returned_provider_data,
|
||||||
&returned_provider_dispatch_table,
|
&returned_provider_dispatch_table,
|
||||||
nullptr) == EBPF_SUCCESS);
|
nullptr);
|
||||||
|
if (result != EBPF_SUCCESS) {
|
||||||
|
ebpf_provider_unload(provider_context);
|
||||||
|
}
|
||||||
|
REQUIRE(result == EBPF_SUCCESS);
|
||||||
|
|
||||||
REQUIRE(returned_provider_data == &provider_data);
|
REQUIRE(returned_provider_data == &provider_data);
|
||||||
REQUIRE(returned_provider_dispatch_table == &test_provider_dispatch_table);
|
REQUIRE(returned_provider_dispatch_table == &test_provider_dispatch_table);
|
||||||
|
|
||||||
ebpf_extension_unload(client_context);
|
ebpf_extension_unload(client_context);
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable : 6001) // Using uninitialized memory 'provider_context'.
|
||||||
ebpf_provider_unload(provider_context);
|
ebpf_provider_unload(provider_context);
|
||||||
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("trampoline_test", "[platform]")
|
TEST_CASE("trampoline_test", "[platform]")
|
||||||
|
@ -619,10 +644,10 @@ TEST_CASE("serialize_map_test", "[platform]")
|
||||||
std::string pin_path_prefix = "\\ebpf\\map\\";
|
std::string pin_path_prefix = "\\ebpf\\map\\";
|
||||||
std::vector<std::string> pin_paths;
|
std::vector<std::string> pin_paths;
|
||||||
size_t buffer_length = 0;
|
size_t buffer_length = 0;
|
||||||
uint8_t* buffer = nullptr;
|
|
||||||
size_t required_length;
|
size_t required_length;
|
||||||
size_t serialized_length;
|
size_t serialized_length;
|
||||||
ebpf_map_info_t* map_info_array;
|
ebpf_map_info_t* map_info_array;
|
||||||
|
ebpf_memory_t unique_buffer;
|
||||||
|
|
||||||
// Construct the array of ebpf_map_info_internal_t to be serialized.
|
// Construct the array of ebpf_map_info_internal_t to be serialized.
|
||||||
for (int i = 0; i < map_count; i++) {
|
for (int i = 0; i < map_count; i++) {
|
||||||
|
@ -643,24 +668,31 @@ TEST_CASE("serialize_map_test", "[platform]")
|
||||||
// Serialize.
|
// Serialize.
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
ebpf_serialize_internal_map_info_array(
|
ebpf_serialize_internal_map_info_array(
|
||||||
map_count, internal_map_info_array, buffer, buffer_length, &serialized_length, &required_length) ==
|
map_count, internal_map_info_array, nullptr, buffer_length, &serialized_length, &required_length) ==
|
||||||
EBPF_INSUFFICIENT_BUFFER);
|
EBPF_INSUFFICIENT_BUFFER);
|
||||||
|
|
||||||
buffer = static_cast<uint8_t*>(ebpf_allocate(required_length));
|
{
|
||||||
// Required to deal with code analysis warning about buffer not being checked for null.
|
uint8_t* buffer = static_cast<uint8_t*>(ebpf_allocate(required_length));
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
return;
|
}
|
||||||
|
unique_buffer.reset(buffer);
|
||||||
}
|
}
|
||||||
buffer_length = required_length;
|
buffer_length = required_length;
|
||||||
|
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
ebpf_serialize_internal_map_info_array(
|
ebpf_serialize_internal_map_info_array(
|
||||||
map_count, internal_map_info_array, buffer, buffer_length, &serialized_length, &required_length) ==
|
map_count,
|
||||||
EBPF_SUCCESS);
|
internal_map_info_array,
|
||||||
|
unique_buffer.get(),
|
||||||
|
buffer_length,
|
||||||
|
&serialized_length,
|
||||||
|
&required_length) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// Deserialize.
|
// Deserialize.
|
||||||
REQUIRE(ebpf_deserialize_map_info_array(serialized_length, buffer, map_count, &map_info_array) == EBPF_SUCCESS);
|
REQUIRE(
|
||||||
|
ebpf_deserialize_map_info_array(serialized_length, unique_buffer.get(), map_count, &map_info_array) ==
|
||||||
|
EBPF_SUCCESS);
|
||||||
_Analysis_assume_(map_info_array != nullptr);
|
_Analysis_assume_(map_info_array != nullptr);
|
||||||
// Verify de-serialized map info array matches input.
|
// Verify de-serialized map info array matches input.
|
||||||
for (int i = 0; i < map_count; i++) {
|
for (int i = 0; i < map_count; i++) {
|
||||||
|
@ -674,8 +706,6 @@ TEST_CASE("serialize_map_test", "[platform]")
|
||||||
|
|
||||||
// Free de-serialized map info array.
|
// Free de-serialized map info array.
|
||||||
ebpf_map_info_array_free(map_count, map_info_array);
|
ebpf_map_info_array_free(map_count, map_info_array);
|
||||||
|
|
||||||
ebpf_free(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("serialize_program_info_test", "[platform]")
|
TEST_CASE("serialize_program_info_test", "[platform]")
|
||||||
|
@ -699,29 +729,32 @@ TEST_CASE("serialize_program_info_test", "[platform]")
|
||||||
ebpf_program_info_t in_program_info = {program_type, EBPF_COUNT_OF(helper_prototype), helper_prototype};
|
ebpf_program_info_t in_program_info = {program_type, EBPF_COUNT_OF(helper_prototype), helper_prototype};
|
||||||
|
|
||||||
size_t buffer_length = 0;
|
size_t buffer_length = 0;
|
||||||
uint8_t* buffer = nullptr;
|
|
||||||
size_t required_length;
|
size_t required_length;
|
||||||
size_t serialized_length;
|
size_t serialized_length;
|
||||||
|
ebpf_memory_t unique_buffer;
|
||||||
|
|
||||||
ebpf_program_info_t* out_program_info;
|
ebpf_program_info_t* out_program_info;
|
||||||
|
|
||||||
// Serialize.
|
// Serialize.
|
||||||
REQUIRE(ebpf_serialize_program_info(&in_program_info, buffer, buffer_length, &serialized_length, &required_length));
|
REQUIRE(
|
||||||
|
ebpf_serialize_program_info(&in_program_info, nullptr, buffer_length, &serialized_length, &required_length));
|
||||||
|
|
||||||
buffer = static_cast<uint8_t*>(ebpf_allocate(required_length));
|
{
|
||||||
// Work around code analysis warning about buffer not being checked for null.
|
uint8_t* buffer = static_cast<uint8_t*>(ebpf_allocate(required_length));
|
||||||
if (buffer == nullptr) {
|
if (buffer == nullptr) {
|
||||||
REQUIRE(false);
|
REQUIRE(false);
|
||||||
return;
|
}
|
||||||
|
unique_buffer.reset(buffer);
|
||||||
}
|
}
|
||||||
buffer_length = required_length;
|
buffer_length = required_length;
|
||||||
|
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
ebpf_serialize_program_info(&in_program_info, buffer, buffer_length, &serialized_length, &required_length) ==
|
ebpf_serialize_program_info(
|
||||||
|
&in_program_info, unique_buffer.get(), buffer_length, &serialized_length, &required_length) ==
|
||||||
EBPF_SUCCESS);
|
EBPF_SUCCESS);
|
||||||
|
|
||||||
// Deserialize.
|
// Deserialize.
|
||||||
REQUIRE(ebpf_deserialize_program_info(serialized_length, buffer, &out_program_info) == EBPF_SUCCESS);
|
REQUIRE(ebpf_deserialize_program_info(serialized_length, unique_buffer.get(), &out_program_info) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// Verify de-serialized program info matches input.
|
// Verify de-serialized program info matches input.
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
|
@ -757,8 +790,6 @@ TEST_CASE("serialize_program_info_test", "[platform]")
|
||||||
|
|
||||||
// Free de-serialized program info.
|
// Free de-serialized program info.
|
||||||
ebpf_program_info_free(out_program_info);
|
ebpf_program_info_free(out_program_info);
|
||||||
|
|
||||||
ebpf_free(buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("state_test", "[state]")
|
TEST_CASE("state_test", "[state]")
|
||||||
|
|
|
@ -64,6 +64,19 @@ CATCH_REGISTER_LISTENER(_passed_test_log)
|
||||||
|
|
||||||
extern thread_local bool ebpf_non_preemptible;
|
extern thread_local bool ebpf_non_preemptible;
|
||||||
|
|
||||||
|
typedef struct _close_bpf_object
|
||||||
|
{
|
||||||
|
void
|
||||||
|
operator()(_In_opt_ _Post_invalid_ bpf_object* object)
|
||||||
|
{
|
||||||
|
if (object != nullptr) {
|
||||||
|
bpf_object__close(object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} close_bpf_object_t;
|
||||||
|
|
||||||
|
typedef std::unique_ptr<bpf_object, close_bpf_object_t> bpf_object_ptr;
|
||||||
|
|
||||||
std::vector<uint8_t>
|
std::vector<uint8_t>
|
||||||
prepare_ip_packet(uint16_t ethernet_type)
|
prepare_ip_packet(uint16_t ethernet_type)
|
||||||
{
|
{
|
||||||
|
@ -330,16 +343,17 @@ ebpf_program_load(
|
||||||
_In_z_ const char* file_name,
|
_In_z_ const char* file_name,
|
||||||
bpf_prog_type prog_type,
|
bpf_prog_type prog_type,
|
||||||
ebpf_execution_type_t execution_type,
|
ebpf_execution_type_t execution_type,
|
||||||
_Outptr_result_maybenull_ struct bpf_object** object,
|
_Out_ bpf_object_ptr* unique_object,
|
||||||
_Out_ fd_t* program_fd,
|
_Out_ fd_t* program_fd,
|
||||||
_Outptr_opt_result_maybenull_z_ const char** log_buffer)
|
_Outptr_opt_result_maybenull_z_ const char** log_buffer)
|
||||||
{
|
{
|
||||||
*object = nullptr;
|
|
||||||
*program_fd = ebpf_fd_invalid;
|
*program_fd = ebpf_fd_invalid;
|
||||||
if (log_buffer) {
|
if (log_buffer) {
|
||||||
*log_buffer = nullptr;
|
*log_buffer = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unique_object->reset(nullptr);
|
||||||
|
|
||||||
bpf_object* new_object = bpf_object__open(file_name);
|
bpf_object* new_object = bpf_object__open(file_name);
|
||||||
if (new_object == nullptr) {
|
if (new_object == nullptr) {
|
||||||
return -errno;
|
return -errno;
|
||||||
|
@ -365,7 +379,7 @@ ebpf_program_load(
|
||||||
}
|
}
|
||||||
|
|
||||||
*program_fd = bpf_program__fd(program);
|
*program_fd = bpf_program__fd(program);
|
||||||
*object = new_object;
|
unique_object->reset(new_object);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -376,26 +390,26 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
bpf_link* link;
|
bpf_link_ptr link;
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
|
||||||
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "droppacket_um.dll" : "droppacket.o");
|
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "droppacket_um.dll" : "droppacket.o");
|
||||||
|
result =
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
ebpf_free((void*)error_message);
|
ebpf_free((void*)error_message);
|
||||||
}
|
}
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
fd_t dropped_packet_map_fd = bpf_object__find_map_fd_by_name(object, "dropped_packet_map");
|
fd_t dropped_packet_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "dropped_packet_map");
|
||||||
|
|
||||||
// Tell the program which interface to filter on.
|
// Tell the program which interface to filter on.
|
||||||
fd_t interface_index_map_fd = bpf_object__find_map_fd_by_name(object, "interface_index_map");
|
fd_t interface_index_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "interface_index_map");
|
||||||
uint32_t key = 0;
|
uint32_t key = 0;
|
||||||
uint32_t if_index = TEST_IFINDEX;
|
uint32_t if_index = TEST_IFINDEX;
|
||||||
REQUIRE(bpf_map_update_elem(interface_index_map_fd, &key, &if_index, EBPF_ANY) == EBPF_SUCCESS);
|
REQUIRE(bpf_map_update_elem(interface_index_map_fd, &key, &if_index, EBPF_ANY) == EBPF_SUCCESS);
|
||||||
|
@ -436,8 +450,7 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
||||||
REQUIRE(value == 0);
|
REQUIRE(value == 0);
|
||||||
|
|
||||||
// Reattach to all interfaces so we can test the ingress_ifindex field passed to the program.
|
// Reattach to all interfaces so we can test the ingress_ifindex field passed to the program.
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
if_index = 0;
|
if_index = 0;
|
||||||
REQUIRE(hook.attach_link(program_fd, &if_index, sizeof(if_index), &link) == EBPF_SUCCESS);
|
REQUIRE(hook.attach_link(program_fd, &if_index, sizeof(if_index), &link) == EBPF_SUCCESS);
|
||||||
|
|
||||||
|
@ -478,10 +491,9 @@ droppacket_test(ebpf_execution_type_t execution_type)
|
||||||
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
REQUIRE(bpf_map_lookup_elem(dropped_packet_map_fd, &key, &value) == EBPF_SUCCESS);
|
||||||
REQUIRE(value == 0);
|
REQUIRE(value == 0);
|
||||||
|
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// See also divide_by_zero_test_km in api_test.cpp for the kernel-mode equivalent.
|
// See also divide_by_zero_test_km in api_test.cpp for the kernel-mode equivalent.
|
||||||
|
@ -492,17 +504,16 @@ divide_by_zero_test_um(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
bpf_link* link;
|
bpf_link_ptr link;
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
|
||||||
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "divide_by_zero_um.dll" : "divide_by_zero.o");
|
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "divide_by_zero_um.dll" : "divide_by_zero.o");
|
||||||
|
result =
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
ebpf_free((void*)error_message);
|
ebpf_free((void*)error_message);
|
||||||
|
@ -522,10 +533,9 @@ divide_by_zero_test_um(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
REQUIRE(hook_result == 0);
|
REQUIRE(hook_result == 0);
|
||||||
|
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -535,7 +545,7 @@ bad_map_name_um(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||||
|
@ -543,7 +553,8 @@ bad_map_name_um(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "bad_map_name_um.dll" : "bad_map_name.o");
|
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "bad_map_name_um.dll" : "bad_map_name.o");
|
||||||
|
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
result =
|
||||||
|
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -551,7 +562,7 @@ bad_map_name_um(ebpf_execution_type_t execution_type)
|
||||||
}
|
}
|
||||||
REQUIRE(result == -EINVAL);
|
REQUIRE(result == -EINVAL);
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct _process_entry
|
typedef struct _process_entry
|
||||||
|
@ -638,8 +649,8 @@ bindmonitor_test(ebpf_execution_type_t execution_type)
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
uint64_t fake_pid = 12345;
|
uint64_t fake_pid = 12345;
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
uint64_t process_id = _get_current_pid_tgid();
|
uint64_t process_id = _get_current_pid_tgid();
|
||||||
|
|
||||||
|
@ -650,18 +661,19 @@ bindmonitor_test(ebpf_execution_type_t execution_type)
|
||||||
// bpf2c.exe tool.
|
// bpf2c.exe tool.
|
||||||
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "bindmonitor_um.dll" : "bindmonitor.o");
|
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "bindmonitor_um.dll" : "bindmonitor.o");
|
||||||
|
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
result =
|
||||||
|
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
ebpf_free((void*)error_message);
|
ebpf_free((void*)error_message);
|
||||||
}
|
}
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
fd_t limit_map_fd = bpf_object__find_map_fd_by_name(object, "limits_map");
|
fd_t limit_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "limits_map");
|
||||||
REQUIRE(limit_map_fd > 0);
|
REQUIRE(limit_map_fd > 0);
|
||||||
fd_t process_map_fd = bpf_object__find_map_fd_by_name(object, "process_map");
|
fd_t process_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "process_map");
|
||||||
REQUIRE(process_map_fd > 0);
|
REQUIRE(process_map_fd > 0);
|
||||||
fd_t audit_map_fd = bpf_object__find_map_fd_by_name(object, "audit_map");
|
fd_t audit_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "audit_map");
|
||||||
REQUIRE(audit_map_fd > 0);
|
REQUIRE(audit_map_fd > 0);
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
||||||
|
@ -717,10 +729,9 @@ bindmonitor_test(ebpf_execution_type_t execution_type)
|
||||||
REQUIRE(bpf_map_get_next_key(process_map_fd, &pid, &pid) < 0);
|
REQUIRE(bpf_map_get_next_key(process_map_fd, &pid, &pid) < 0);
|
||||||
REQUIRE(errno == ENOENT);
|
REQUIRE(errno == ENOENT);
|
||||||
|
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -731,38 +742,39 @@ bindmonitor_tailcall_test(ebpf_execution_type_t execution_type)
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
uint64_t fake_pid = 12345;
|
uint64_t fake_pid = 12345;
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
||||||
|
|
||||||
const char* file_name =
|
const char* file_name =
|
||||||
(execution_type == EBPF_EXECUTION_NATIVE ? "bindmonitor_tailcall_um.dll" : "bindmonitor_tailcall.o");
|
(execution_type == EBPF_EXECUTION_NATIVE ? "bindmonitor_tailcall_um.dll" : "bindmonitor_tailcall.o");
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
result =
|
||||||
|
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
ebpf_free((void*)error_message);
|
ebpf_free((void*)error_message);
|
||||||
}
|
}
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
fd_t limit_map_fd = bpf_object__find_map_fd_by_name(object, "limits_map");
|
fd_t limit_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "limits_map");
|
||||||
REQUIRE(limit_map_fd > 0);
|
REQUIRE(limit_map_fd > 0);
|
||||||
fd_t process_map_fd = bpf_object__find_map_fd_by_name(object, "process_map");
|
fd_t process_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "process_map");
|
||||||
REQUIRE(process_map_fd > 0);
|
REQUIRE(process_map_fd > 0);
|
||||||
|
|
||||||
// Set up tail calls.
|
// Set up tail calls.
|
||||||
struct bpf_program* callee0 = bpf_object__find_program_by_name(object, "BindMonitor_Callee0");
|
struct bpf_program* callee0 = bpf_object__find_program_by_name(unique_object.get(), "BindMonitor_Callee0");
|
||||||
REQUIRE(callee0 != nullptr);
|
REQUIRE(callee0 != nullptr);
|
||||||
fd_t callee0_fd = bpf_program__fd(callee0);
|
fd_t callee0_fd = bpf_program__fd(callee0);
|
||||||
REQUIRE(callee0_fd > 0);
|
REQUIRE(callee0_fd > 0);
|
||||||
|
|
||||||
struct bpf_program* callee1 = bpf_object__find_program_by_name(object, "BindMonitor_Callee1");
|
struct bpf_program* callee1 = bpf_object__find_program_by_name(unique_object.get(), "BindMonitor_Callee1");
|
||||||
REQUIRE(callee1 != nullptr);
|
REQUIRE(callee1 != nullptr);
|
||||||
fd_t callee1_fd = bpf_program__fd(callee1);
|
fd_t callee1_fd = bpf_program__fd(callee1);
|
||||||
REQUIRE(callee1_fd > 0);
|
REQUIRE(callee1_fd > 0);
|
||||||
|
|
||||||
fd_t prog_map_fd = bpf_object__find_map_fd_by_name(object, "prog_array_map");
|
fd_t prog_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "prog_array_map");
|
||||||
REQUIRE(prog_map_fd > 0);
|
REQUIRE(prog_map_fd > 0);
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
@ -773,14 +785,14 @@ bindmonitor_tailcall_test(ebpf_execution_type_t execution_type)
|
||||||
// Validate various maps.
|
// Validate various maps.
|
||||||
|
|
||||||
// Validate map-in-maps with "inner_id".
|
// Validate map-in-maps with "inner_id".
|
||||||
struct bpf_map* outer_map = bpf_object__find_map_by_name(object, "dummy_outer_map");
|
struct bpf_map* outer_map = bpf_object__find_map_by_name(unique_object.get(), "dummy_outer_map");
|
||||||
REQUIRE(outer_map != nullptr);
|
REQUIRE(outer_map != nullptr);
|
||||||
|
|
||||||
int outer_map_fd = bpf_map__fd(outer_map);
|
int outer_map_fd = bpf_map__fd(outer_map);
|
||||||
REQUIRE(outer_map_fd > 0);
|
REQUIRE(outer_map_fd > 0);
|
||||||
|
|
||||||
// Validate map-in-maps with "inner_idx".
|
// Validate map-in-maps with "inner_idx".
|
||||||
struct bpf_map* outer_idx_map = bpf_object__find_map_by_name(object, "dummy_outer_idx_map");
|
struct bpf_map* outer_idx_map = bpf_object__find_map_by_name(unique_object.get(), "dummy_outer_idx_map");
|
||||||
REQUIRE(outer_idx_map != nullptr);
|
REQUIRE(outer_idx_map != nullptr);
|
||||||
|
|
||||||
int outer_idx_map_fd = bpf_map__fd(outer_idx_map);
|
int outer_idx_map_fd = bpf_map__fd(outer_idx_map);
|
||||||
|
@ -832,15 +844,14 @@ bindmonitor_tailcall_test(ebpf_execution_type_t execution_type)
|
||||||
REQUIRE(bpf_map_get_next_key(process_map_fd, &pid, &pid) < 0);
|
REQUIRE(bpf_map_get_next_key(process_map_fd, &pid, &pid) < 0);
|
||||||
REQUIRE(errno == ENOENT);
|
REQUIRE(errno == ENOENT);
|
||||||
|
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
index = 0;
|
index = 0;
|
||||||
REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
||||||
index = 1;
|
index = 1;
|
||||||
REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -850,8 +861,8 @@ bindmonitor_ring_buffer_test(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
||||||
|
@ -860,7 +871,8 @@ bindmonitor_ring_buffer_test(ebpf_execution_type_t execution_type)
|
||||||
(execution_type == EBPF_EXECUTION_NATIVE ? "bindmonitor_ringbuf_um.dll" : "bindmonitor_ringbuf.o");
|
(execution_type == EBPF_EXECUTION_NATIVE ? "bindmonitor_ringbuf_um.dll" : "bindmonitor_ringbuf.o");
|
||||||
|
|
||||||
// Load and attach a bind eBPF program that uses a ring buffer map to notify about bind operations.
|
// Load and attach a bind eBPF program that uses a ring buffer map to notify about bind operations.
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
result =
|
||||||
|
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -868,7 +880,7 @@ bindmonitor_ring_buffer_test(ebpf_execution_type_t execution_type)
|
||||||
}
|
}
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
|
|
||||||
fd_t process_map_fd = bpf_object__find_map_fd_by_name(object, "process_map");
|
fd_t process_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "process_map");
|
||||||
REQUIRE(process_map_fd > 0);
|
REQUIRE(process_map_fd > 0);
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_BIND, EBPF_ATTACH_TYPE_BIND);
|
||||||
|
@ -894,10 +906,9 @@ bindmonitor_ring_buffer_test(ebpf_execution_type_t execution_type)
|
||||||
REQUIRE(emulate_bind(invoke, fake_pid + i, fake_app_id.data()) == BIND_PERMIT);
|
REQUIRE(emulate_bind(invoke, fake_pid + i, fake_app_id.data()) == BIND_PERMIT);
|
||||||
});
|
});
|
||||||
|
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -930,16 +941,17 @@ map_test(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
bpf_link* link;
|
bpf_link_ptr link;
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
|
||||||
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "map_um.dll" : "map.o");
|
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "map_um.dll" : "map.o");
|
||||||
|
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_XDP, execution_type, &object, &program_fd, &error_message);
|
result =
|
||||||
|
ebpf_program_load(file_name, BPF_PROG_TYPE_XDP, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -958,10 +970,9 @@ map_test(ebpf_execution_type_t execution_type)
|
||||||
// Program should return 0 if all the map tests pass.
|
// Program should return 0 if all the map tests pass.
|
||||||
REQUIRE(hook_result >= 0);
|
REQUIRE(hook_result >= 0);
|
||||||
|
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
DECLARE_ALL_TEST_CASES("droppacket", "[end_to_end]", droppacket_test);
|
DECLARE_ALL_TEST_CASES("droppacket", "[end_to_end]", droppacket_test);
|
||||||
|
@ -1074,14 +1085,14 @@ _cgroup_load_test(
|
||||||
{
|
{
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
_test_helper_end_to_end test_helper;
|
_test_helper_end_to_end test_helper;
|
||||||
single_instance_hook_t hook(program_type, attach_type);
|
single_instance_hook_t hook(program_type, attach_type);
|
||||||
program_info_provider_t program_info(program_type);
|
program_info_provider_t program_info(program_type);
|
||||||
|
bpf_object_ptr unique_object;
|
||||||
|
|
||||||
result = ebpf_program_load(file, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, &error_message);
|
result = ebpf_program_load(file, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -1090,7 +1101,7 @@ _cgroup_load_test(
|
||||||
|
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
|
|
||||||
bpf_program* program = bpf_object__find_program_by_name(object, name);
|
bpf_program* program = bpf_object__find_program_by_name(unique_object.get(), name);
|
||||||
REQUIRE(program != nullptr);
|
REQUIRE(program != nullptr);
|
||||||
|
|
||||||
uint32_t compartment_id = 0;
|
uint32_t compartment_id = 0;
|
||||||
|
@ -1101,7 +1112,7 @@ _cgroup_load_test(
|
||||||
REQUIRE(hook.attach(program, &compartment_id, sizeof(compartment_id)) == EBPF_SUCCESS);
|
REQUIRE(hook.attach(program, &compartment_id, sizeof(compartment_id)) == EBPF_SUCCESS);
|
||||||
REQUIRE(hook.detach(program_fd, &compartment_id, sizeof(compartment_id)) == EBPF_SUCCESS);
|
REQUIRE(hook.detach(program_fd, &compartment_id, sizeof(compartment_id)) == EBPF_SUCCESS);
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
static void
|
static void
|
||||||
_cgroup_sock_addr_load_test(
|
_cgroup_sock_addr_load_test(
|
||||||
|
@ -1197,7 +1208,7 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
|
||||||
|
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
||||||
|
@ -1206,7 +1217,7 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
|
||||||
SAMPLE_PATH "bindmonitor.o",
|
SAMPLE_PATH "bindmonitor.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
EBPF_EXECUTION_INTERPRET,
|
EBPF_EXECUTION_INTERPRET,
|
||||||
&object,
|
&unique_object,
|
||||||
&program_fd,
|
&program_fd,
|
||||||
&error_message);
|
&error_message);
|
||||||
|
|
||||||
|
@ -1221,11 +1232,14 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
|
||||||
std::string process_maps_name = "bindmonitor::process_map";
|
std::string process_maps_name = "bindmonitor::process_map";
|
||||||
std::string limit_maps_name = "bindmonitor::limits_map";
|
std::string limit_maps_name = "bindmonitor::limits_map";
|
||||||
|
|
||||||
REQUIRE(bpf_object__find_map_by_name(object, "process_map") != nullptr);
|
REQUIRE(bpf_object__find_map_by_name(unique_object.get(), "process_map") != nullptr);
|
||||||
REQUIRE(bpf_object__find_map_by_name(object, "limits_map") != nullptr);
|
REQUIRE(bpf_object__find_map_by_name(unique_object.get(), "limits_map") != nullptr);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
bpf_map__pin(bpf_object__find_map_by_name(object, "process_map"), process_maps_name.c_str()) == EBPF_SUCCESS);
|
bpf_map__pin(bpf_object__find_map_by_name(unique_object.get(), "process_map"), process_maps_name.c_str()) ==
|
||||||
REQUIRE(bpf_map__pin(bpf_object__find_map_by_name(object, "limits_map"), limit_maps_name.c_str()) == EBPF_SUCCESS);
|
EBPF_SUCCESS);
|
||||||
|
REQUIRE(
|
||||||
|
bpf_map__pin(bpf_object__find_map_by_name(unique_object.get(), "limits_map"), limit_maps_name.c_str()) ==
|
||||||
|
EBPF_SUCCESS);
|
||||||
|
|
||||||
fd_t fd = bpf_obj_get(process_maps_name.c_str());
|
fd_t fd = bpf_obj_get(process_maps_name.c_str());
|
||||||
REQUIRE(fd != ebpf_fd_invalid);
|
REQUIRE(fd != ebpf_fd_invalid);
|
||||||
|
@ -1236,15 +1250,17 @@ TEST_CASE("map_pinning_test", "[end_to_end]")
|
||||||
Platform::_close(fd);
|
Platform::_close(fd);
|
||||||
|
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
bpf_map__unpin(bpf_object__find_map_by_name(object, "process_map"), process_maps_name.c_str()) == EBPF_SUCCESS);
|
bpf_map__unpin(bpf_object__find_map_by_name(unique_object.get(), "process_map"), process_maps_name.c_str()) ==
|
||||||
|
EBPF_SUCCESS);
|
||||||
REQUIRE(
|
REQUIRE(
|
||||||
bpf_map__unpin(bpf_object__find_map_by_name(object, "limits_map"), limit_maps_name.c_str()) == EBPF_SUCCESS);
|
bpf_map__unpin(bpf_object__find_map_by_name(unique_object.get(), "limits_map"), limit_maps_name.c_str()) ==
|
||||||
|
EBPF_SUCCESS);
|
||||||
|
|
||||||
REQUIRE(bpf_obj_get(limit_maps_name.c_str()) == ebpf_fd_invalid);
|
REQUIRE(bpf_obj_get(limit_maps_name.c_str()) == ebpf_fd_invalid);
|
||||||
|
|
||||||
REQUIRE(bpf_obj_get(process_maps_name.c_str()) == ebpf_fd_invalid);
|
REQUIRE(bpf_obj_get(process_maps_name.c_str()) == ebpf_fd_invalid);
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
||||||
|
@ -1257,7 +1273,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
||||||
int result;
|
int result;
|
||||||
const char* file_name = nullptr;
|
const char* file_name = nullptr;
|
||||||
const char* section_name = nullptr;
|
const char* section_name = nullptr;
|
||||||
bpf_object* object[2] = {0};
|
bpf_object_ptr unique_object[2];
|
||||||
fd_t program_fds[2] = {0};
|
fd_t program_fds[2] = {0};
|
||||||
|
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
@ -1266,7 +1282,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
||||||
SAMPLE_PATH "droppacket.o",
|
SAMPLE_PATH "droppacket.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
EBPF_EXECUTION_JIT,
|
EBPF_EXECUTION_JIT,
|
||||||
&object[0],
|
&unique_object[0],
|
||||||
&program_fds[0],
|
&program_fds[0],
|
||||||
&error_message);
|
&error_message);
|
||||||
|
|
||||||
|
@ -1280,7 +1296,7 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
||||||
SAMPLE_PATH "droppacket.o",
|
SAMPLE_PATH "droppacket.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
EBPF_EXECUTION_INTERPRET,
|
EBPF_EXECUTION_INTERPRET,
|
||||||
&object[1],
|
&unique_object[1],
|
||||||
&program_fds[1],
|
&program_fds[1],
|
||||||
&error_message);
|
&error_message);
|
||||||
|
|
||||||
|
@ -1322,8 +1338,8 @@ TEST_CASE("enumerate_and_query_programs", "[end_to_end]")
|
||||||
|
|
||||||
REQUIRE(bpf_prog_get_next_id(program_id, &next_program_id) == -ENOENT);
|
REQUIRE(bpf_prog_get_next_id(program_id, &next_program_id) == -ENOENT);
|
||||||
|
|
||||||
for (int i = 0; i < _countof(object); i++) {
|
for (int i = 0; i < _countof(unique_object); i++) {
|
||||||
bpf_object__close(object[i]);
|
bpf_object__close(unique_object[i].release());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1345,7 +1361,7 @@ TEST_CASE("implicit_detach", "[end_to_end]")
|
||||||
_test_helper_end_to_end test_helper;
|
_test_helper_end_to_end test_helper;
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_link* link = nullptr;
|
bpf_link* link = nullptr;
|
||||||
|
@ -1354,7 +1370,12 @@ TEST_CASE("implicit_detach", "[end_to_end]")
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
|
||||||
result = ebpf_program_load(
|
result = ebpf_program_load(
|
||||||
SAMPLE_PATH "droppacket.o", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_JIT, &object, &program_fd, &error_message);
|
SAMPLE_PATH "droppacket.o",
|
||||||
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
|
EBPF_EXECUTION_JIT,
|
||||||
|
&unique_object,
|
||||||
|
&program_fd,
|
||||||
|
&error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -1367,7 +1388,7 @@ TEST_CASE("implicit_detach", "[end_to_end]")
|
||||||
|
|
||||||
// Call bpf_object__close() which will close the program fd. That should
|
// Call bpf_object__close() which will close the program fd. That should
|
||||||
// detach the program from the hook and unload the program.
|
// detach the program from the hook and unload the program.
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
|
|
||||||
uint32_t program_id;
|
uint32_t program_id;
|
||||||
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
||||||
|
@ -1390,7 +1411,7 @@ TEST_CASE("implicit_detach_2", "[end_to_end]")
|
||||||
_test_helper_end_to_end test_helper;
|
_test_helper_end_to_end test_helper;
|
||||||
|
|
||||||
int result = 0;
|
int result = 0;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_link* link = nullptr;
|
bpf_link* link = nullptr;
|
||||||
|
@ -1399,7 +1420,12 @@ TEST_CASE("implicit_detach_2", "[end_to_end]")
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
|
||||||
result = ebpf_program_load(
|
result = ebpf_program_load(
|
||||||
SAMPLE_PATH "droppacket.o", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_JIT, &object, &program_fd, &error_message);
|
SAMPLE_PATH "droppacket.o",
|
||||||
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
|
EBPF_EXECUTION_JIT,
|
||||||
|
&unique_object,
|
||||||
|
&program_fd,
|
||||||
|
&error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -1412,7 +1438,7 @@ TEST_CASE("implicit_detach_2", "[end_to_end]")
|
||||||
|
|
||||||
// Call bpf_object__close() which will close the program fd. That should
|
// Call bpf_object__close() which will close the program fd. That should
|
||||||
// detach the program from the hook and unload the program.
|
// detach the program from the hook and unload the program.
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
|
|
||||||
uint32_t program_id;
|
uint32_t program_id;
|
||||||
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
||||||
|
@ -1433,9 +1459,9 @@ TEST_CASE("explicit_detach", "[end_to_end]")
|
||||||
|
|
||||||
_test_helper_end_to_end test_helper;
|
_test_helper_end_to_end test_helper;
|
||||||
|
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
|
|
||||||
|
@ -1446,7 +1472,7 @@ TEST_CASE("explicit_detach", "[end_to_end]")
|
||||||
SAMPLE_PATH "droppacket.o",
|
SAMPLE_PATH "droppacket.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
EBPF_EXECUTION_INTERPRET,
|
EBPF_EXECUTION_INTERPRET,
|
||||||
&object,
|
&unique_object,
|
||||||
&program_fd,
|
&program_fd,
|
||||||
&error_message);
|
&error_message);
|
||||||
|
|
||||||
|
@ -1462,11 +1488,10 @@ TEST_CASE("explicit_detach", "[end_to_end]")
|
||||||
// Detach and close link handle.
|
// Detach and close link handle.
|
||||||
// ebpf_object_tracking_terminate() which is called when the test
|
// ebpf_object_tracking_terminate() which is called when the test
|
||||||
// exits checks if all the objects in EC have been deleted.
|
// exits checks if all the objects in EC have been deleted.
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
// Close program handle.
|
// Close program handle.
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
uint32_t program_id;
|
uint32_t program_id;
|
||||||
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
||||||
}
|
}
|
||||||
|
@ -1480,9 +1505,9 @@ TEST_CASE("implicit_explicit_detach", "[end_to_end]")
|
||||||
|
|
||||||
_test_helper_end_to_end test_helper;
|
_test_helper_end_to_end test_helper;
|
||||||
|
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
|
|
||||||
|
@ -1493,7 +1518,7 @@ TEST_CASE("implicit_explicit_detach", "[end_to_end]")
|
||||||
SAMPLE_PATH "droppacket.o",
|
SAMPLE_PATH "droppacket.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
EBPF_EXECUTION_INTERPRET,
|
EBPF_EXECUTION_INTERPRET,
|
||||||
&object,
|
&unique_object,
|
||||||
&program_fd,
|
&program_fd,
|
||||||
&error_message);
|
&error_message);
|
||||||
|
|
||||||
|
@ -1508,15 +1533,14 @@ TEST_CASE("implicit_explicit_detach", "[end_to_end]")
|
||||||
|
|
||||||
// Close program handle. That should detach the program from the hook
|
// Close program handle. That should detach the program from the hook
|
||||||
// and unload the program.
|
// and unload the program.
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
uint32_t program_id;
|
uint32_t program_id;
|
||||||
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
REQUIRE(bpf_prog_get_next_id(0, &program_id) == -ENOENT);
|
||||||
|
|
||||||
// Detach and close link handle.
|
// Detach and close link handle.
|
||||||
// ebpf_object_tracking_terminate() which is called when the test
|
// ebpf_object_tracking_terminate() which is called when the test
|
||||||
// exits checks if all the objects in EC have been deleted.
|
// exits checks if all the objects in EC have been deleted.
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("create_map", "[end_to_end]")
|
TEST_CASE("create_map", "[end_to_end]")
|
||||||
|
@ -2094,10 +2118,11 @@ _map_reuse_invalid_test(ebpf_execution_type_t execution_type)
|
||||||
|
|
||||||
// Load BPF object from ELF file. Loading the program should fail as the
|
// Load BPF object from ELF file. Loading the program should fail as the
|
||||||
// map type for map pinned at "/ebpf/global/outer_map" does not match.
|
// map type for map pinned at "/ebpf/global/outer_map" does not match.
|
||||||
struct bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "map_reuse_um.dll" : "map_reuse.o");
|
const char* file_name = (execution_type == EBPF_EXECUTION_NATIVE ? "map_reuse_um.dll" : "map_reuse.o");
|
||||||
int result = ebpf_program_load(file_name, BPF_PROG_TYPE_XDP, EBPF_EXECUTION_ANY, &object, &program_fd, nullptr);
|
int result =
|
||||||
|
ebpf_program_load(file_name, BPF_PROG_TYPE_XDP, EBPF_EXECUTION_ANY, &unique_object, &program_fd, nullptr);
|
||||||
|
|
||||||
REQUIRE(result == -EINVAL);
|
REQUIRE(result == -EINVAL);
|
||||||
|
|
||||||
|
@ -2339,7 +2364,7 @@ TEST_CASE("load_native_program_negative3", "[end-to-end]")
|
||||||
size_t count_of_programs = 0;
|
size_t count_of_programs = 0;
|
||||||
int error;
|
int error;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
std::wstring file_path(L"droppacket_um.dll");
|
std::wstring file_path(L"droppacket_um.dll");
|
||||||
const wchar_t* service_name = nullptr;
|
const wchar_t* service_name = nullptr;
|
||||||
|
@ -2351,7 +2376,7 @@ TEST_CASE("load_native_program_negative3", "[end-to-end]")
|
||||||
|
|
||||||
// Load a valid native module.
|
// Load a valid native module.
|
||||||
error = ebpf_program_load(
|
error = ebpf_program_load(
|
||||||
"droppacket_um.dll", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &object, &program_fd, &error_message);
|
"droppacket_um.dll", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &unique_object, &program_fd, &error_message);
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
ebpf_free((void*)error_message);
|
ebpf_free((void*)error_message);
|
||||||
|
@ -2376,7 +2401,7 @@ TEST_CASE("load_native_program_negative3", "[end-to-end]")
|
||||||
&provider_module_id, nullptr, MAP_COUNT, map_handles, PROGRAM_COUNT, program_handles) ==
|
&provider_module_id, nullptr, MAP_COUNT, map_handles, PROGRAM_COUNT, program_handles) ==
|
||||||
ERROR_OBJECT_ALREADY_EXISTS);
|
ERROR_OBJECT_ALREADY_EXISTS);
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
|
|
||||||
// Now that we have closed the object, try to load programs from the same module again. This should
|
// Now that we have closed the object, try to load programs from the same module again. This should
|
||||||
// fail as the module should now be marked as "unloading".
|
// fail as the module should now be marked as "unloading".
|
||||||
|
@ -2440,15 +2465,15 @@ TEST_CASE("load_native_program_negative5", "[end_to_end]")
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
single_instance_hook_t hook(EBPF_PROGRAM_TYPE_XDP, EBPF_ATTACH_TYPE_XDP);
|
||||||
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
program_info_provider_t xdp_program_info(EBPF_PROGRAM_TYPE_XDP);
|
||||||
|
|
||||||
set_native_module_failures(true);
|
set_native_module_failures(true);
|
||||||
result =
|
result = ebpf_program_load(
|
||||||
ebpf_program_load("map.sys", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_ANY, &object, &program_fd, &error_message);
|
"map.sys", BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_ANY, &unique_object, &program_fd, &error_message);
|
||||||
REQUIRE(result == -ENOENT);
|
REQUIRE(result == -ENOENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2549,12 +2574,12 @@ _load_invalid_program(_In_z_ const char* file_name, ebpf_execution_type_t execut
|
||||||
_test_helper_end_to_end test_helper;
|
_test_helper_end_to_end test_helper;
|
||||||
|
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
||||||
|
|
||||||
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &object, &program_fd, nullptr);
|
result = ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, execution_type, &unique_object, &program_fd, nullptr);
|
||||||
REQUIRE(result == expected_result);
|
REQUIRE(result == expected_result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2769,7 +2794,7 @@ extension_reload_test(ebpf_execution_type_t execution_type)
|
||||||
xdp_md_t ctx0{packet0.data(), packet0.data() + packet0.size(), 0, TEST_IFINDEX};
|
xdp_md_t ctx0{packet0.data(), packet0.data() + packet0.size(), 0, TEST_IFINDEX};
|
||||||
|
|
||||||
// Try loading without the extension loaded.
|
// Try loading without the extension loaded.
|
||||||
bpf_object* droppacket_object;
|
bpf_object_ptr unique_droppacket_object;
|
||||||
int program_fd = -1;
|
int program_fd = -1;
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
|
|
||||||
|
@ -2779,7 +2804,7 @@ extension_reload_test(ebpf_execution_type_t execution_type)
|
||||||
execution_type == EBPF_EXECUTION_NATIVE ? "droppacket_um.dll" : "droppacket.o",
|
execution_type == EBPF_EXECUTION_NATIVE ? "droppacket_um.dll" : "droppacket.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
execution_type,
|
execution_type,
|
||||||
&droppacket_object,
|
&unique_droppacket_object,
|
||||||
&program_fd,
|
&program_fd,
|
||||||
&error_message) != 0);
|
&error_message) != 0);
|
||||||
|
|
||||||
|
@ -2795,7 +2820,7 @@ extension_reload_test(ebpf_execution_type_t execution_type)
|
||||||
execution_type == EBPF_EXECUTION_NATIVE ? "droppacket_um.dll" : "droppacket.o",
|
execution_type == EBPF_EXECUTION_NATIVE ? "droppacket_um.dll" : "droppacket.o",
|
||||||
BPF_PROG_TYPE_UNSPEC,
|
BPF_PROG_TYPE_UNSPEC,
|
||||||
execution_type,
|
execution_type,
|
||||||
&droppacket_object,
|
&unique_droppacket_object,
|
||||||
&program_fd,
|
&program_fd,
|
||||||
&error_message) == 0);
|
&error_message) == 0);
|
||||||
|
|
||||||
|
@ -2883,15 +2908,15 @@ TEST_CASE("close_unload_test", "[close_cleanup]")
|
||||||
|
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
||||||
|
|
||||||
const char* file_name = "bindmonitor_tailcall_um.dll";
|
const char* file_name = "bindmonitor_tailcall_um.dll";
|
||||||
result =
|
result = ebpf_program_load(
|
||||||
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &object, &program_fd, &error_message);
|
file_name, BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -2900,17 +2925,17 @@ TEST_CASE("close_unload_test", "[close_cleanup]")
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
|
|
||||||
// Set up tail calls.
|
// Set up tail calls.
|
||||||
struct bpf_program* callee0 = bpf_object__find_program_by_name(object, "BindMonitor_Callee0");
|
struct bpf_program* callee0 = bpf_object__find_program_by_name(unique_object.get(), "BindMonitor_Callee0");
|
||||||
REQUIRE(callee0 != nullptr);
|
REQUIRE(callee0 != nullptr);
|
||||||
fd_t callee0_fd = bpf_program__fd(callee0);
|
fd_t callee0_fd = bpf_program__fd(callee0);
|
||||||
REQUIRE(callee0_fd > 0);
|
REQUIRE(callee0_fd > 0);
|
||||||
|
|
||||||
struct bpf_program* callee1 = bpf_object__find_program_by_name(object, "BindMonitor_Callee1");
|
struct bpf_program* callee1 = bpf_object__find_program_by_name(unique_object.get(), "BindMonitor_Callee1");
|
||||||
REQUIRE(callee1 != nullptr);
|
REQUIRE(callee1 != nullptr);
|
||||||
fd_t callee1_fd = bpf_program__fd(callee1);
|
fd_t callee1_fd = bpf_program__fd(callee1);
|
||||||
REQUIRE(callee1_fd > 0);
|
REQUIRE(callee1_fd > 0);
|
||||||
|
|
||||||
fd_t prog_map_fd = bpf_object__find_map_fd_by_name(object, "prog_array_map");
|
fd_t prog_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "prog_array_map");
|
||||||
REQUIRE(prog_map_fd > 0);
|
REQUIRE(prog_map_fd > 0);
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
@ -2923,8 +2948,7 @@ TEST_CASE("close_unload_test", "[close_cleanup]")
|
||||||
REQUIRE(hook.attach_link(program_fd, &ifindex, sizeof(ifindex), &link) == EBPF_SUCCESS);
|
REQUIRE(hook.attach_link(program_fd, &ifindex, sizeof(ifindex), &link) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// These are needed to prevent the memory leak detector from flagging a memory leak.
|
// These are needed to prevent the memory leak detector from flagging a memory leak.
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
// The block of commented code after this comment is for documentation purposes only.
|
// The block of commented code after this comment is for documentation purposes only.
|
||||||
//
|
//
|
||||||
|
@ -2952,7 +2976,7 @@ TEST_CASE("close_unload_test", "[close_cleanup]")
|
||||||
// REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
// REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
||||||
// This test tests the case where a program is inserted multiple times with different keys into the same map.
|
// This test tests the case where a program is inserted multiple times with different keys into the same map.
|
||||||
|
@ -2962,15 +2986,15 @@ TEST_CASE("multiple_map_insert", "[close_cleanup]")
|
||||||
|
|
||||||
const char* error_message = nullptr;
|
const char* error_message = nullptr;
|
||||||
int result;
|
int result;
|
||||||
bpf_object* object = nullptr;
|
bpf_object_ptr unique_object;
|
||||||
bpf_link* link = nullptr;
|
bpf_link_ptr link;
|
||||||
fd_t program_fd;
|
fd_t program_fd;
|
||||||
|
|
||||||
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
program_info_provider_t bind_program_info(EBPF_PROGRAM_TYPE_BIND);
|
||||||
|
|
||||||
const char* file_name = "bindmonitor_tailcall_um.dll";
|
const char* file_name = "bindmonitor_tailcall_um.dll";
|
||||||
result =
|
result = ebpf_program_load(
|
||||||
ebpf_program_load(file_name, BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &object, &program_fd, &error_message);
|
file_name, BPF_PROG_TYPE_UNSPEC, EBPF_EXECUTION_NATIVE, &unique_object, &program_fd, &error_message);
|
||||||
|
|
||||||
if (error_message) {
|
if (error_message) {
|
||||||
printf("ebpf_program_load failed with %s\n", error_message);
|
printf("ebpf_program_load failed with %s\n", error_message);
|
||||||
|
@ -2979,17 +3003,17 @@ TEST_CASE("multiple_map_insert", "[close_cleanup]")
|
||||||
REQUIRE(result == 0);
|
REQUIRE(result == 0);
|
||||||
|
|
||||||
// Set up tail calls.
|
// Set up tail calls.
|
||||||
struct bpf_program* callee0 = bpf_object__find_program_by_name(object, "BindMonitor_Callee0");
|
struct bpf_program* callee0 = bpf_object__find_program_by_name(unique_object.get(), "BindMonitor_Callee0");
|
||||||
REQUIRE(callee0 != nullptr);
|
REQUIRE(callee0 != nullptr);
|
||||||
fd_t callee0_fd = bpf_program__fd(callee0);
|
fd_t callee0_fd = bpf_program__fd(callee0);
|
||||||
REQUIRE(callee0_fd > 0);
|
REQUIRE(callee0_fd > 0);
|
||||||
|
|
||||||
struct bpf_program* callee1 = bpf_object__find_program_by_name(object, "BindMonitor_Callee1");
|
struct bpf_program* callee1 = bpf_object__find_program_by_name(unique_object.get(), "BindMonitor_Callee1");
|
||||||
REQUIRE(callee1 != nullptr);
|
REQUIRE(callee1 != nullptr);
|
||||||
fd_t callee1_fd = bpf_program__fd(callee1);
|
fd_t callee1_fd = bpf_program__fd(callee1);
|
||||||
REQUIRE(callee1_fd > 0);
|
REQUIRE(callee1_fd > 0);
|
||||||
|
|
||||||
fd_t prog_map_fd = bpf_object__find_map_fd_by_name(object, "prog_array_map");
|
fd_t prog_map_fd = bpf_object__find_map_fd_by_name(unique_object.get(), "prog_array_map");
|
||||||
REQUIRE(prog_map_fd > 0);
|
REQUIRE(prog_map_fd > 0);
|
||||||
|
|
||||||
uint32_t index = 0;
|
uint32_t index = 0;
|
||||||
|
@ -3013,8 +3037,7 @@ TEST_CASE("multiple_map_insert", "[close_cleanup]")
|
||||||
REQUIRE(hook.attach_link(program_fd, &ifindex, sizeof(ifindex), &link) == EBPF_SUCCESS);
|
REQUIRE(hook.attach_link(program_fd, &ifindex, sizeof(ifindex), &link) == EBPF_SUCCESS);
|
||||||
|
|
||||||
// These are needed to prevent the memory leak detector from flagging a memory leak.
|
// These are needed to prevent the memory leak detector from flagging a memory leak.
|
||||||
hook.detach_link(link);
|
hook.detach_and_close_link(&link);
|
||||||
hook.close_link(link);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
--- DO NOT REMOVE OR UN-COMMENT ---
|
--- DO NOT REMOVE OR UN-COMMENT ---
|
||||||
|
@ -3027,5 +3050,5 @@ TEST_CASE("multiple_map_insert", "[close_cleanup]")
|
||||||
// REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
// REQUIRE(bpf_map_update_elem(prog_map_fd, &index, &ebpf_fd_invalid, 0) == 0);
|
||||||
*/
|
*/
|
||||||
|
|
||||||
bpf_object__close(object);
|
bpf_object__close(unique_object.release());
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,22 @@ typedef struct _ebpf_free_memory
|
||||||
|
|
||||||
typedef std::unique_ptr<uint8_t, ebpf_free_memory_t> ebpf_memory_t;
|
typedef std::unique_ptr<uint8_t, ebpf_free_memory_t> ebpf_memory_t;
|
||||||
|
|
||||||
|
typedef struct _close_bpf_link
|
||||||
|
{
|
||||||
|
void
|
||||||
|
operator()(_In_opt_ _Post_invalid_ bpf_link* link)
|
||||||
|
{
|
||||||
|
if (link != nullptr) {
|
||||||
|
if (ebpf_link_detach(link) != EBPF_SUCCESS) {
|
||||||
|
throw std::runtime_error("ebpf_link_detach failed");
|
||||||
|
}
|
||||||
|
ebpf_link_close(link);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} close_bpf_link_t;
|
||||||
|
|
||||||
|
typedef std::unique_ptr<bpf_link, close_bpf_link_t> bpf_link_ptr;
|
||||||
|
|
||||||
extern bool _ebpf_platform_is_preemptible;
|
extern bool _ebpf_platform_is_preemptible;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
@ -70,6 +86,24 @@ typedef class _hook_helper
|
||||||
public:
|
public:
|
||||||
_hook_helper(ebpf_attach_type_t attach_type) : _attach_type(attach_type) {}
|
_hook_helper(ebpf_attach_type_t attach_type) : _attach_type(attach_type) {}
|
||||||
|
|
||||||
|
_Must_inspect_result_ ebpf_result_t
|
||||||
|
attach_link(
|
||||||
|
fd_t program_fd,
|
||||||
|
_In_reads_bytes_opt_(attach_parameters_size) void* attach_parameters,
|
||||||
|
size_t attach_parameters_size,
|
||||||
|
_Out_ bpf_link_ptr* unique_link)
|
||||||
|
{
|
||||||
|
bpf_link* link = nullptr;
|
||||||
|
ebpf_result_t result;
|
||||||
|
|
||||||
|
result = ebpf_program_attach_by_fd(program_fd, &_attach_type, attach_parameters, attach_parameters_size, &link);
|
||||||
|
if (result == EBPF_SUCCESS) {
|
||||||
|
unique_link->reset(link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
_Must_inspect_result_ ebpf_result_t
|
_Must_inspect_result_ ebpf_result_t
|
||||||
attach_link(
|
attach_link(
|
||||||
fd_t program_fd,
|
fd_t program_fd,
|
||||||
|
@ -172,6 +206,14 @@ typedef class _single_instance_hook : public _hook_helper
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
detach_and_close_link(_Inout_ bpf_link_ptr* unique_link)
|
||||||
|
{
|
||||||
|
bpf_link* link = unique_link->release();
|
||||||
|
detach_link(link);
|
||||||
|
close_link(link);
|
||||||
|
}
|
||||||
|
|
||||||
_Must_inspect_result_ ebpf_result_t
|
_Must_inspect_result_ ebpf_result_t
|
||||||
fire(_Inout_ void* context, _Out_ uint32_t* result)
|
fire(_Inout_ void* context, _Out_ uint32_t* result)
|
||||||
{
|
{
|
||||||
|
|
Загрузка…
Ссылка в новой задаче