forked from rlane/ubpf
-
Notifications
You must be signed in to change notification settings - Fork 138
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support external stacks and local function calls using local memory
1. Add support for invoking the interpreter and JIT'd code with an external stack. This feature is generally useful and will also make it easier to fuzz the runtime and check for correctness. 2. Add support for local functions that use local memory. Prior to this commit, a local function could be called but could not use any local memory (without overwriting memory from another function). Signed-off-by: Will Hawkins <[email protected]>
- Loading branch information
Showing
18 changed files
with
937 additions
and
250 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
72 0a fc ff 01 00 00 00 72 0a fd ff 02 00 00 00 72 0a fe ff 03 00 00 00 72 0a ff ff 04 00 00 00 85 10 00 00 02 00 00 00 b7 00 00 00 00 00 00 00 95 00 00 00 00 00 00 00 72 0a fc ff 05 00 00 00 72 0a fd ff 06 00 00 00 72 0a fe ff 07 00 00 00 72 0a ff ff 08 00 00 00 95 00 00 00 00 00 00 00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
b7 06 00 00 0a 00 00 00 b7 07 00 00 0a 00 00 00 b7 08 00 00 0a 00 00 00 b7 09 00 00 0a 00 00 00 b7 01 00 00 05 00 00 00 7b 1a f8 ff 00 00 00 00 85 10 00 00 02 00 00 00 79 a0 f8 ff 00 00 00 00 95 00 00 00 00 00 00 00 b7 01 00 00 37 00 00 00 7b 1a f8 ff 00 00 00 00 95 00 00 00 00 00 00 00 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
## Test Description | ||
|
||
This custom test guarantees that the eBPF program's manipulation of its stack has the intended effect. The eBPF program is JIT'd under the assumption that each of the functions require 16 bytes of space. The test guarantees that by returning `16` from `stack_usage_calculator` which is registered as the callback that will determine the stack usage of a local function. | ||
|
||
### eBPF Program Source | ||
|
||
``` | ||
stb [%r10-4], 0x01 | ||
stb [%r10-3], 0x02 | ||
stb [%r10-2], 0x03 | ||
stb [%r10-1], 0x04 | ||
call local inner | ||
mov %r0, 0 | ||
exit | ||
inner: | ||
stb [%r10-4], 0x05 | ||
stb [%r10-3], 0x06 | ||
stb [%r10-2], 0x07 | ||
stb [%r10-1], 0x08 | ||
exit | ||
``` | ||
|
||
### Expected Behavior | ||
|
||
Given the size of the stack usage for each function (see above), the contents of the memory at the end of the program will be: | ||
|
||
``` | ||
0x00: 0x00 | ||
0x01: 0x00 | ||
0x02: 0x00 | ||
0x03: 0x00 | ||
0x04: 0x00 | ||
0x05: 0x00 | ||
0x06: 0x00 | ||
0x07: 0x00 | ||
0x08: 0x00 | ||
0x09: 0x00 | ||
0x0a: 0x00 | ||
0x0b: 0x05 | ||
0x0c: 0x06 | ||
0x0d: 0x07 | ||
0x0e: 0x08 | ||
0x0f: 0x00 | ||
0x10: 0x00 | ||
0x11: 0x00 | ||
0x12: 0x00 | ||
0x13: 0x00 | ||
0x14: 0x00 | ||
0x15: 0x00 | ||
0x16: 0x00 | ||
0x17: 0x00 | ||
0x18: 0x00 | ||
0x19: 0x00 | ||
0x1a: 0x00 | ||
0x1b: 0x01 | ||
0x1c: 0x02 | ||
0x1d: 0x03 | ||
0x1e: 0x04 | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
## Test Description | ||
|
||
This custom test program tests whether it is possible to update the external helper | ||
functions for an eBPF program that has already been JIT'd. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright (c) Will Hawkins | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#include <cstdint> | ||
#include <iostream> | ||
#include <memory> | ||
#include <stdint.h> | ||
#include <vector> | ||
#include <string> | ||
|
||
extern "C" | ||
{ | ||
#include "ubpf.h" | ||
} | ||
|
||
#include "ubpf_custom_test_support.h" | ||
|
||
int | ||
stack_usage_calculator(const struct ubpf_vm* vm, uint16_t pc, void* cookie) | ||
{ | ||
UNREFERENCED_PARAMETER(vm); | ||
UNREFERENCED_PARAMETER(pc); | ||
UNREFERENCED_PARAMETER(cookie); | ||
return 16; | ||
} | ||
|
||
int | ||
main(int argc, char** argv) | ||
{ | ||
std::vector<std::string> args(argv, argv + argc); | ||
std::string program_string{}; | ||
ubpf_jit_fn jit_fn; | ||
|
||
std::getline(std::cin, program_string); | ||
|
||
const size_t stack_size{32}; | ||
uint8_t expected_result[] = { | ||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, 6, 7, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 2, 3, 4, | ||
}; | ||
|
||
bool success = true; | ||
|
||
std::unique_ptr<ubpf_vm, decltype(&ubpf_destroy)> vm(ubpf_create(), ubpf_destroy); | ||
std::string error{}; | ||
if (!ubpf_setup_custom_test( | ||
vm, | ||
program_string, | ||
[](ubpf_vm_up& vm, std::string& error) { | ||
if (ubpf_register_stack_usage_calculator(vm.get(), stack_usage_calculator, nullptr) < 0) { | ||
error = "Failed to register stack usage calculator."; | ||
return false; | ||
} | ||
return true; | ||
}, | ||
jit_fn, | ||
error)) { | ||
std::cerr << "Problem setting up custom test: " << error << std::endl; | ||
return 1; | ||
} | ||
|
||
char* ex_jit_compile_error = nullptr; | ||
auto jit_ex_fn = ubpf_compile_ex(vm.get(), &ex_jit_compile_error, ExtendedJitMode); | ||
uint8_t external_stack[stack_size] = { | ||
0, | ||
}; | ||
jit_ex_fn(nullptr, 0, external_stack, stack_size); | ||
|
||
for (size_t i = 0; i < stack_size; i++) { | ||
if (external_stack[i] != expected_result[i]) { | ||
success = false; | ||
} | ||
} | ||
return !success; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
// Copyright (c) Will Hawkins | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#include <cstdint> | ||
#include <iostream> | ||
#include <memory> | ||
#include <stdint.h> | ||
#include <vector> | ||
#include <string> | ||
|
||
extern "C" | ||
{ | ||
#include "ubpf.h" | ||
} | ||
|
||
#include "ubpf_custom_test_support.h" | ||
|
||
int | ||
stack_usage_calculator(const struct ubpf_vm* vm, uint16_t pc, void* cookie) | ||
{ | ||
UNREFERENCED_PARAMETER(vm); | ||
UNREFERENCED_PARAMETER(pc); | ||
UNREFERENCED_PARAMETER(cookie); | ||
return 16; | ||
} | ||
|
||
int | ||
overwrite_stack_usage_calculator(const struct ubpf_vm* vm, uint16_t pc, void* cookie) | ||
{ | ||
UNREFERENCED_PARAMETER(vm); | ||
UNREFERENCED_PARAMETER(pc); | ||
UNREFERENCED_PARAMETER(cookie); | ||
return 0; | ||
} | ||
|
||
int | ||
main(int argc, char** argv) | ||
{ | ||
std::vector<std::string> args(argv, argv + argc); | ||
std::string program_string{}; | ||
ubpf_jit_fn jit_fn; | ||
|
||
std::getline(std::cin, program_string); | ||
|
||
uint64_t no_overwrite_interp_result = 0; | ||
uint64_t no_overwrite_jit_result = 0; | ||
uint64_t overwrite_interp_result = 0; | ||
uint64_t overwrite_jit_result = 0; | ||
|
||
{ | ||
|
||
std::unique_ptr<ubpf_vm, decltype(&ubpf_destroy)> vm(ubpf_create(), ubpf_destroy); | ||
std::string error{}; | ||
if (!ubpf_setup_custom_test( | ||
vm, | ||
program_string, | ||
[](ubpf_vm_up& vm, std::string& error) { | ||
if (ubpf_register_stack_usage_calculator(vm.get(), stack_usage_calculator, nullptr) < 0) { | ||
error = "Failed to register stack usage calculator."; | ||
return false; | ||
} | ||
return true; | ||
}, | ||
jit_fn, | ||
error)) { | ||
std::cerr << "Problem setting up custom test: " << error << std::endl; | ||
return 1; | ||
} | ||
|
||
no_overwrite_jit_result = jit_fn(nullptr, 0); | ||
[[maybe_unused]] auto exec_result = ubpf_exec(vm.get(), NULL, 0, &no_overwrite_interp_result); | ||
} | ||
|
||
{ | ||
|
||
std::unique_ptr<ubpf_vm, decltype(&ubpf_destroy)> vm(ubpf_create(), ubpf_destroy); | ||
std::string error{}; | ||
if (!ubpf_setup_custom_test( | ||
vm, | ||
program_string, | ||
[](ubpf_vm_up& vm, std::string& error) { | ||
if (ubpf_register_stack_usage_calculator(vm.get(), overwrite_stack_usage_calculator, nullptr) < 0) { | ||
error = "Failed to register stack usage calculator."; | ||
return false; | ||
} | ||
return true; | ||
}, | ||
jit_fn, | ||
error)) { | ||
std::cerr << "Problem setting up custom test: " << error << std::endl; | ||
return 1; | ||
} | ||
|
||
overwrite_jit_result = jit_fn(nullptr, 0); | ||
|
||
[[maybe_unused]] auto exec_result = ubpf_exec(vm.get(), NULL, 0, &overwrite_interp_result); | ||
} | ||
// ... because of the semantics of external_dispatcher, the result of the eBPF | ||
// program execution should point to the same place to which &memory points. | ||
return !( | ||
no_overwrite_interp_result == no_overwrite_jit_result && no_overwrite_interp_result == 0x5 && | ||
overwrite_interp_result == overwrite_jit_result && overwrite_interp_result == 0x37); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.