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

libbpf: Support opting out from autoloading BPF programs declaratively

Establish SEC("?abc") naming convention (i.e., adding question mark in
front of otherwise normal section name) that allows to set corresponding
program's autoload property to false. This is effectively just
a declarative way to do bpf_program__set_autoload(prog, false).

Having a way to do this declaratively in BPF code itself is useful and
convenient for various scenarios. E.g., for testing, when BPF object
consists of multiple independent BPF programs that each needs to be
tested separately. Opting out all of them by default and then setting
autoload to true for just one of them at a time simplifies testing code
(see next patch for few conversions in BPF selftests taking advantage of
this new feature).

Another real-world use case is in libbpf-tools for cases when different
BPF programs have to be picked depending on particulars of the host
kernel due to various incompatible changes (like kernel function renames
or signature change, or to pick kprobe vs fentry depending on
corresponding kernel support for the latter). Marking all the different
BPF program candidates as non-autoloaded declaratively makes this more
obvious in BPF source code and allows simpler code in user-space code.

When BPF program marked as SEC("?abc") it is otherwise treated just like
SEC("abc") and bpf_program__section_name() reported will be "abc".

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/20220419002452.632125-1-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Alexei Starovoitov
a3820c48 44df171a

+21 -10
+21 -10
tools/lib/bpf/libbpf.c
··· 302 302 void *priv; 303 303 bpf_program_clear_priv_t clear_priv; 304 304 305 - bool load; 305 + bool autoload; 306 306 bool mark_btf_static; 307 307 enum bpf_prog_type type; 308 308 enum bpf_attach_type expected_attach_type; ··· 672 672 prog->insns_cnt = prog->sec_insn_cnt; 673 673 674 674 prog->type = BPF_PROG_TYPE_UNSPEC; 675 - prog->load = true; 675 + 676 + /* libbpf's convention for SEC("?abc...") is that it's just like 677 + * SEC("abc...") but the corresponding bpf_program starts out with 678 + * autoload set to false. 679 + */ 680 + if (sec_name[0] == '?') { 681 + prog->autoload = false; 682 + /* from now on forget there was ? in section name */ 683 + sec_name++; 684 + } else { 685 + prog->autoload = true; 686 + } 676 687 677 688 prog->instances.fds = NULL; 678 689 prog->instances.nr = -1; ··· 2938 2927 } 2939 2928 2940 2929 bpf_object__for_each_program(prog, obj) { 2941 - if (!prog->load) 2930 + if (!prog->autoload) 2942 2931 continue; 2943 2932 if (prog_needs_vmlinux_btf(prog)) 2944 2933 return true; ··· 5713 5702 /* no need to apply CO-RE relocation if the program is 5714 5703 * not going to be loaded 5715 5704 */ 5716 - if (!prog->load) 5705 + if (!prog->autoload) 5717 5706 continue; 5718 5707 5719 5708 /* adjust insn_idx from section frame of reference to the local ··· 6374 6363 */ 6375 6364 if (prog_is_subprog(obj, prog)) 6376 6365 continue; 6377 - if (!prog->load) 6366 + if (!prog->autoload) 6378 6367 continue; 6379 6368 6380 6369 err = bpf_object__relocate_calls(obj, prog); ··· 6389 6378 prog = &obj->programs[i]; 6390 6379 if (prog_is_subprog(obj, prog)) 6391 6380 continue; 6392 - if (!prog->load) 6381 + if (!prog->autoload) 6393 6382 continue; 6394 6383 err = bpf_object__relocate_data(obj, prog); 6395 6384 if (err) { ··· 6986 6975 prog = &obj->programs[i]; 6987 6976 if (prog_is_subprog(obj, prog)) 6988 6977 continue; 6989 - if (!prog->load) { 6978 + if (!prog->autoload) { 6990 6979 pr_debug("prog '%s': skipped loading\n", prog->name); 6991 6980 continue; 6992 6981 } ··· 8466 8455 8467 8456 bool bpf_program__autoload(const struct bpf_program *prog) 8468 8457 { 8469 - return prog->load; 8458 + return prog->autoload; 8470 8459 } 8471 8460 8472 8461 int bpf_program__set_autoload(struct bpf_program *prog, bool autoload) ··· 8474 8463 if (prog->obj->loaded) 8475 8464 return libbpf_err(-EINVAL); 8476 8465 8477 - prog->load = autoload; 8466 + prog->autoload = autoload; 8478 8467 return 0; 8479 8468 } 8480 8469 ··· 12676 12665 struct bpf_program *prog = *s->progs[i].prog; 12677 12666 struct bpf_link **link = s->progs[i].link; 12678 12667 12679 - if (!prog->load) 12668 + if (!prog->autoload) 12680 12669 continue; 12681 12670 12682 12671 /* auto-attaching not supported for this program */