bpf/tracing: allow user space to query prog array on the same tp
Subsystems (10)
v3 cover bpf/tracing: allow user space to query prog array on the same tp
Commit e87c6bc3852b ("bpf: permit multiple bpf attachments for a single perf event") added support to attach multiple bpf programs to a single perf event. Given a perf event (kprobe, uprobe, or kernel tracepoint), the perf ioctl interface is used to query bpf programs attached to the same trace event.
There already exists a BPF_PROG_QUERY command for introspection currently used by cgroup+bpf. We did have an implementation for querying tracepoint+bpf through the same interface. However, it looks cleaner to use ioctl() style of api here, since attaching bpf prog to tracepoint/kuprobe is also done via ioctl.
Patch #1 had the core implementation and patch #2 added a test case in tools bpf selftests suite.
Changelogs:
v2 -> v3:
- Change uapi structure perf_event_query_bpf to be more clearer based on Peter's suggestion, and adjust other codes accordingly.
v1 -> v2:
- Rebase on top of net-next.
- Use existing bpf_prog_array_length function instead of implementing the same functionality in function bpf_prog_array_copy_info.
Yonghong Song (2):
bpf/tracing: allow user space to query prog array on the same tp bpf/tracing: add a bpf test for new ioctl query interface
include/linux/bpf.h | 4 + include/uapi/linux/perf_event.h | 22 +++++ kernel/bpf/core.c | 21 ++++ kernel/events/core.c | 3 + kernel/trace/bpf_trace.c | 23 +++++ tools/include/uapi/linux/perf_event.h | 22 +++++ tools/testing/selftests/bpf/Makefile | 2 +- tools/testing/selftests/bpf/test_progs.c | 134 ++++++++++++++++++++++++++ tools/testing/selftests/bpf/test_tracepoint.c | 26 +++++ 9 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/test_tracepoint.c
Signature · 1 line
2.9.5
PATCH v3 1/2 bpf/tracing: allow user space to query prog array on the same tp
Commit e87c6bc3852b ("bpf: permit multiple bpf attachments for a single perf event") added support to attach multiple bpf programs to a single perf event.
Although this provides flexibility, users may want to know what other bpf programs attached to the same tp interface. Besides getting visibility for the underlying bpf system, such information may also help consolidate multiple bpf programs, understand potential performance issues due to a large array, and debug (e.g., one bpf program which overwrites return code may impact subsequent program results).
Commit 2541517c32be ("tracing, perf: Implement BPF programs attached to kprobes") utilized the existing perf ioctl interface and added the command PERF_EVENT_IOC_SET_BPF to attach a bpf program to a tracepoint. This patch adds a new ioctl command, given a perf event fd, to query the bpf program array attached to the same perf tracepoint event.
The new uapi ioctl command:
PERF_EVENT_IOC_QUERY_BPF
The new uapi/linux/perf_event.h structure:
struct perf_event_query_bpf {
__u32 ids_len;
__u32 prog_cnt;
__u32 ids[0];};
User space provides buffer "ids" for kernel to copy to. When returning from the kernel, the number of available programs in the array is set in "prog_cnt".
The usage:
struct perf_event_query_bpf *query = malloc(...); query.ids_len = ids_len;
err = ioctl(pmu_efd, PERF_EVENT_IOC_QUERY_BPF, &query);
if (err == 0) {
/* query.prog_cnt is the number of available progs,
* number of progs in ids: (ids_len == 0) ? 0 : query.prog_cnt
*/
} else if (errno == ENOSPC) {
/* query.ids_len number of progs copied,
* query.prog_cnt is the number of available progs
*/
} else {
/* other errors */}
--- include/linux/bpf.h | 4 ++++ include/uapi/linux/perf_event.h | 22 ++++++++++++++++++++++ kernel/bpf/core.c | 21 +++++++++++++++++++++ kernel/events/core.c | 3 +++ kernel/trace/bpf_trace.c | 23 +++++++++++++++++++++++ 5 files changed, 73 insertions(+)
include/linux/bpf.h +4 -0
@@ -254,6 +254,7 @@ typedef unsigned long (*bpf_ctx_copy_t)(void *dst, const void *src,u64 bpf_event_output (struct bpf_map *map,u64 flags,void *meta,u64 meta_size,void *ctx,u64 ctx_size,bpf_ctx_copy_t ctx_copy); +int bpf_event_query_prog_array (struct perf_event *event,void __user *info);int bpf_prog_test_run_xdp (struct bpf_prog *prog,const union bpf_attr *kattr,union bpf_attr __user *uattr);
@@ -285,6 +286,9 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,void bpf_prog_array_delete_safe (struct bpf_prog_array __rcu *progs,struct bpf_prog *old_prog); +int bpf_prog_array_copy_info (struct bpf_prog_array __rcu *array, +__u32 __user *prog_ids,u32 request_cnt, +__u32 __user *prog_cnt); int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array, struct bpf_prog *exclude_prog, struct bpf_prog *include_prog,
include/uapi/linux/perf_event.h +22 -0
@@ -418,6 +418,27 @@ struct perf_event_attr {__u16 __reserved_2;/* align to __u64 */ }; +/* +* Structure used by below PERF_EVENT_IOC_QUERY_BPF command +* to query bpf programs attached to the same perf tracepoint +* as the given perf event. +*/ +struct perf_event_query_bpf { +/* +* The below ids array length +*/ +__u32 ids_len; +/* +* Set by the kernel to indicate the number of +* available programs +*/ +__u32 prog_cnt; +/* +* User provided buffer to store program ids +*/ +__u32 ids[0 ]; +}; +#define perf_flags (attr) (*(&(attr)->read_format + 1))/*
@@ -433,6 +454,7 @@ struct perf_event_attr {#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) +#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)enum perf_event_ioc_flags {PERF_IOC_FLAG_GROUP =1U <<0 ,
kernel/bpf/core.c +21 -0
@@ -1462,6 +1462,8 @@ int bpf_prog_array_copy_to_user(struct bpf_prog_array __rcu *progs,rcu_read_lock (); prog =rcu_dereference (progs)->progs;for (; *prog; prog++) { +if (*prog == &dummy_bpf_prog.prog) +continue ; id = (*prog)->aux->id;if (copy_to_user (prog_ids + i, &id,sizeof (id))) {rcu_read_unlock ();
@@ -1545,6 +1547,25 @@ int bpf_prog_array_copy(struct bpf_prog_array __rcu *old_array,return 0 ; } +int bpf_prog_array_copy_info (struct bpf_prog_array __rcu *array, +__u32 __user *prog_ids,u32 request_cnt, +__u32 __user *prog_cnt) +{ +u32 cnt =0 ; + +if (array) + cnt =bpf_prog_array_length (array); + +if (copy_to_user (prog_cnt, &cnt,sizeof (cnt))) +return -EFAULT ; + +/* return early if user requested only program count or nothing to copy */ +if (!request_cnt || !cnt) +return 0 ; + +return bpf_prog_array_copy_to_user (array, prog_ids, request_cnt); +} +static void bpf_prog_free_deferred (struct work_struct *work) {struct bpf_prog_aux *aux;
kernel/events/core.c +3 -0
@@ -4723,6 +4723,9 @@ static long _perf_ioctl(struct perf_event *event, unsigned int cmd, unsigned lonrcu_read_unlock ();return 0 ; } + +case PERF_EVENT_IOC_QUERY_BPF : +return bpf_event_query_prog_array (event, (void __user *)arg);default :return -ENOTTY ; }
kernel/trace/bpf_trace.c +23 -0
@@ -820,3 +820,26 @@ void perf_event_detach_bpf_prog(struct perf_event *event) unlock:mutex_unlock (&bpf_event_mutex); } + +int bpf_event_query_prog_array (struct perf_event *event,void __user *info) +{ +struct perf_event_query_bpf __user *uquery = info; +struct perf_event_query_bpf query = {}; +int ret; + +if (!capable (CAP_SYS_ADMIN )) +return -EPERM ; +if (event->attr.type !=PERF_TYPE_TRACEPOINT ) +return -EINVAL ; +if (copy_from_user (&query, uquery,sizeof (query))) +return -EFAULT ; + +mutex_lock (&bpf_event_mutex); + ret =bpf_prog_array_copy_info (event->tp_event->prog_array, + &uquery->ids, + query.ids_len, + &uquery->prog_cnt); +mutex_unlock (&bpf_event_mutex); + +return ret; +}
Signature · 1 line
2.9.5
Quoted 26 lines · Yonghong Song
Commit
e87c6bc3852b("bpf: permit multiple bpf attachments for a single perf event") added support to attach multiple bpf programs to a single perf event.
Although this provides flexibility, users may want to know what other bpf programs attached to the same tp interface. Besides getting visibility for the underlying bpf system, such information may also help consolidate multiple bpf programs, understand potential performance issues due to a large array, and debug (e.g., one bpf program which overwrites return code may impact subsequent program results).Commit
2541517c32be("tracing, perf: Implement BPF programs attached to kprobes") utilized the existing perf ioctl interface and added the commandPERF_EVENT_IOC_SET_BPFto attach a bpf program to a tracepoint. This patch adds a new ioctl command, given a perf event fd, to query the bpf program array attached to the same perf tracepoint event.The new uapi ioctl command:
PERF_EVENT_IOC_QUERY_BPFThe new
uapi/linux/perf_event.hstructure:struct perf_event_query_bpf { __u32 ids_len; __u32 prog_cnt; __u32 ids[0];
Quoted 7 lines
};
User space provides buffer "ids" for kernel to copy to. When returning from the kernel, the number of available programs in the array is set in "
prog_cnt".The usage:
struct perf_event_query_bpf *query =
malloc(sizeof(*query) + sizeof(u32) * ids_len);
query->ids_len = ids_len;
err = ioctl(pmu_efd, PERF_EVENT_IOC_QUERY_BPF, query);Quoted 10 lines
if (err == 0) {
/* query.prog_cnt is the number of available progs,
* number of progs in ids: (ids_len == 0) ? 0 : query.prog_cnt
*/
} else if (errno == ENOSPC) {
/* query.ids_len number of progs copied,
* query.prog_cnt is the number of available progs
*/
} else {
/* other errors */Quoted 3 lines
}
Signed-off-by Yonghong Song <[email protected]>
Yes this looks much better, thanks!
PATCH v3 2/2 bpf/tracing: add a bpf test for new ioctl query interface
In reply to Yonghong SongAdded a subtest in test_progs. The tracepoint is sched/sched_switch. Multiple bpf programs are attached to this tracepoint and the query interface is exercised.
--- tools/include/uapi/linux/perf_event.h | 22 +++++ tools/testing/selftests/bpf/Makefile | 2 +- tools/testing/selftests/bpf/test_progs.c | 134 ++++++++++++++++++++++++++ tools/testing/selftests/bpf/test_tracepoint.c | 26 +++++ 4 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/test_tracepoint.c
tools/include/uapi/linux/perf_event.h +22 -0
@@ -418,6 +418,27 @@ struct perf_event_attr {__u16 __reserved_2;/* align to __u64 */ }; +/* +* Structure used by below PERF_EVENT_IOC_QUERY_BPF command +* to query bpf programs attached to the same perf tracepoint +* as the given perf event. +*/ +struct perf_event_query_bpf { +/* +* The below ids array length +*/ +__u32 ids_len; +/* +* Set by the kernel to indicate the number of +* available programs +*/ +__u32 prog_cnt; +/* +* User provided buffer to store program ids +*/ +__u32 ids[0 ]; +}; +#define perf_flags (attr) (*(&(attr)->read_format + 1))/*
@@ -433,6 +454,7 @@ struct perf_event_attr {#define PERF_EVENT_IOC_ID _IOR('$', 7, __u64 *)#define PERF_EVENT_IOC_SET_BPF _IOW('$', 8, __u32)#define PERF_EVENT_IOC_PAUSE_OUTPUT _IOW('$', 9, __u32) +#define PERF_EVENT_IOC_QUERY_BPF _IOWR('$', 10, struct perf_event_query_bpf *)enum perf_event_ioc_flags {PERF_IOC_FLAG_GROUP =1U <<0 ,
tools/testing/selftests/bpf/Makefile +1 -1
@@ -17,7 +17,7 @@ TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test TEST_GEN_FILES = test_pkt_access.o test_xdp.o test_l4lb.o test_tcp_estats.o test_obj_id.o \ test_pkt_md_access.o test_xdp_redirect.o test_xdp_meta.o sockmap_parse_prog.o \ - sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o + sockmap_verdict_prog.o dev_cgroup.o sample_ret0.o test_tracepoint.o TEST_PROGS := test_kmod.sh test_xdp_redirect.sh test_xdp_meta.sh \ test_offload.py
tools/testing/selftests/bpf/test_progs.c +134 -0
154 lines not on this page · raw message
tools/testing/selftests/bpf/test_tracepoint.c new file +26 -0
@@ -0,0 +1,26 @@ +// SPDX-License-Identifier: GPL-2.0 +// Copyright (c) 2017 Facebook + +#include <linux/bpf.h> +#include "bpf_helpers.h" + +/* taken from /sys/kernel/debug/tracing/events/sched/sched_switch/format */ +struct sched_switch_args { +unsigned long long pad; +char prev_comm[16 ]; +int prev_pid; +int prev_prio; +long long prev_state; +char next_comm[16 ]; +int next_pid; +int next_prio; +}; + +SEC("tracepoint/sched/sched_switch") +int oncpu (struct sched_switch_args *ctx) +{ +return 0 ; +} + +char _license[] SEC("license") = "GPL"; +__u32 _version SEC("version") = 1; /* ignored by tracepoints, required by libbpf.a */
Signature · 1 line
2.9.5
Quoted 12 lines · Yonghong Song
Commit
e87c6bc3852b("bpf: permit multiple bpf attachments for a single perf event") added support to attach multiple bpf programs to a single perf event. Given a perf event (kprobe, uprobe, or kernel tracepoint), the perf ioctl interface is used to query bpf programs attached to the same trace event.There already exists a
BPF_PROG_QUERYcommand for introspection currently used by cgroup+bpf. We did have an implementation for querying tracepoint+bpf through the same interface. However, it looks cleaner to useioctl()style of api here, since attaching bpf prog to tracepoint/kuprobe is also done via ioctl.
Quoted 8 lines
Patch #1 had the core implementation and patch #2 added a test case in tools bpf selftests suite.
Changelogs:
v2 -> v3:
- Change uapi structureperf_event_query_bpfto be more clearer based on Peter's suggestion, and adjust other codes accordingly.
Peter,
could you please ack the patch 1 ?
We'd like to route the set via bpf-next -> net-next trees.
Daniel Borkmann
maintainerHey Yonghong,
Quoted 26 lines · Yonghong Song
Commit
e87c6bc3852b("bpf: permit multiple bpf attachments for a single perf event") added support to attach multiple bpf programs to a single perf event. Given a perf event (kprobe, uprobe, or kernel tracepoint), the perf ioctl interface is used to query bpf programs attached to the same trace event.There already exists a
BPF_PROG_QUERYcommand for introspection currently used by cgroup+bpf. We did have an implementation for querying tracepoint+bpf through the same interface. However, it looks cleaner to useioctl()style of api here, since attaching bpf prog to tracepoint/kuprobe is also done via ioctl.Patch #1 had the core implementation and patch #2 added a test case in tools bpf selftests suite.
Changelogs:
v2 -> v3:
- Change uapi structureperf_event_query_bpfto be more clearer based on Peter's suggestion, and adjust other codes accordingly.
v1 -> v2:
- Rebase on top of net-next.
- Use existingbpf_prog_array_lengthfunction instead of implementing the same functionality in functionbpf_prog_array_copy_info.
Quoted 3 lines
Yonghong Song (2):
bpf/tracing: allow user space to query prog array on the same tp bpf/tracing: add a bpf test for new ioctl query interface
v3 doesn't build cleanly, could you take a look & fix?
Thanks,
Daniel
$ make -j4 kernel/trace/
CHK include/config/kernel.release
HOSTCC scripts/basic/fixdep
CHK include/generated/uapi/linux/version.h
DESCEND objtool
CHK include/generated/utsrelease.h
HOSTCC /home/darkstar/trees/bpf-next/tools/objtool/fixdep.o
HOSTCC scripts/basic/bin2c
HOSTLD /home/darkstar/trees/bpf-next/tools/objtool/fixdep-in.o
LINK /home/darkstar/trees/bpf-next/tools/objtool/fixdep
CC /home/darkstar/trees/bpf-next/tools/objtool/builtin-check.o
CC /home/darkstar/trees/bpf-next/tools/objtool/arch/x86/decode.o
CC /home/darkstar/trees/bpf-next/tools/objtool/builtin-orc.o
CC /home/darkstar/trees/bpf-next/tools/objtool/exec-cmd.o
CC /home/darkstar/trees/bpf-next/tools/objtool/help.o
CC /home/darkstar/trees/bpf-next/tools/objtool/pager.o
CC /home/darkstar/trees/bpf-next/tools/objtool/parse-options.o
CC /home/darkstar/trees/bpf-next/tools/objtool/run-command.o
CC /home/darkstar/trees/bpf-next/tools/objtool/sigchain.o
CC /home/darkstar/trees/bpf-next/tools/objtool/subcmd-config.o
LD /home/darkstar/trees/bpf-next/tools/objtool/arch/x86/objtool-in.o
CC /home/darkstar/trees/bpf-next/tools/objtool/check.o
HOSTCC arch/x86/tools/relocs_32.o
HOSTCC arch/x86/tools/relocs_64.o
CC /home/darkstar/trees/bpf-next/tools/objtool/orc_gen.o
HOSTCC arch/x86/tools/relocs_common.o
LD /home/darkstar/trees/bpf-next/tools/objtool/libsubcmd-in.o
AR /home/darkstar/trees/bpf-next/tools/objtool/libsubcmd.a
HOSTLD arch/x86/tools/relocs
CC /home/darkstar/trees/bpf-next/tools/objtool/orc_dump.o
CC scripts/mod/empty.o
HOSTCC scripts/mod/mk_elfconfig
CC arch/x86/purgatory/purgatory.o
AS arch/x86/purgatory/stack.o
CC scripts/mod/devicetable-offsets.s
AS arch/x86/purgatory/setup-x86_64.o
HOSTCC scripts/kallsyms
CC arch/x86/purgatory/sha256.o
MKELF scripts/mod/elfconfig.h
CHK scripts/mod/devicetable-offsets.h
HOSTCC scripts/mod/sumversion.o
HOSTCC scripts/pnmtologo
HOSTCC scripts/mod/modpost.o
AS arch/x86/purgatory/entry64.o
CC arch/x86/purgatory/string.o
CC /home/darkstar/trees/bpf-next/tools/objtool/elf.o
LD arch/x86/purgatory/purgatory.ro
HOSTCC scripts/conmakehash
BIN2C arch/x86/purgatory/kexec-purgatory.c
CC kernel/bounds.s
CHK include/generated/timeconst.h
CHK include/generated/bounds.h
CC arch/x86/kernel/asm-offsets.s
HOSTCC scripts/recordmcount
CC /home/darkstar/trees/bpf-next/tools/objtool/special.o
CC /home/darkstar/trees/bpf-next/tools/objtool/objtool.o
CC /home/darkstar/trees/bpf-next/tools/objtool/libstring.o
CC /home/darkstar/trees/bpf-next/tools/objtool/str_error_r.o
LD /home/darkstar/trees/bpf-next/tools/objtool/objtool-in.o
HOSTCC scripts/mod/file2alias.o
Warning: synced file at 'tools/objtool/arch/x86/lib/x86-opcode-map.txt' differs from latest kernel version at 'arch/x86/lib/x86-opcode-map.txt'
LINK /home/darkstar/trees/bpf-next/tools/objtool/objtool
HOSTCC scripts/sortextable
CHK include/generated/asm-offsets.h
HOSTCC scripts/asn1_compiler
CALL scripts/checksyscalls.sh
HOSTCC scripts/sign-file
HOSTCC scripts/extract-cert
HOSTLD scripts/mod/modpost
CC kernel/trace/trace_clock.o
CC kernel/trace/ftrace.o
CC kernel/trace/ring_buffer.o
CC kernel/trace/trace.o
CC kernel/trace/trace_output.o
CC kernel/trace/trace_seq.o
CC kernel/trace/trace_stat.o
CC kernel/trace/trace_printk.o
CC kernel/trace/trace_sched_switch.o
CC kernel/trace/trace_functions.o
CC kernel/trace/trace_nop.o
CC kernel/trace/trace_functions_graph.o
CC kernel/trace/blktrace.o
CC kernel/trace/trace_events.o
CC kernel/trace/trace_export.o
CC kernel/trace/trace_syscalls.o
CC kernel/trace/trace_event_perf.o
CC kernel/trace/trace_events_filter.o
CC kernel/trace/trace_events_trigger.o
CC kernel/trace/bpf_trace.o
CC kernel/trace/trace_kprobe.o
kernel/trace/bpf_trace.c: In function ‘bpf_event_query_prog_array’:
kernel/trace/bpf_trace.c:839:12: error: passing argument 2 of ‘bpf_prog_array_copy_info’ from incompatible pointer type [-Werror=incompatible-pointer-types]
&uquery->ids,
^
In file included from kernel/trace/bpf_trace.c:11:0:
./include/linux/bpf.h:289:5: note: expected ‘__u32 * {aka unsigned int *}’ but argument is of type ‘__u32 (*)[]’
int bpf_prog_array_copy_info(struct bpf_prog_array __rcu *array,
^~~~~~~~~~~~~~~~~~~~~~~~
CC kernel/trace/power-traces.o
CC kernel/trace/rpm-traces.o
cc1: some warnings being treated as errors
scripts/Makefile.build:310: recipe for target 'kernel/trace/bpf_trace.o' failed
make[1]: *** [kernel/trace/bpf_trace.o] Error 1
make[1]: *** Waiting for unfinished jobs....
Makefile:1674: recipe for target 'kernel/trace/' failed
make: *** [kernel/trace/] Error 2