From 7a2c27c91056d363707646f715b164dd59f0617e Mon Sep 17 00:00:00 2001 From: officeyutong Date: Sat, 4 Nov 2023 20:53:18 +0800 Subject: [PATCH] Make malloc work --- .gitignore | 1 + daemon/kernel/bpf_tracer.bpf.c | 62 ++++++++++++++----- daemon/user/bpf_tracer.cpp | 6 +- daemon/user/bpftime_driver.cpp | 23 +++++-- daemon/user/bpftime_driver.hpp | 5 +- daemon/user/daemon_config.hpp | 2 +- daemon/user/handle_bpf_event.cpp | 18 +++++- runtime/src/attach/bpf_attach_ctx.cpp | 16 +++++ .../bpf_map/shared/hash_map_kernel_user.cpp | 1 + runtime/src/bpftime_shm_internal.cpp | 8 +-- runtime/src/handler/prog_handler.hpp | 3 + 11 files changed, 114 insertions(+), 31 deletions(-) diff --git a/.gitignore b/.gitignore index a757ac01..948572bc 100644 --- a/.gitignore +++ b/.gitignore @@ -14,6 +14,7 @@ test.txt test.gdb index.html* dump* +test* ### VisualStudioCode ### .vscode/settings.json .vscode/runtime.json diff --git a/daemon/kernel/bpf_tracer.bpf.c b/daemon/kernel/bpf_tracer.bpf.c index f7f9bed8..4065b849 100644 --- a/daemon/kernel/bpf_tracer.bpf.c +++ b/daemon/kernel/bpf_tracer.bpf.c @@ -185,7 +185,7 @@ static int process_bpf_prog_load_events(union bpf_attr *attr) // check whether write is success bpf_probe_read_user(&new_attr, sizeof(new_attr), attr); if (new_attr.insn_cnt != 2) { - bpf_printk("write failed\n"); + bpf_printk("bpftime: write failed\n"); } } return 0; @@ -210,6 +210,7 @@ SEC("tracepoint/syscalls/sys_enter_bpf") int tracepoint__syscalls__sys_enter_bpf(struct trace_event_raw_sys_enter *ctx) { if (!filter_target()) { + bpf_printk("bpftime: Skipping sys enter bpf"); return 0; } @@ -226,9 +227,8 @@ int tracepoint__syscalls__sys_enter_bpf(struct trace_event_raw_sys_enter *ctx) process_bpf_syscall_enter(ctx); return 0; } - -inline struct event *get_ringbuf_sys_exit_bpf_event(struct bpf_args_t *ap, - int ret) +static __always_inline struct event * +get_ringbuf_sys_exit_bpf_event(struct bpf_args_t *ap, int ret) { struct event *event = fill_basic_event_info(); if (!event) { @@ -257,47 +257,68 @@ static int process_bpf_syscall_exit(struct bpf_args_t *ap, int ret) &bpf_progs_new_fd_args_map, &pid_tgid); if (!id_ptr) return 0; /* missed entry */ - bpf_map_delete_elem(&bpf_progs_new_fd_args_map, - &pid_tgid); + // bpf_map_delete_elem(&bpf_progs_new_fd_args_map, + // &pid_tgid); struct bpf_fd_data data = { .type = BPF_FD_TYPE_PROG, .kernel_id = *id_ptr }; set_bpf_fd_data(ret, &data); - bpf_printk("bpf_prog_load exit id: %d fd: %d\n", - *id_ptr, ret); + bpf_printk( + "bpftime: bpf_prog_load exit id: %d fd: %d\n", + *id_ptr, ret); break; } - + case BPF_MAP_CREATE: { u64 pid_tgid = bpf_get_current_pid_tgid(); u32 *id_ptr = (u32 *)bpf_map_lookup_elem( &bpf_map_new_fd_args_map, &pid_tgid); if (!id_ptr) return 0; /* missed entry */ - bpf_map_delete_elem(&bpf_map_new_fd_args_map, - &pid_tgid); + u32 id = *id_ptr; + // bpf_map_delete_elem(&bpf_map_new_fd_args_map, + // &pid_tgid); struct bpf_fd_data data = { .type = BPF_FD_TYPE_MAP, - .kernel_id = *id_ptr }; + .kernel_id = id }; // record map fd and id set_bpf_fd_data(ret, &data); - bpf_printk("bpf_map_create exit id: %d fd: %d\n", - *id_ptr, ret); + bpf_printk( + "bpftime: bpf_map_create exit id: %d fd: %d\n", + id, ret); if (submit_bpf_events) { // submit event to user for record struct event *event = get_ringbuf_sys_exit_bpf_event(ap, ret); - event->bpf_data.map_id = *id_ptr; + // Make verifier happy + if (!event) + return 0; + event->bpf_data.map_id = (int)id; bpf_ringbuf_submit(event, 0); } break; } case BPF_LINK_CREATE: { + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 *id_ptr = (u32 *)bpf_map_lookup_elem( + &bpf_progs_new_fd_args_map, &pid_tgid); + if (!id_ptr) { + bpf_printk( + "bpftime: Unable to get prog id when creating link"); + return 0; /* missed entry */ + } + u32 id = *id_ptr; + // bpf_map_delete_elem(&bpf_map_new_fd_args_map, + // &pid_tgid); struct bpf_fd_data data = { .type = BPF_FD_TYPE_OTHERS, - .kernel_id = 0 }; + .kernel_id = id }; set_bpf_fd_data(ret, &data); + bpf_printk("bpftime: bpf_link_create"); if (submit_bpf_events) { + bpf_printk("bpftime: Submitting link creation"); struct event *event = get_ringbuf_sys_exit_bpf_event(ap, ret); + if (!event) + return 0; bpf_ringbuf_submit(event, 0); } break; @@ -309,6 +330,8 @@ static int process_bpf_syscall_exit(struct bpf_args_t *ap, int ret) if (submit_bpf_events) { struct event *event = get_ringbuf_sys_exit_bpf_event(ap, ret); + if (!event) + return 0; bpf_ringbuf_submit(event, 0); } break; @@ -369,6 +392,11 @@ process_perf_event_open_enter(struct trace_event_raw_sys_enter *ctx) bpf_probe_write_user((void *)new_attr.uprobe_path, &new_uprobe_path, (size_t)size); bpf_probe_write_user(attr, &new_attr, sizeof(new_attr)); + + char buf[64]; + bpf_probe_read_user_str(buf, sizeof(buf), + (void *)new_attr.uprobe_path); + bpf_printk("Writting new uprobe path: %s", buf); } return 0; } @@ -408,7 +436,7 @@ int tracepoint__syscalls__sys_enter_perf_event_open( args.cpu = (int)ctx->args[2]; bpf_probe_read_user_str(args.name_or_path, PATH_LENTH, (const void *)args.attr.uprobe_path); - + bpf_printk("Received path: %s", args.name_or_path); u64 pid_tgid = bpf_get_current_pid_tgid(); bpf_map_update_elem(&perf_event_open_param_start, &pid_tgid, &args, 0); diff --git a/daemon/user/bpf_tracer.cpp b/daemon/user/bpf_tracer.cpp index 090b8dd4..7197f269 100644 --- a/daemon/user/bpf_tracer.cpp +++ b/daemon/user/bpf_tracer.cpp @@ -78,7 +78,11 @@ int bpftime::start_daemon(struct daemon_config env) /* initialize global data (filtering options) */ obj->rodata->target_pid = env.pid; obj->rodata->enable_replace_prog = env.enable_replace_prog; - strncpy(obj->rodata->new_uprobe_path, env.new_uprobe_path, PATH_LENTH); +// strncpy(obj->rodata->new_uprobe_path, env.new_uprobe_path, +// PATH_LENTH); +#warning FIXME: currently using `/a` as the replacing executable path to uprobe perf event in the kernel, since long strings (such as bpftime_daemon it self) may break userspace memory. Find a better way to solve this in the future + strncpy(obj->rodata->new_uprobe_path, "/a", PATH_LENTH); + obj->rodata->enable_replace_uprobe = env.enable_replace_uprobe; obj->rodata->uprobe_perf_type = determine_uprobe_perf_type(); obj->rodata->kprobe_perf_type = determine_kprobe_perf_type(); diff --git a/daemon/user/bpftime_driver.cpp b/daemon/user/bpftime_driver.cpp index 6e407529..7b06fbbb 100644 --- a/daemon/user/bpftime_driver.cpp +++ b/daemon/user/bpftime_driver.cpp @@ -154,7 +154,8 @@ int bpftime_driver::bpftime_progs_create_server(int kernel_id, int server_pid) { int fd = bpf_prog_get_fd_by_id(kernel_id); if (fd < 0) { - spdlog::error("Failed to get prog fd for id {}", kernel_id); + spdlog::error("Failed to get prog fd by prog id {}, err={}", + kernel_id, errno); return -1; } spdlog::debug("get prog fd {} for id {}", fd, kernel_id); @@ -237,7 +238,20 @@ int bpftime_driver::bpftime_maps_create_server(int kernel_id) spdlog::info("create map in kernel id {}", kernel_id); return kernel_id; } - +int bpftime_driver::bpftime_attach_perf_to_bpf_fd_server(int server_pid, + int perf_fd, + int bpf_prog_fd) +{ + int prog_id = + get_bpf_map_id_from_pid_fd(object, server_pid, bpf_prog_fd); + if (prog_id < 0) { + spdlog::error( + "Failed to lookup bpf prog id from bpf prog fd {}", + bpf_prog_fd); + return -1; + } + return bpftime_attach_perf_to_bpf_server(server_pid, perf_fd, prog_id); +} int bpftime_driver::bpftime_attach_perf_to_bpf_server(int server_pid, int perf_fd, int kernel_bpf_id) @@ -254,8 +268,9 @@ int bpftime_driver::bpftime_attach_perf_to_bpf_server(int server_pid, int res = bpftime_progs_create_server(kernel_bpf_id, server_pid); if (res < 0) { - spdlog::error("Failed to create bpf for id {}", - kernel_bpf_id); + spdlog::error( + "Failed to create bpf program (userspace side) for kernel program id {}", + kernel_bpf_id); return -1; } } diff --git a/daemon/user/bpftime_driver.hpp b/daemon/user/bpftime_driver.hpp index 587b80c7..7bf528ab 100644 --- a/daemon/user/bpftime_driver.hpp +++ b/daemon/user/bpftime_driver.hpp @@ -34,7 +34,8 @@ class bpftime_driver { daemon_config config; struct bpf_tracer_bpf *object = NULL; - int check_and_create_prog_related_maps(int fd, const bpf_prog_info* info); + int check_and_create_prog_related_maps(int fd, + const bpf_prog_info *info); public: // create a bpf prog in the global shared memory @@ -51,6 +52,8 @@ class bpftime_driver { int bpftime_attach_perf_to_bpf_server(int server_pid, int perf_fd, int kernel_bpf_id); + int bpftime_attach_perf_to_bpf_fd_server(int server_pid, int perf_fd, + int bpf_prog_fd); // create uprobe in the global shared memory // diff --git a/daemon/user/daemon_config.hpp b/daemon/user/daemon_config.hpp index 5ff1cd50..d72dd2b4 100644 --- a/daemon/user/daemon_config.hpp +++ b/daemon/user/daemon_config.hpp @@ -29,7 +29,7 @@ struct daemon_config { // should bpftime be involve bool is_driving_bpftime = true; - bool submit_bpf_events = false; + bool submit_bpf_events = true; }; #endif // BPFTIME_DAEMON_CONFIG_HPP diff --git a/daemon/user/handle_bpf_event.cpp b/daemon/user/handle_bpf_event.cpp index ff9e1ea8..e2817782 100644 --- a/daemon/user/handle_bpf_event.cpp +++ b/daemon/user/handle_bpf_event.cpp @@ -215,12 +215,24 @@ int bpf_event_handler::handle_bpf_event(const struct event *e) (enum bpf_map_type)e->bpf_data.attr.map_type), e->bpf_data.attr.map_name, e->bpf_data.map_id); break; - case BPF_LINK_CREATE: + case BPF_LINK_CREATE: { + int prog_fd = e->bpf_data.attr.link_create.prog_fd; + int perf = e->bpf_data.attr.link_create.target_fd; /* code */ spdlog::info(" BPF_LINK_CREATE prog_fd:{} target_fd:{}", - e->bpf_data.attr.link_create.prog_fd, - e->bpf_data.attr.link_create.target_fd); + prog_fd, perf); + if (config.is_driving_bpftime) { + if (int err = + driver.bpftime_attach_perf_to_bpf_fd_server( + e->pid, perf, prog_fd); + err < 0) { + spdlog::warn( + "Unable to attach perf {} to bpf prog {}, err={}", + perf, prog_fd, err); + } + } break; + } case BPF_PROG_LOAD: /* code */ spdlog::info( diff --git a/runtime/src/attach/bpf_attach_ctx.cpp b/runtime/src/attach/bpf_attach_ctx.cpp index e7fe4448..b5aa5bed 100644 --- a/runtime/src/attach/bpf_attach_ctx.cpp +++ b/runtime/src/attach/bpf_attach_ctx.cpp @@ -248,6 +248,9 @@ int bpf_attach_ctx::init_attach_ctx_from_handlers( // attach base on events switch (event_handler.type) { case bpf_event_type::BPF_TYPE_FILTER: { + spdlog::debug( + "Creating filter for perf event fd {}", + i); auto progs = handler_prog_fds[i]; if (progs.size() > 1) { spdlog::error( @@ -273,6 +276,9 @@ int bpf_attach_ctx::init_attach_ctx_from_handlers( break; } case bpf_event_type::BPF_TYPE_REPLACE: { + spdlog::debug( + "Creating replace for perf event fd {}", + i); auto progs = handler_prog_fds[i]; if (progs.size() > 1) { spdlog::error( @@ -307,8 +313,12 @@ int bpf_attach_ctx::init_attach_ctx_from_handlers( progs.size(), (uintptr_t)func_addr); err = attach_manager->attach_uprobe_at( func_addr, [=](const pt_regs ®s) { + spdlog::trace( + "Uprobe triggered"); uint64_t ret; for (auto &[k, prog] : progs) { + spdlog::trace( + "Calling ebpf programs in uprobe callback"); prog->bpftime_prog_exec( (void *)®s, sizeof(regs), @@ -346,6 +356,9 @@ int bpf_attach_ctx::init_attach_ctx_from_handlers( break; } case bpf_event_type::PERF_TYPE_TRACEPOINT: { + spdlog::debug( + "Creating tracepoint for perf event fd {}", + i); err = create_tracepoint( event_handler.tracepoint_id, i, manager); @@ -361,8 +374,11 @@ int bpf_attach_ctx::init_attach_ctx_from_handlers( spdlog::debug( "Attaching software perf event, nothing need to do"); err = i; + break; } default: + spdlog::warn("Unexpected bpf_event_type: {}", + (int)event_handler.type); break; } spdlog::debug("Create attach event {} {} {} for {}", i, diff --git a/runtime/src/bpf_map/shared/hash_map_kernel_user.cpp b/runtime/src/bpf_map/shared/hash_map_kernel_user.cpp index bab0f824..23e0668b 100644 --- a/runtime/src/bpf_map/shared/hash_map_kernel_user.cpp +++ b/runtime/src/bpf_map/shared/hash_map_kernel_user.cpp @@ -59,6 +59,7 @@ long hash_map_kernel_user_impl::elem_update(const void *key, const void *value, if (map_fd < 0) { init_map_fd(); } + spdlog::debug("Update shared hash map"); // Allocate as a local variable to make // it thread safe, since we use sharable lock return bpf_map_update_elem(map_fd, key, value, flags); diff --git a/runtime/src/bpftime_shm_internal.cpp b/runtime/src/bpftime_shm_internal.cpp index e8c9e696..7e21188e 100644 --- a/runtime/src/bpftime_shm_internal.cpp +++ b/runtime/src/bpftime_shm_internal.cpp @@ -176,6 +176,8 @@ int bpftime_shm::attach_perf_to_bpf(int perf_fd, int bpf_fd) int bpftime_shm::add_bpf_prog_attach_target(int perf_fd, int bpf_fd) { + spdlog::debug("Try attaching prog fd {} to perf fd {}", bpf_fd, + perf_fd); if (!is_prog_fd(bpf_fd)) { spdlog::error("Fd {} not prog fd", bpf_fd); errno = ENOENT; @@ -228,8 +230,7 @@ int bpftime_shm::add_software_perf_event_to_epoll(int swpe_fd, int epoll_fd, } auto &perf_handler = std::get(manager->get_handler(swpe_fd)); - if (perf_handler.type != - bpf_event_type::PERF_TYPE_SOFTWARE) { + if (perf_handler.type != bpf_event_type::PERF_TYPE_SOFTWARE) { spdlog::error( "Expected perf fd {} to be a software perf event instance", swpe_fd); @@ -554,8 +555,7 @@ bool bpftime_shm::is_software_perf_event_handler_fd(int fd) const if (!is_perf_event_handler_fd(fd)) return false; const auto &hd = std::get(get_handler(fd)); - return hd.type == - bpf_event_type::PERF_TYPE_SOFTWARE; + return hd.type == bpf_event_type::PERF_TYPE_SOFTWARE; } bpftime::agent_config &bpftime_get_agent_config() diff --git a/runtime/src/handler/prog_handler.hpp b/runtime/src/handler/prog_handler.hpp index d369f2a7..f57f3ad0 100644 --- a/runtime/src/handler/prog_handler.hpp +++ b/runtime/src/handler/prog_handler.hpp @@ -1,5 +1,6 @@ #ifndef _PROG_HANDLER_HPP #define _PROG_HANDLER_HPP +#include "spdlog/spdlog.h" #include #include #include @@ -56,6 +57,8 @@ class bpf_prog_handler { void add_attach_fd(int fd) const { + spdlog::debug("Add attach fd {} for bpf_prog {}", fd, + name.c_str()); attach_fds.push_back(fd); }