From 0f753dea28ad62f2fa2de9e83d019fc8415dca08 Mon Sep 17 00:00:00 2001 From: Alan Jowett Date: Tue, 23 Feb 2021 17:34:19 +0000 Subject: [PATCH] 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. --- external/ebpf-verifier | 2 +- src/ebpf/libs/api/Verifier.cpp | 11 +++++++---- src/ebpf/libs/api/Verifier.h | 5 ++++- src/ebpf/libs/api/api.cpp | 17 ++++++++++++----- src/tools/netsh/elf.cpp | 14 ++++++++------ 5 files changed, 32 insertions(+), 17 deletions(-) diff --git a/external/ebpf-verifier b/external/ebpf-verifier index b40e16861..23e17278b 160000 --- a/external/ebpf-verifier +++ b/external/ebpf-verifier @@ -1 +1 @@ -Subproject commit b40e16861ed6bd1410ddb9057903b9b905e56d55 +Subproject commit 23e17278ba7f484464ea981b15055928aa4db079 diff --git a/src/ebpf/libs/api/Verifier.cpp b/src/ebpf/libs/api/Verifier.cpp index 4ba111c34..5ae458ec8 100644 --- a/src/ebpf/libs/api/Verifier.cpp +++ b/src/ebpf/libs/api/Verifier.cpp @@ -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; - - auto raw_progs = read_elf(filename, sectionname, map_create_function, nullptr, platform); + 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, &verifier_options, &platform); if (raw_progs.size() != 1) { return 1; // Error } diff --git a/src/ebpf/libs/api/Verifier.h b/src/ebpf/libs/api/Verifier.h index 99d1bdfd6..f187b3fef 100644 --- a/src/ebpf/libs/api/Verifier.h +++ b/src/ebpf/libs/api/Verifier.h @@ -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); diff --git a/src/ebpf/libs/api/api.cpp b/src/ebpf/libs/api/api.cpp index 00c4c1ab3..be3afa456 100644 --- a/src/ebpf/libs/api/api.cpp +++ b/src/ebpf/libs/api/api.cpp @@ -125,7 +125,12 @@ DLL void ebpf_api_terminate() } } -std::vector _map_file_descriptors; +typedef struct _map_cache { + uintptr_t handle; + EbpfMapDescriptor ebpf_map_descriptor; +} map_cache_t; + +std::vector _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(_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; } diff --git a/src/tools/netsh/elf.cpp b/src/tools/netsh/elf.cpp index f5373129c..75b306a27 100644 --- a/src/tools/netsh/elf.cpp +++ b/src/tools/netsh/elf.cpp @@ -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 programOrError = unmarshal(rawProgram, platform); if (std::holds_alternative(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 programOrError = unmarshal(rawProgram, platform); if (std::holds_alternative(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";