2021-06-09 18:44:24 +03:00
|
|
|
// Copyright (c) Microsoft Corporation
|
|
|
|
// SPDX-License-Identifier: MIT
|
|
|
|
|
|
|
|
#define CATCH_CONFIG_MAIN
|
|
|
|
|
|
|
|
#include <chrono>
|
|
|
|
#include <mutex>
|
|
|
|
#include <thread>
|
|
|
|
#include "api_test.h"
|
2021-06-29 02:13:29 +03:00
|
|
|
#include "catch_wrapper.hpp"
|
2021-06-09 18:44:24 +03:00
|
|
|
#include "common_tests.h"
|
2021-09-14 18:25:56 +03:00
|
|
|
#include <io.h>
|
2021-06-09 18:44:24 +03:00
|
|
|
#include "service_helper.h"
|
2021-08-04 03:25:50 +03:00
|
|
|
#include "libbpf.h"
|
2021-06-09 18:44:24 +03:00
|
|
|
#define SAMPLE_PATH ""
|
|
|
|
|
|
|
|
#define EBPF_CORE_DRIVER_BINARY_NAME L"ebpfcore.sys"
|
|
|
|
#define EBPF_CORE_DRIVER_NAME L"ebpfcore"
|
|
|
|
|
2021-06-23 06:42:18 +03:00
|
|
|
#define EBPF_EXTENSION_DRIVER_BINARY_NAME L"netebpfext.sys"
|
|
|
|
#define EBPF_EXTENSION_DRIVER_NAME L"netebpfext"
|
|
|
|
|
|
|
|
#define EBPF_SERVICE_BINARY_NAME L"ebpfsvc.exe"
|
|
|
|
#define EBPF_SERVICE_NAME L"ebpfsvc"
|
|
|
|
|
|
|
|
#define DROP_PACKET_PROGRAM_COUNT 1
|
|
|
|
#define BIND_MONITOR_PROGRAM_COUNT 1
|
|
|
|
|
|
|
|
#define DROP_PACKET_MAP_COUNT 1
|
|
|
|
#define BIND_MONITOR_MAP_COUNT 2
|
|
|
|
|
2021-06-09 18:44:24 +03:00
|
|
|
static service_install_helper
|
|
|
|
_ebpf_core_driver_helper(EBPF_CORE_DRIVER_NAME, EBPF_CORE_DRIVER_BINARY_NAME, SERVICE_KERNEL_DRIVER);
|
|
|
|
|
2021-06-23 06:42:18 +03:00
|
|
|
static service_install_helper
|
|
|
|
_ebpf_extension_driver_helper(EBPF_EXTENSION_DRIVER_NAME, EBPF_EXTENSION_DRIVER_BINARY_NAME, SERVICE_KERNEL_DRIVER);
|
|
|
|
|
|
|
|
static service_install_helper
|
|
|
|
_ebpf_service_helper(EBPF_SERVICE_NAME, EBPF_SERVICE_BINARY_NAME, SERVICE_WIN32_OWN_PROCESS);
|
|
|
|
|
|
|
|
static ebpf_result_t
|
|
|
|
_program_load_helper(
|
2021-06-24 03:54:03 +03:00
|
|
|
const char* file_name,
|
|
|
|
const ebpf_program_type_t* program_type,
|
|
|
|
ebpf_execution_type_t execution_type,
|
2021-08-04 03:25:50 +03:00
|
|
|
struct bpf_object** object,
|
2021-06-24 03:54:03 +03:00
|
|
|
fd_t* program_fd)
|
2021-06-23 06:42:18 +03:00
|
|
|
{
|
|
|
|
ebpf_result_t result;
|
|
|
|
const char* log_buffer = nullptr;
|
2021-06-24 03:54:03 +03:00
|
|
|
result = ebpf_program_load(file_name, program_type, nullptr, execution_type, object, program_fd, &log_buffer);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
ebpf_free_string(log_buffer);
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2021-06-24 03:54:03 +03:00
|
|
|
_test_program_load(
|
|
|
|
const char* file_name,
|
|
|
|
ebpf_program_type_t* program_type,
|
|
|
|
ebpf_execution_type_t execution_type,
|
|
|
|
bool expected_to_load)
|
2021-06-23 06:42:18 +03:00
|
|
|
{
|
|
|
|
ebpf_result_t result;
|
2021-08-04 03:25:50 +03:00
|
|
|
struct bpf_object* object = nullptr;
|
2021-06-23 06:42:18 +03:00
|
|
|
fd_t program_fd;
|
2021-08-11 03:04:07 +03:00
|
|
|
fd_t previous_fd = ebpf_fd_invalid;
|
|
|
|
fd_t next_fd = ebpf_fd_invalid;
|
|
|
|
|
2021-06-24 03:54:03 +03:00
|
|
|
result = _program_load_helper(file_name, program_type, execution_type, &object, &program_fd);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
if (expected_to_load) {
|
|
|
|
REQUIRE(result == EBPF_SUCCESS);
|
|
|
|
REQUIRE(program_fd > 0);
|
|
|
|
} else {
|
|
|
|
REQUIRE(result == EBPF_VERIFICATION_FAILED);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Query loaded programs to verify this program is loaded.
|
2021-08-11 03:04:07 +03:00
|
|
|
REQUIRE(ebpf_get_next_program(previous_fd, &next_fd) == EBPF_SUCCESS);
|
|
|
|
REQUIRE(next_fd != ebpf_fd_invalid);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
const char* program_file_name;
|
|
|
|
const char* program_section_name;
|
|
|
|
ebpf_execution_type_t program_execution_type;
|
|
|
|
REQUIRE(
|
2021-08-11 03:04:07 +03:00
|
|
|
ebpf_program_query_info(program_fd, &program_execution_type, &program_file_name, &program_section_name) ==
|
|
|
|
EBPF_SUCCESS);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
2021-06-24 03:54:03 +03:00
|
|
|
// Set the default execution type to JIT. This will eventually
|
|
|
|
// be decided by a system-wide policy. TODO(Issue #288): Configure
|
|
|
|
// system-wide execution type.
|
|
|
|
if (execution_type == EBPF_EXECUTION_ANY) {
|
|
|
|
execution_type = EBPF_EXECUTION_JIT;
|
|
|
|
}
|
|
|
|
REQUIRE(program_execution_type == execution_type);
|
2021-06-23 06:42:18 +03:00
|
|
|
REQUIRE(strcmp(program_file_name, file_name) == 0);
|
|
|
|
|
|
|
|
// Next program should not be present.
|
2021-08-11 03:04:07 +03:00
|
|
|
previous_fd = next_fd;
|
|
|
|
REQUIRE(ebpf_get_next_program(previous_fd, &next_fd) == EBPF_SUCCESS);
|
|
|
|
REQUIRE(next_fd == ebpf_fd_invalid);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
2021-09-14 18:25:56 +03:00
|
|
|
_close(previous_fd);
|
2021-08-11 03:04:07 +03:00
|
|
|
previous_fd = ebpf_fd_invalid;
|
2021-08-04 03:25:50 +03:00
|
|
|
bpf_object__close(object);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
// We have closed both handles to the program. Program should be unloaded now.
|
2021-08-11 03:04:07 +03:00
|
|
|
REQUIRE(ebpf_get_next_program(previous_fd, &next_fd) == ERROR_SUCCESS);
|
|
|
|
REQUIRE(next_fd == ebpf_fd_invalid);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_test_map_next_previous(const char* file_name, int expected_map_count)
|
|
|
|
{
|
|
|
|
ebpf_result_t result;
|
2021-08-04 03:25:50 +03:00
|
|
|
struct bpf_object* object = nullptr;
|
2021-06-23 06:42:18 +03:00
|
|
|
fd_t program_fd;
|
|
|
|
int map_count = 0;
|
2021-08-04 03:25:50 +03:00
|
|
|
struct bpf_map* previous = nullptr;
|
|
|
|
struct bpf_map* next = nullptr;
|
2021-06-24 03:54:03 +03:00
|
|
|
result = _program_load_helper(file_name, nullptr, EBPF_EXECUTION_ANY, &object, &program_fd);
|
2021-06-23 06:42:18 +03:00
|
|
|
REQUIRE(result == EBPF_SUCCESS);
|
|
|
|
|
2021-08-04 03:25:50 +03:00
|
|
|
next = bpf_map__next(previous, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
while (next != nullptr) {
|
|
|
|
map_count++;
|
|
|
|
previous = next;
|
2021-08-04 03:25:50 +03:00
|
|
|
next = bpf_map__next(previous, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
REQUIRE(map_count == expected_map_count);
|
|
|
|
|
|
|
|
map_count = 0;
|
|
|
|
previous = next = nullptr;
|
|
|
|
|
2021-08-04 03:25:50 +03:00
|
|
|
previous = bpf_map__prev(next, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
while (previous != nullptr) {
|
|
|
|
map_count++;
|
|
|
|
next = previous;
|
2021-08-04 03:25:50 +03:00
|
|
|
previous = bpf_map__prev(next, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
REQUIRE(map_count == expected_map_count);
|
|
|
|
|
2021-08-04 03:25:50 +03:00
|
|
|
bpf_object__close(object);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_test_program_next_previous(const char* file_name, int expected_program_count)
|
|
|
|
{
|
|
|
|
ebpf_result_t result;
|
2021-08-04 03:25:50 +03:00
|
|
|
struct bpf_object* object = nullptr;
|
2021-06-23 06:42:18 +03:00
|
|
|
fd_t program_fd;
|
|
|
|
int program_count = 0;
|
2021-08-04 03:25:50 +03:00
|
|
|
struct bpf_program* previous = nullptr;
|
|
|
|
struct bpf_program* next = nullptr;
|
2021-06-24 03:54:03 +03:00
|
|
|
result = _program_load_helper(file_name, nullptr, EBPF_EXECUTION_ANY, &object, &program_fd);
|
2021-06-23 06:42:18 +03:00
|
|
|
REQUIRE(result == EBPF_SUCCESS);
|
|
|
|
|
2021-08-04 03:25:50 +03:00
|
|
|
next = bpf_program__next(previous, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
while (next != nullptr) {
|
|
|
|
program_count++;
|
|
|
|
previous = next;
|
2021-08-04 03:25:50 +03:00
|
|
|
next = bpf_program__next(previous, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
REQUIRE(program_count == expected_program_count);
|
|
|
|
|
|
|
|
program_count = 0;
|
|
|
|
previous = next = nullptr;
|
|
|
|
|
2021-08-04 03:25:50 +03:00
|
|
|
previous = bpf_program__prev(next, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
while (previous != nullptr) {
|
|
|
|
program_count++;
|
|
|
|
next = previous;
|
2021-08-04 03:25:50 +03:00
|
|
|
previous = bpf_program__prev(next, object);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
REQUIRE(program_count == expected_program_count);
|
|
|
|
|
2021-08-04 03:25:50 +03:00
|
|
|
bpf_object__close(object);
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
|
2021-06-09 18:44:24 +03:00
|
|
|
TEST_CASE("pinned_map_enum", "[pinned_map_enum]")
|
|
|
|
{
|
|
|
|
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
|
|
|
|
|
|
|
ebpf_test_pinned_map_enum();
|
|
|
|
ebpf_api_terminate();
|
2021-06-23 06:42:18 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("test_ebpf_program_load", "[test_ebpf_program_load]")
|
|
|
|
{
|
|
|
|
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
|
|
|
|
2021-06-24 03:54:03 +03:00
|
|
|
// Load droppacket (JIT) without providing expected program type.
|
|
|
|
_test_program_load("droppacket.o", nullptr, EBPF_EXECUTION_JIT, true);
|
|
|
|
|
|
|
|
// Load droppacket (ANY) without providing expected program type.
|
|
|
|
_test_program_load("droppacket.o", nullptr, EBPF_EXECUTION_ANY, true);
|
|
|
|
|
|
|
|
// Load droppacket (INTERPRET) without providing expected program type.
|
|
|
|
_test_program_load("droppacket.o", nullptr, EBPF_EXECUTION_INTERPRET, true);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
// Load droppacket with providing expected program type.
|
2021-06-24 03:54:03 +03:00
|
|
|
_test_program_load("droppacket.o", &EBPF_PROGRAM_TYPE_XDP, EBPF_EXECUTION_INTERPRET, true);
|
|
|
|
|
|
|
|
// Load bindmonitor (JIT) without providing expected program type.
|
|
|
|
_test_program_load("bindmonitor.o", nullptr, EBPF_EXECUTION_JIT, true);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
2021-06-24 03:54:03 +03:00
|
|
|
// Load bindmonitor (INTERPRET) without providing expected program type.
|
|
|
|
_test_program_load("bindmonitor.o", nullptr, EBPF_EXECUTION_INTERPRET, true);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
// Load bindmonitor with providing expected program type.
|
2021-06-24 03:54:03 +03:00
|
|
|
_test_program_load("bindmonitor.o", &EBPF_PROGRAM_TYPE_BIND, EBPF_EXECUTION_JIT, true);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
// Try to load bindmonitor with providing wrong program type.
|
2021-06-24 03:54:03 +03:00
|
|
|
_test_program_load("bindmonitor.o", &EBPF_PROGRAM_TYPE_XDP, EBPF_EXECUTION_ANY, false);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
// Try to load an unsafe program.
|
2021-06-24 03:54:03 +03:00
|
|
|
_test_program_load("droppacket_unsafe.o", nullptr, EBPF_EXECUTION_ANY, false);
|
2021-06-23 06:42:18 +03:00
|
|
|
|
|
|
|
ebpf_api_terminate();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("test_ebpf_program_next_previous", "[test_ebpf_program_next_previous]")
|
|
|
|
{
|
|
|
|
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
|
|
|
|
|
|
|
_test_program_next_previous("droppacket.o", DROP_PACKET_PROGRAM_COUNT);
|
|
|
|
_test_program_next_previous("bindmonitor.o", BIND_MONITOR_PROGRAM_COUNT);
|
|
|
|
|
|
|
|
ebpf_api_terminate();
|
|
|
|
}
|
|
|
|
|
|
|
|
TEST_CASE("test_ebpf_map_next_previous", "[test_ebpf_map_next_previous]")
|
|
|
|
{
|
|
|
|
REQUIRE(ebpf_api_initiate() == EBPF_SUCCESS);
|
|
|
|
|
|
|
|
_test_map_next_previous("droppacket.o", DROP_PACKET_MAP_COUNT);
|
|
|
|
_test_map_next_previous("bindmonitor.o", BIND_MONITOR_MAP_COUNT);
|
|
|
|
|
|
|
|
ebpf_api_terminate();
|
2021-08-04 03:25:50 +03:00
|
|
|
}
|