From 1e96b3a5b4af406265817e67e0027faebb80e748 Mon Sep 17 00:00:00 2001 From: yunwei37 <1067852565@qq.com> Date: Wed, 22 Nov 2023 08:58:27 +0000 Subject: [PATCH] add error injection demo --- README.md | 4 ++++ example/error-inject/.gitignore | 3 ++- example/error-inject/README.md | 19 +++++++++++++++++++ example/error-inject/error_inject.bpf.c | 9 +++++++-- example/error-inject/victim.c | 23 +++++++++++++++++++++++ runtime/src/bpf_helper.cpp | 13 ++++++++++++- 6 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 example/error-inject/README.md create mode 100644 example/error-inject/victim.c diff --git a/README.md b/README.md index 4b1ee5ef..d5e1de89 100644 --- a/README.md +++ b/README.md @@ -121,6 +121,10 @@ More bcc/libbpf-tools examples can be found in [example/libbpf-tools](https://gi You can also run bpftime with `bpftrace`, we've test it on [this commit](https://github.com/iovisor/bpftrace/commit/75aca47dd8e1d642ff31c9d3ce330e0c616e5b96). More details about how to run bpftrace in usespace, can be found in [example/bpftrace](https://github.com/eunomia-bpf/bpftime/tree/master/example/bpftrace). +### Error injections + +- [`error-injection`](https://github.com/eunomia-bpf/bpftime/tree/master/example/error-inject) Inject errors into a userspace function to test its error handling capabilities. + > ⚠️ **Note**: `bpftime` is actively under development, and it's not yet recommended for production use. See our [roadmap](#roadmap) for details. We'd love to hear your feedback and suggestions! Please feel free to open an issue or [Contact us](#contact-and-citations). ## In-Depth diff --git a/example/error-inject/.gitignore b/example/error-inject/.gitignore index 7a710b39..a4c46eb1 100644 --- a/example/error-inject/.gitignore +++ b/example/error-inject/.gitignore @@ -1,2 +1,3 @@ error_inject -.output/ \ No newline at end of file +.output/ +victim diff --git a/example/error-inject/README.md b/example/error-inject/README.md new file mode 100644 index 00000000..4c3227ad --- /dev/null +++ b/example/error-inject/README.md @@ -0,0 +1,19 @@ +# error-inject + +bpftime can allow you override the execution of a function in userspace, and return a value you specify, or error injection in the system call. + +It's useful for testing the error handling of your program. + +## Run for override userspace function + +server + +```sh +LD_PRELOAD=~/.bpftime/libbpftime-syscall-server.so ./error_inject +``` + +client + +```sh +LD_PRELOAD=~/.bpftime/libbpftime-agent.so ./victim +``` diff --git a/example/error-inject/error_inject.bpf.c b/example/error-inject/error_inject.bpf.c index d3612165..b88847c0 100644 --- a/example/error-inject/error_inject.bpf.c +++ b/example/error-inject/error_inject.bpf.c @@ -6,8 +6,13 @@ SEC("uprobe") int do_error_inject_patch(struct pt_regs *ctx) { - bpf_printk("target_func called is overrided.\n"); - bpf_override_return(ctx, 0); + int rand = bpf_get_prandom_u32(); + if (rand % 2 == 0) { + bpf_printk("bpf: Inject error. Target func will not exec.\n"); + bpf_override_return(ctx, -1); + return 0; + } + bpf_printk("bpf: Continue.\n"); return 0; } diff --git a/example/error-inject/victim.c b/example/error-inject/victim.c new file mode 100644 index 00000000..964e0290 --- /dev/null +++ b/example/error-inject/victim.c @@ -0,0 +1,23 @@ +#include +#include +#include + +int target_func() +{ + int res = open("/dev/null"); + printf("target_func is running\n"); + close(res); + return 0; +} + +int main(int argc, char *argv[]) +{ + while (1) { + sleep(1); + int res = target_func(); + if (res != 0) { + printf("got error %d\n", res); + } + } + return 0; +} diff --git a/runtime/src/bpf_helper.cpp b/runtime/src/bpf_helper.cpp index d38415b8..7bbb62d7 100644 --- a/runtime/src/bpf_helper.cpp +++ b/runtime/src/bpf_helper.cpp @@ -68,6 +68,11 @@ uint64_t bpftime_probe_read(uint64_t dst, uint64_t size, uint64_t ptr, uint64_t, return 0; } +uint64_t bpftime_get_prandom_u32() +{ + return (uint32_t)rand(); +} + uint64_t bpftime_ktime_get_coarse_ns(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t) { @@ -613,6 +618,12 @@ const bpftime_helper_group kernel_helper_group = { .name = "bpf_trace_printk", .fn = (void *)bpftime_trace_printk, } }, + { BPF_FUNC_get_prandom_u32, + bpftime_helper_info{ + .index = BPF_FUNC_get_prandom_u32, + .name = "bpf_get_prandom_u32", + .fn = (void *)bpftime_get_prandom_u32, + } }, { BPF_FUNC_get_current_pid_tgid, bpftime_helper_info{ .index = BPF_FUNC_get_current_pid_tgid, @@ -629,7 +640,7 @@ const bpftime_helper_group kernel_helper_group = { .name = "bpf_get_current_comm", .fn = (void *)bpftime_get_current_comm, } }, - { BPF_FUNC_override_return, + { BPF_FUNC_override_return, bpftime_helper_info{ .index = BPF_FUNC_override_return, .name = "bpf_override_return",