Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

libbpf: Auto-detect btf_id of BTF-based raw_tracepoints

It's a responsiblity of bpf program author to annotate the program
with SEC("tp_btf/name") where "name" is a valid raw tracepoint.
The libbpf will try to find "name" in vmlinux BTF and error out
in case vmlinux BTF is not available or "name" is not found.
If "name" is indeed a valid raw tracepoint then in-kernel BTF
will have "btf_trace_##name" typedef that points to function
prototype of that raw tracepoint. BTF description captures
exact argument the kernel C code is passing into raw tracepoint.
The kernel verifier will check the types while loading bpf program.

libbpf keeps BTF type id in expected_attach_type, but since
kernel ignores this attribute for tracing programs copy it
into attach_btf_id attribute before loading.

Later the kernel will use prog->attach_btf_id to select raw tracepoint
during bpf_raw_tracepoint_open syscall command.

Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Andrii Nakryiko <andriin@fb.com>
Acked-by: Martin KaFai Lau <kafai@fb.com>
Link: https://lore.kernel.org/bpf/20191016032505.2089704-6-ast@kernel.org

authored by

Alexei Starovoitov and committed by
Daniel Borkmann
f75a697e ccfe29eb

+35 -6
+3
tools/lib/bpf/bpf.c
··· 228 228 memset(&attr, 0, sizeof(attr)); 229 229 attr.prog_type = load_attr->prog_type; 230 230 attr.expected_attach_type = load_attr->expected_attach_type; 231 + if (attr.prog_type == BPF_PROG_TYPE_RAW_TRACEPOINT) 232 + /* expected_attach_type is ignored for tracing progs */ 233 + attr.attach_btf_id = attr.expected_attach_type; 231 234 attr.insn_cnt = (__u32)load_attr->insns_cnt; 232 235 attr.insns = ptr_to_u64(load_attr->insns); 233 236 attr.license = ptr_to_u64(load_attr->license);
+32 -6
tools/lib/bpf/libbpf.c
··· 4489 4489 prog->expected_attach_type = type; 4490 4490 } 4491 4491 4492 - #define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, atype) \ 4493 - { string, sizeof(string) - 1, ptype, eatype, is_attachable, atype } 4492 + #define BPF_PROG_SEC_IMPL(string, ptype, eatype, is_attachable, btf, atype) \ 4493 + { string, sizeof(string) - 1, ptype, eatype, is_attachable, btf, atype } 4494 4494 4495 4495 /* Programs that can NOT be attached. */ 4496 - #define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0) 4496 + #define BPF_PROG_SEC(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 0, 0) 4497 4497 4498 4498 /* Programs that can be attached. */ 4499 4499 #define BPF_APROG_SEC(string, ptype, atype) \ 4500 - BPF_PROG_SEC_IMPL(string, ptype, 0, 1, atype) 4500 + BPF_PROG_SEC_IMPL(string, ptype, 0, 1, 0, atype) 4501 4501 4502 4502 /* Programs that must specify expected attach type at load time. */ 4503 4503 #define BPF_EAPROG_SEC(string, ptype, eatype) \ 4504 - BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, eatype) 4504 + BPF_PROG_SEC_IMPL(string, ptype, eatype, 1, 0, eatype) 4505 + 4506 + /* Programs that use BTF to identify attach point */ 4507 + #define BPF_PROG_BTF(string, ptype) BPF_PROG_SEC_IMPL(string, ptype, 0, 0, 1, 0) 4505 4508 4506 4509 /* Programs that can be attached but attach type can't be identified by section 4507 4510 * name. Kept for backward compatibility. ··· 4516 4513 size_t len; 4517 4514 enum bpf_prog_type prog_type; 4518 4515 enum bpf_attach_type expected_attach_type; 4519 - int is_attachable; 4516 + bool is_attachable; 4517 + bool is_attach_btf; 4520 4518 enum bpf_attach_type attach_type; 4521 4519 } section_names[] = { 4522 4520 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), ··· 4527 4523 BPF_PROG_SEC("action", BPF_PROG_TYPE_SCHED_ACT), 4528 4524 BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT), 4529 4525 BPF_PROG_SEC("raw_tracepoint/", BPF_PROG_TYPE_RAW_TRACEPOINT), 4526 + BPF_PROG_BTF("tp_btf/", BPF_PROG_TYPE_RAW_TRACEPOINT), 4530 4527 BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP), 4531 4528 BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT), 4532 4529 BPF_PROG_SEC("lwt_in", BPF_PROG_TYPE_LWT_IN), ··· 4632 4627 continue; 4633 4628 *prog_type = section_names[i].prog_type; 4634 4629 *expected_attach_type = section_names[i].expected_attach_type; 4630 + if (section_names[i].is_attach_btf) { 4631 + struct btf *btf = bpf_core_find_kernel_btf(); 4632 + char raw_tp_btf_name[128] = "btf_trace_"; 4633 + char *dst = raw_tp_btf_name + sizeof("btf_trace_") - 1; 4634 + int ret; 4635 + 4636 + if (IS_ERR(btf)) { 4637 + pr_warning("vmlinux BTF is not found\n"); 4638 + return -EINVAL; 4639 + } 4640 + /* prepend "btf_trace_" prefix per kernel convention */ 4641 + strncat(dst, name + section_names[i].len, 4642 + sizeof(raw_tp_btf_name) - (dst - raw_tp_btf_name)); 4643 + ret = btf__find_by_name(btf, raw_tp_btf_name); 4644 + btf__free(btf); 4645 + if (ret <= 0) { 4646 + pr_warning("%s is not found in vmlinux BTF\n", dst); 4647 + return -EINVAL; 4648 + } 4649 + *expected_attach_type = ret; 4650 + } 4635 4651 return 0; 4636 4652 } 4637 4653 pr_warning("failed to guess program type based on ELF section name '%s'\n", name);