Merged PR 4147072: First version of changes to comply with new ebpf contract

First version of changes to comply with new ebpf contract

Note:
We can't use crt handle -> fd mapping until ebpfcore returns *real* handles.
This commit is contained in:
Alan Jowett 2021-02-23 17:34:19 +00:00
Родитель 20914bf459
Коммит 0f753dea28
5 изменённых файлов: 32 добавлений и 17 удалений

2
external/ebpf-verifier поставляемый

@ -1 +1 @@
Subproject commit b40e16861ed6bd1410ddb9057903b9b905e56d55
Subproject commit 23e17278ba7f484464ea981b15055928aa4db079

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

@ -62,11 +62,14 @@ static int analyze(raw_program& raw_prog, char ** error_message)
return 0; // Success.
}
int verify(const char* filename, const char* sectionname, uint8_t* byte_code, size_t* byte_code_size, map_create_fp map_create_function, char** error_message)
int verify(const char* filename, const char* sectionname, uint8_t* byte_code, size_t* byte_code_size, ebpf_create_map_fn map_create_function, ebpf_get_map_descriptor_fn get_map_descriptor, char** error_message)
{
const ebpf_platform_t* platform = &g_ebpf_platform_windows;
ebpf_verifier_options_t verifier_options{ false, false, false, false };
ebpf_platform_t platform = g_ebpf_platform_windows;
platform.create_map = map_create_function;
platform.get_map_descriptor = get_map_descriptor;
auto raw_progs = read_elf(filename, sectionname, map_create_function, nullptr, platform);
auto raw_progs = read_elf(filename, sectionname, &verifier_options, &platform);
if (raw_progs.size() != 1) {
return 1; // Error
}

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

@ -1,7 +1,10 @@
#pragma once
#include "config.hpp"
#undef VOID
#include "platform.hpp"
#define VOID void
typedef int (*map_create_fp)(uint32_t map_type, uint32_t key_size, uint32_t value_size, uint32_t max_entries, ebpf_verifier_options_t options);
int get_file_size(char* filename, size_t* byte_code_size);
int verify(const char* filename, const char* sectionname, uint8_t* byte_code, size_t* byte_code_size, map_create_fp map_creat_function, char** error_message);
int verify(const char* filename, const char* sectionname, uint8_t* byte_code, size_t* byte_code_size, ebpf_create_map_fn map_creat_function, ebpf_get_map_descriptor_fn get_map_descriptor, char** error_message);
int verify_byte_code(const char* path, const char* section_name, const uint8_t* byte_code, size_t byte_code_size, char** error_message);

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

@ -125,7 +125,12 @@ DLL void ebpf_api_terminate()
}
}
std::vector<uint64_t> _map_file_descriptors;
typedef struct _map_cache {
uintptr_t handle;
EbpfMapDescriptor ebpf_map_descriptor;
} map_cache_t;
std::vector<map_cache_t> _map_file_descriptors;
static int create_map_function(uint32_t type, uint32_t key_size, uint32_t value_size, uint32_t max_entries, ebpf_verifier_options_t options)
{
@ -159,8 +164,10 @@ static int create_map_function(uint32_t type, uint32_t key_size, uint32_t value_
// TODO: prevail encodes map size into the map file descriptor leaving
// the lowest 6 bits usable. Use this as an index into a process wide
// table.
_map_file_descriptors.push_back(reply.handle);
return (value_size << 14) + (key_size << 6) + _map_file_descriptors.size();
int fd = static_cast<int>(_map_file_descriptors.size() + 1);
_map_file_descriptors.push_back({ reply.handle, {fd, type, key_size, value_size, 0} });
return _map_file_descriptors.size();
}
static uint64_t map_resolver(void* context, uint64_t fd)
@ -171,7 +178,7 @@ static uint64_t map_resolver(void* context, uint64_t fd)
_ebpf_operation_resolve_map_request request{
sizeof(request),
ebpf_operation_id_t::EBPF_OPERATION_RESOLVE_MAP,
_map_file_descriptors[(fd & 0x1f) - 1] };
_map_file_descriptors[fd-1].handle };
_ebpf_operation_resolve_map_reply reply;
@ -227,7 +234,7 @@ DLL DWORD ebpf_api_load_program(const char* file_name, const char* section_name,
{
_map_file_descriptors.resize(0);
// Verify code.
if (verify(file_name, section_name, byte_code.data(), &byte_code_size, create_map_function, error_message) != 0)
if (verify(file_name, section_name, byte_code.data(), &byte_code_size, create_map_function, [](int fd) -> EbpfMapDescriptor& { return _map_file_descriptors[fd - 1].ebpf_map_descriptor; }, error_message) != 0)
{
return ERROR_INVALID_PARAMETER;
}

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

@ -67,7 +67,9 @@ DWORD handle_ebpf_show_disassembly(
}
try {
auto rawPrograms = read_elf(filename, section, create_map_crab, nullptr, platform);
ebpf_verifier_options_t verifierOptions = ebpf_verifier_default_options;
verifierOptions.print_failures = true;
auto rawPrograms = read_elf(filename, section, &verifierOptions, platform);
raw_program rawProgram = rawPrograms.back();
std::variant<InstructionSeq, std::string> programOrError = unmarshal(rawProgram, platform);
if (std::holds_alternative<std::string>(programOrError)) {
@ -157,7 +159,7 @@ DWORD handle_ebpf_show_sections(
}
try {
auto rawPrograms = read_elf(filename, section, create_map_crab, nullptr, platform);
auto rawPrograms = read_elf(filename, section, &ebpf_verifier_default_options, platform);
if (level == VL_NORMAL) {
std::cout << "\n";
std::cout << " Section Type # Maps Size\n";
@ -255,7 +257,10 @@ DWORD handle_ebpf_show_verification(
}
try {
auto rawPrograms = read_elf(filename, section, create_map_crab, nullptr, platform);
// Analyze the control-flow graph.
ebpf_verifier_options_t verifierOptions = ebpf_verifier_default_options;
verifierOptions.print_failures = true;
auto rawPrograms = read_elf(filename, section, &verifierOptions, platform);
raw_program rawProgram = rawPrograms.back();
std::variant<InstructionSeq, std::string> programOrError = unmarshal(rawProgram, platform);
if (std::holds_alternative<std::string>(programOrError)) {
@ -268,9 +273,6 @@ DWORD handle_ebpf_show_verification(
// in a "passive", non-deterministic form.
cfg_t controlFlowGraph = prepare_cfg(program, rawProgram.info, true);
// Analyze the control-flow graph.
ebpf_verifier_options_t verifierOptions = ebpf_verifier_default_options;
verifierOptions.print_failures = true;
const auto res = run_ebpf_analysis(std::cout, controlFlowGraph, rawProgram.info, &verifierOptions);
if (!res) {
std::cout << "\nVerification failed\n";