Commit 82e6b1eee6a8 ("bpf: Allow to specify user-provided bpf_cookie for BPF perf links") introduced the concept of user specified bpf_cookie, which could be accessed by BPF programs using bpf_get_attach_cookie(). For troubleshooting purposes it is convenient to expose bpf_cookie via bpftool as well, so there is no need to meddle with the target BPF program itself. $ bpftool perf pid 83 fd 9: prog_id 5 bpf_cookie: 123 tracepoint sched_process_exec Signed-off-by: Dmitrii Dolgov <9erthalion6@xxxxxxxxx> --- include/linux/trace_events.h | 4 ++-- kernel/bpf/syscall.c | 13 +++++++------ kernel/trace/bpf_trace.c | 3 ++- samples/bpf/task_fd_query_user.c | 16 ++++++++-------- tools/bpf/bpftool/perf.c | 19 +++++++++++-------- tools/lib/bpf/bpf.c | 3 ++- tools/lib/bpf/bpf.h | 2 +- tools/lib/bpf/libbpf.map | 1 + .../bpf/prog_tests/task_fd_query_rawtp.c | 10 +++++----- .../bpf/prog_tests/task_fd_query_tp.c | 4 ++-- 10 files changed, 41 insertions(+), 34 deletions(-) diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h index 50453b287615..56d9929ee2dc 100644 --- a/include/linux/trace_events.h +++ b/include/linux/trace_events.h @@ -734,7 +734,7 @@ struct bpf_raw_event_map *bpf_get_raw_tracepoint(const char *name); void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp); int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, u32 *fd_type, const char **buf, - u64 *probe_offset, u64 *probe_addr); + u64 *probe_offset, u64 *probe_addr, u64 *bpf_cookie); #else static inline unsigned int trace_call_bpf(struct trace_event_call *call, void *ctx) { @@ -772,7 +772,7 @@ static inline void bpf_put_raw_tracepoint(struct bpf_raw_event_map *btp) static inline int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, u32 *fd_type, const char **buf, u64 *probe_offset, - u64 *probe_addr) + u64 *probe_addr, u64 *bpf_cookie) { return -EOPNOTSUPP; } diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c index 45c9bb932132..fc2195cd8d38 100644 --- a/kernel/bpf/syscall.c +++ b/kernel/bpf/syscall.c @@ -4041,7 +4041,7 @@ static int bpf_task_fd_query_copy(const union bpf_attr *attr, union bpf_attr __user *uattr, u32 prog_id, u32 fd_type, const char *buf, u64 probe_offset, - u64 probe_addr) + u64 probe_addr, u64 bpf_cookie) { char __user *ubuf = u64_to_user_ptr(attr->task_fd_query.buf); u32 len = buf ? strlen(buf) : 0, input_len; @@ -4078,7 +4078,8 @@ static int bpf_task_fd_query_copy(const union bpf_attr *attr, if (put_user(prog_id, &uattr->task_fd_query.prog_id) || put_user(fd_type, &uattr->task_fd_query.fd_type) || put_user(probe_offset, &uattr->task_fd_query.probe_offset) || - put_user(probe_addr, &uattr->task_fd_query.probe_addr)) + put_user(probe_addr, &uattr->task_fd_query.probe_addr) || + put_user(bpf_cookie, &uattr->link_create.perf_event.bpf_cookie)) return -EFAULT; return err; @@ -4126,7 +4127,7 @@ static int bpf_task_fd_query(const union bpf_attr *attr, err = bpf_task_fd_query_copy(attr, uattr, raw_tp->link.prog->aux->id, BPF_FD_TYPE_RAW_TRACEPOINT, - btp->tp->name, 0, 0); + btp->tp->name, 0, 0, 0); goto put_file; } goto out_not_supp; @@ -4134,18 +4135,18 @@ static int bpf_task_fd_query(const union bpf_attr *attr, event = perf_get_event(file); if (!IS_ERR(event)) { - u64 probe_offset, probe_addr; + u64 probe_offset, probe_addr, bpf_cookie; u32 prog_id, fd_type; const char *buf; err = bpf_get_perf_event_info(event, &prog_id, &fd_type, &buf, &probe_offset, - &probe_addr); + &probe_addr, &bpf_cookie); if (!err) err = bpf_task_fd_query_copy(attr, uattr, prog_id, fd_type, buf, probe_offset, - probe_addr); + probe_addr, bpf_cookie); goto put_file; } diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c index 25ea521fb8f1..11da2a222492 100644 --- a/kernel/trace/bpf_trace.c +++ b/kernel/trace/bpf_trace.c @@ -2017,7 +2017,7 @@ int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog) int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, u32 *fd_type, const char **buf, - u64 *probe_offset, u64 *probe_addr) + u64 *probe_offset, u64 *probe_addr, u64 *bpf_cookie) { bool is_tracepoint, is_syscall_tp; struct bpf_prog *prog; @@ -2032,6 +2032,7 @@ int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id, return -EOPNOTSUPP; *prog_id = prog->aux->id; + *bpf_cookie = event->bpf_cookie; flags = event->tp_event->flags; is_tracepoint = flags & TRACE_EVENT_FL_TRACEPOINT; is_syscall_tp = is_syscall_trace_event(event->tp_event); diff --git a/samples/bpf/task_fd_query_user.c b/samples/bpf/task_fd_query_user.c index c9a0ca8351fd..7479f1c4d0b1 100644 --- a/samples/bpf/task_fd_query_user.c +++ b/samples/bpf/task_fd_query_user.c @@ -92,7 +92,7 @@ static int bpf_get_retprobe_bit(const char *event_type) static int test_debug_fs_kprobe(int link_idx, const char *fn_name, __u32 expected_fd_type) { - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 len, prog_id, fd_type; int err, event_fd; char buf[256]; @@ -101,7 +101,7 @@ static int test_debug_fs_kprobe(int link_idx, const char *fn_name, event_fd = bpf_link__fd(links[link_idx]); err = bpf_task_fd_query(getpid(), event_fd, 0, buf, &len, &prog_id, &fd_type, &probe_offset, - &probe_addr); + &probe_addr, &bpf_cookie); if (err < 0) { printf("FAIL: %s, for event_fd idx %d, fn_name %s\n", __func__, link_idx, fn_name); @@ -124,7 +124,7 @@ static int test_debug_fs_kprobe(int link_idx, const char *fn_name, static int test_nondebug_fs_kuprobe_common(const char *event_type, const char *name, __u64 offset, __u64 addr, bool is_return, char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, - __u64 *probe_offset, __u64 *probe_addr) + __u64 *probe_offset, __u64 *probe_addr, __u64 *bpf_cookie) { int is_return_bit = bpf_get_retprobe_bit(event_type); int type = bpf_find_probe_type(event_type); @@ -163,7 +163,7 @@ static int test_nondebug_fs_kuprobe_common(const char *event_type, } CHECK_PERROR_RET(bpf_task_fd_query(getpid(), fd, 0, buf, buf_len, - prog_id, fd_type, probe_offset, probe_addr) < 0); + prog_id, fd_type, probe_offset, probe_addr, bpf_cookie) < 0); err = 0; cleanup: @@ -177,7 +177,7 @@ static int test_nondebug_fs_probe(const char *event_type, const char *name, __u32 expected_ret_fd_type, char *buf, __u32 buf_len) { - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 prog_id, fd_type; int err; @@ -185,7 +185,7 @@ static int test_nondebug_fs_probe(const char *event_type, const char *name, offset, addr, is_return, buf, &buf_len, &prog_id, &fd_type, &probe_offset, - &probe_addr); + &probe_addr, &bpf_cookie); if (err < 0) { printf("FAIL: %s, " "for name %s, offset 0x%llx, addr 0x%llx, is_return %d\n", @@ -230,7 +230,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return) char buf[256], event_alias[sizeof("test_1234567890")]; const char *event_type = "uprobe"; struct perf_event_attr attr = {}; - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 len, prog_id, fd_type; int err = -1, res, kfd, efd; struct bpf_link *link; @@ -280,7 +280,7 @@ static int test_debug_fs_uprobe(char *binary_path, long offset, bool is_return) len = sizeof(buf); err = bpf_task_fd_query(getpid(), kfd, 0, buf, &len, &prog_id, &fd_type, &probe_offset, - &probe_addr); + &probe_addr, &bpf_cookie); if (err < 0) { printf("FAIL: %s, binary_path %s\n", __func__, binary_path); perror(" :"); diff --git a/tools/bpf/bpftool/perf.c b/tools/bpf/bpftool/perf.c index 50de087b0db7..3b7746795004 100644 --- a/tools/bpf/bpftool/perf.c +++ b/tools/bpf/bpftool/perf.c @@ -21,7 +21,7 @@ static int perf_query_supported; static bool has_perf_query_support(void) { - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 len, prog_id, fd_type; char buf[256]; int fd; @@ -42,7 +42,7 @@ static bool has_perf_query_support(void) errno = 0; len = sizeof(buf); bpf_task_fd_query(getpid(), fd, 0, buf, &len, &prog_id, - &fd_type, &probe_offset, &probe_addr); + &fd_type, &probe_offset, &probe_addr, &bpf_cookie); if (errno == 524 /* ENOTSUPP */) { perf_query_supported = 1; @@ -61,12 +61,14 @@ static bool has_perf_query_support(void) } static void print_perf_json(int pid, int fd, __u32 prog_id, __u32 fd_type, - char *buf, __u64 probe_offset, __u64 probe_addr) + char *buf, __u64 probe_offset, __u64 probe_addr, + __u64 bpf_cookie) { jsonw_start_object(json_wtr); jsonw_int_field(json_wtr, "pid", pid); jsonw_int_field(json_wtr, "fd", fd); jsonw_uint_field(json_wtr, "prog_id", prog_id); + jsonw_lluint_field(json_wtr, "bpf_cookie", bpf_cookie); switch (fd_type) { case BPF_FD_TYPE_RAW_TRACEPOINT: jsonw_string_field(json_wtr, "fd_type", "raw_tracepoint"); @@ -111,9 +113,10 @@ static void print_perf_json(int pid, int fd, __u32 prog_id, __u32 fd_type, } static void print_perf_plain(int pid, int fd, __u32 prog_id, __u32 fd_type, - char *buf, __u64 probe_offset, __u64 probe_addr) + char *buf, __u64 probe_offset, __u64 probe_addr, __u64 bpf_cookie) { printf("pid %d fd %d: prog_id %u ", pid, fd, prog_id); + printf("bpf_cookie: %llu ", bpf_cookie); switch (fd_type) { case BPF_FD_TYPE_RAW_TRACEPOINT: printf("raw_tracepoint %s\n", buf); @@ -150,7 +153,7 @@ static void print_perf_plain(int pid, int fd, __u32 prog_id, __u32 fd_type, static int show_proc(const char *fpath, const struct stat *sb, int tflag, struct FTW *ftwbuf) { - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 len, prog_id, fd_type; int err, pid = 0, fd = 0; const char *pch; @@ -194,16 +197,16 @@ static int show_proc(const char *fpath, const struct stat *sb, /* query (pid, fd) for potential perf events */ len = sizeof(buf); err = bpf_task_fd_query(pid, fd, 0, buf, &len, &prog_id, &fd_type, - &probe_offset, &probe_addr); + &probe_offset, &probe_addr, &bpf_cookie); if (err < 0) return 0; if (json_output) print_perf_json(pid, fd, prog_id, fd_type, buf, probe_offset, - probe_addr); + probe_addr, bpf_cookie); else print_perf_plain(pid, fd, prog_id, fd_type, buf, probe_offset, - probe_addr); + probe_addr, bpf_cookie); return 0; } diff --git a/tools/lib/bpf/bpf.c b/tools/lib/bpf/bpf.c index 94560ba31724..d8b92508918e 100644 --- a/tools/lib/bpf/bpf.c +++ b/tools/lib/bpf/bpf.c @@ -1090,7 +1090,7 @@ int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_s int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, __u64 *probe_offset, - __u64 *probe_addr) + __u64 *probe_addr, __u64 *bpf_cookie) { union bpf_attr attr = {}; int err; @@ -1108,6 +1108,7 @@ int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, *fd_type = attr.task_fd_query.fd_type; *probe_offset = attr.task_fd_query.probe_offset; *probe_addr = attr.task_fd_query.probe_addr; + *bpf_cookie = attr.link_create.perf_event.bpf_cookie; return libbpf_err_errno(err); } diff --git a/tools/lib/bpf/bpf.h b/tools/lib/bpf/bpf.h index 079cc81ac51e..80bd705eca59 100644 --- a/tools/lib/bpf/bpf.h +++ b/tools/lib/bpf/bpf.h @@ -315,7 +315,7 @@ LIBBPF_API int bpf_load_btf(const void *btf, __u32 btf_size, char *log_buf, __u32 log_buf_size, bool do_log); LIBBPF_API int bpf_task_fd_query(int pid, int fd, __u32 flags, char *buf, __u32 *buf_len, __u32 *prog_id, __u32 *fd_type, - __u64 *probe_offset, __u64 *probe_addr); + __u64 *probe_offset, __u64 *probe_addr, __u64 *bpf_cookie); enum bpf_stats_type; /* defined in up-to-date linux/bpf.h */ LIBBPF_API int bpf_enable_stats(enum bpf_stats_type type); diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 69bc069f0a68..ca25f33f8b48 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -106,6 +106,7 @@ LIBBPF_0.0.1 { bpf_raw_tracepoint_open; bpf_set_link_xdp_fd; bpf_task_fd_query; + bpf_task_fd_query2; bpf_verify_program; btf__fd; btf__find_by_name; diff --git a/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c b/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c index 17947c9e1d66..0dbe91df96ef 100644 --- a/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c +++ b/tools/testing/selftests/bpf/prog_tests/task_fd_query_rawtp.c @@ -4,7 +4,7 @@ void test_task_fd_query_rawtp(void) { const char *file = "./test_get_stack_rawtp.o"; - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 len, prog_id, fd_type; struct bpf_object *obj; int efd, err, prog_fd; @@ -22,7 +22,7 @@ void test_task_fd_query_rawtp(void) /* query (getpid(), efd) */ len = sizeof(buf); err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id, - &fd_type, &probe_offset, &probe_addr); + &fd_type, &probe_offset, &probe_addr, &bpf_cookie); if (CHECK(err < 0, "bpf_task_fd_query", "err %d errno %d\n", err, errno)) goto close_prog; @@ -36,7 +36,7 @@ void test_task_fd_query_rawtp(void) /* test zero len */ len = 0; err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id, - &fd_type, &probe_offset, &probe_addr); + &fd_type, &probe_offset, &probe_addr, &bpf_cookie); if (CHECK(err < 0, "bpf_task_fd_query (len = 0)", "err %d errno %d\n", err, errno)) goto close_prog; @@ -48,7 +48,7 @@ void test_task_fd_query_rawtp(void) /* test empty buffer */ len = sizeof(buf); err = bpf_task_fd_query(getpid(), efd, 0, 0, &len, &prog_id, - &fd_type, &probe_offset, &probe_addr); + &fd_type, &probe_offset, &probe_addr, &bpf_cookie); if (CHECK(err < 0, "bpf_task_fd_query (buf = 0)", "err %d errno %d\n", err, errno)) goto close_prog; @@ -60,7 +60,7 @@ void test_task_fd_query_rawtp(void) /* test smaller buffer */ len = 3; err = bpf_task_fd_query(getpid(), efd, 0, buf, &len, &prog_id, - &fd_type, &probe_offset, &probe_addr); + &fd_type, &probe_offset, &probe_addr, &bpf_cookie); if (CHECK(err >= 0 || errno != ENOSPC, "bpf_task_fd_query (len = 3)", "err %d errno %d\n", err, errno)) goto close_prog; diff --git a/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c b/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c index c2a98a7a8dfc..5fbb61d52a2e 100644 --- a/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c +++ b/tools/testing/selftests/bpf/prog_tests/task_fd_query_tp.c @@ -7,7 +7,7 @@ static void test_task_fd_query_tp_core(const char *probe_name, const char *file = "./test_tracepoint.o"; int err, bytes, efd, prog_fd, pmu_fd; struct perf_event_attr attr = {}; - __u64 probe_offset, probe_addr; + __u64 probe_offset, probe_addr, bpf_cookie; __u32 len, prog_id, fd_type; struct bpf_object *obj = NULL; __u32 duration = 0; @@ -52,7 +52,7 @@ static void test_task_fd_query_tp_core(const char *probe_name, /* query (getpid(), pmu_fd) */ len = sizeof(buf); err = bpf_task_fd_query(getpid(), pmu_fd, 0, buf, &len, &prog_id, - &fd_type, &probe_offset, &probe_addr); + &fd_type, &probe_offset, &probe_addr, &bpf_cookie); if (CHECK(err < 0, "bpf_task_fd_query", "err %d errno %d\n", err, errno)) goto close_pmu; -- 2.32.0