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

Merge branch 'libbpf: Streamline internal BPF program sections handling'

Andrii Nakryiko says:

====================

This small patch set performs internal refactorings around libbpf BPF program
ELF section definitions' handling. This is preparatory changes for further
changes around making libbpf BPF program section handling more strict but also
pluggable and customizable, as part of the libbpf 1.0 effort. See individual
patches for details.
====================

Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+95 -117
+92 -108
tools/lib/bpf/libbpf.c
··· 218 218 219 219 struct bpf_sec_def; 220 220 221 - typedef struct bpf_link *(*attach_fn_t)(const struct bpf_sec_def *sec, 222 - struct bpf_program *prog); 221 + typedef struct bpf_link *(*attach_fn_t)(struct bpf_program *prog); 223 222 224 223 struct bpf_sec_def { 225 224 const char *sec; ··· 6372 6373 6373 6374 static const struct bpf_sec_def *find_sec_def(const char *sec_name); 6374 6375 6376 + static int bpf_object_init_progs(struct bpf_object *obj, const struct bpf_object_open_opts *opts) 6377 + { 6378 + struct bpf_program *prog; 6379 + 6380 + bpf_object__for_each_program(prog, obj) { 6381 + prog->sec_def = find_sec_def(prog->sec_name); 6382 + if (!prog->sec_def) { 6383 + /* couldn't guess, but user might manually specify */ 6384 + pr_debug("prog '%s': unrecognized ELF section name '%s'\n", 6385 + prog->name, prog->sec_name); 6386 + continue; 6387 + } 6388 + 6389 + if (prog->sec_def->is_sleepable) 6390 + prog->prog_flags |= BPF_F_SLEEPABLE; 6391 + bpf_program__set_type(prog, prog->sec_def->prog_type); 6392 + bpf_program__set_expected_attach_type(prog, prog->sec_def->expected_attach_type); 6393 + 6394 + if (prog->sec_def->prog_type == BPF_PROG_TYPE_TRACING || 6395 + prog->sec_def->prog_type == BPF_PROG_TYPE_EXT) 6396 + prog->attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0); 6397 + } 6398 + 6399 + return 0; 6400 + } 6401 + 6375 6402 static struct bpf_object * 6376 6403 __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz, 6377 6404 const struct bpf_object_open_opts *opts) 6378 6405 { 6379 6406 const char *obj_name, *kconfig, *btf_tmp_path; 6380 - struct bpf_program *prog; 6381 6407 struct bpf_object *obj; 6382 6408 char tmp_name[64]; 6383 6409 int err; ··· 6460 6436 err = err ? : bpf_object__collect_externs(obj); 6461 6437 err = err ? : bpf_object__finalize_btf(obj); 6462 6438 err = err ? : bpf_object__init_maps(obj, opts); 6439 + err = err ? : bpf_object_init_progs(obj, opts); 6463 6440 err = err ? : bpf_object__collect_relos(obj); 6464 6441 if (err) 6465 6442 goto out; 6443 + 6466 6444 bpf_object__elf_finish(obj); 6467 - 6468 - bpf_object__for_each_program(prog, obj) { 6469 - prog->sec_def = find_sec_def(prog->sec_name); 6470 - if (!prog->sec_def) { 6471 - /* couldn't guess, but user might manually specify */ 6472 - pr_debug("prog '%s': unrecognized ELF section name '%s'\n", 6473 - prog->name, prog->sec_name); 6474 - continue; 6475 - } 6476 - 6477 - if (prog->sec_def->is_sleepable) 6478 - prog->prog_flags |= BPF_F_SLEEPABLE; 6479 - bpf_program__set_type(prog, prog->sec_def->prog_type); 6480 - bpf_program__set_expected_attach_type(prog, 6481 - prog->sec_def->expected_attach_type); 6482 - 6483 - if (prog->sec_def->prog_type == BPF_PROG_TYPE_TRACING || 6484 - prog->sec_def->prog_type == BPF_PROG_TYPE_EXT) 6485 - prog->attach_prog_fd = OPTS_GET(opts, attach_prog_fd, 0); 6486 - } 6487 6445 6488 6446 return obj; 6489 6447 out: ··· 7919 7913 __VA_ARGS__ \ 7920 7914 } 7921 7915 7922 - static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec, 7923 - struct bpf_program *prog); 7924 - static struct bpf_link *attach_tp(const struct bpf_sec_def *sec, 7925 - struct bpf_program *prog); 7926 - static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec, 7927 - struct bpf_program *prog); 7928 - static struct bpf_link *attach_trace(const struct bpf_sec_def *sec, 7929 - struct bpf_program *prog); 7930 - static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec, 7931 - struct bpf_program *prog); 7932 - static struct bpf_link *attach_iter(const struct bpf_sec_def *sec, 7933 - struct bpf_program *prog); 7916 + static struct bpf_link *attach_kprobe(struct bpf_program *prog); 7917 + static struct bpf_link *attach_tp(struct bpf_program *prog); 7918 + static struct bpf_link *attach_raw_tp(struct bpf_program *prog); 7919 + static struct bpf_link *attach_trace(struct bpf_program *prog); 7920 + static struct bpf_link *attach_lsm(struct bpf_program *prog); 7921 + static struct bpf_link *attach_iter(struct bpf_program *prog); 7934 7922 7935 7923 static const struct bpf_sec_def section_defs[] = { 7936 7924 BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), ··· 8250 8250 return -EINVAL; 8251 8251 } 8252 8252 8253 - if (prog->type == BPF_PROG_TYPE_UNSPEC) { 8254 - const struct bpf_sec_def *sec_def; 8253 + /* prevent the use of BPF prog with invalid type */ 8254 + if (prog->type != BPF_PROG_TYPE_STRUCT_OPS) { 8255 + pr_warn("struct_ops reloc %s: prog %s is not struct_ops BPF program\n", 8256 + map->name, prog->name); 8257 + return -EINVAL; 8258 + } 8255 8259 8256 - sec_def = find_sec_def(prog->sec_name); 8257 - if (sec_def && 8258 - sec_def->prog_type != BPF_PROG_TYPE_STRUCT_OPS) { 8259 - /* for pr_warn */ 8260 - prog->type = sec_def->prog_type; 8261 - goto invalid_prog; 8262 - } 8263 - 8264 - prog->type = BPF_PROG_TYPE_STRUCT_OPS; 8260 + /* if we haven't yet processed this BPF program, record proper 8261 + * attach_btf_id and member_idx 8262 + */ 8263 + if (!prog->attach_btf_id) { 8265 8264 prog->attach_btf_id = st_ops->type_id; 8266 8265 prog->expected_attach_type = member_idx; 8267 - } else if (prog->type != BPF_PROG_TYPE_STRUCT_OPS || 8268 - prog->attach_btf_id != st_ops->type_id || 8269 - prog->expected_attach_type != member_idx) { 8270 - goto invalid_prog; 8271 8266 } 8267 + 8268 + /* struct_ops BPF prog can be re-used between multiple 8269 + * .struct_ops as long as it's the same struct_ops struct 8270 + * definition and the same function pointer field 8271 + */ 8272 + if (prog->attach_btf_id != st_ops->type_id || 8273 + prog->expected_attach_type != member_idx) { 8274 + pr_warn("struct_ops reloc %s: cannot use prog %s in sec %s with type %u attach_btf_id %u expected_attach_type %u for func ptr %s\n", 8275 + map->name, prog->name, prog->sec_name, prog->type, 8276 + prog->attach_btf_id, prog->expected_attach_type, name); 8277 + return -EINVAL; 8278 + } 8279 + 8272 8280 st_ops->progs[member_idx] = prog; 8273 8281 } 8274 8282 8275 8283 return 0; 8276 - 8277 - invalid_prog: 8278 - pr_warn("struct_ops reloc %s: cannot use prog %s in sec %s with type %u attach_btf_id %u expected_attach_type %u for func ptr %s\n", 8279 - map->name, prog->name, prog->sec_name, prog->type, 8280 - prog->attach_btf_id, prog->expected_attach_type, name); 8281 - return -EINVAL; 8282 8284 } 8283 8285 8284 8286 #define BTF_TRACE_PREFIX "btf_trace_" ··· 8438 8436 __u32 attach_prog_fd = prog->attach_prog_fd; 8439 8437 const char *name = prog->sec_name, *attach_name; 8440 8438 const struct bpf_sec_def *sec = NULL; 8441 - int i, err = 0; 8439 + int err = 0; 8442 8440 8443 8441 if (!name) 8444 8442 return -EINVAL; 8445 8443 8446 - for (i = 0; i < ARRAY_SIZE(section_defs); i++) { 8447 - if (!section_defs[i].is_attach_btf) 8448 - continue; 8449 - if (strncmp(name, section_defs[i].sec, section_defs[i].len)) 8450 - continue; 8451 - 8452 - sec = &section_defs[i]; 8453 - break; 8454 - } 8455 - 8456 - if (!sec) { 8444 + sec = find_sec_def(name); 8445 + if (!sec || !sec->is_attach_btf) { 8457 8446 pr_warn("failed to identify BTF ID based on ELF section name '%s'\n", name); 8458 8447 return -ESRCH; 8459 8448 } ··· 8482 8489 enum bpf_attach_type *attach_type) 8483 8490 { 8484 8491 char *type_names; 8485 - int i; 8492 + const struct bpf_sec_def *sec_def; 8486 8493 8487 8494 if (!name) 8488 8495 return libbpf_err(-EINVAL); 8489 8496 8490 - for (i = 0; i < ARRAY_SIZE(section_defs); i++) { 8491 - if (strncmp(name, section_defs[i].sec, section_defs[i].len)) 8492 - continue; 8493 - if (!section_defs[i].is_attachable) 8494 - return libbpf_err(-EINVAL); 8495 - *attach_type = section_defs[i].expected_attach_type; 8496 - return 0; 8497 - } 8498 - pr_debug("failed to guess attach type based on ELF section name '%s'\n", name); 8499 - type_names = libbpf_get_type_names(true); 8500 - if (type_names != NULL) { 8501 - pr_debug("attachable section(type) names are:%s\n", type_names); 8502 - free(type_names); 8497 + sec_def = find_sec_def(name); 8498 + if (!sec_def) { 8499 + pr_debug("failed to guess attach type based on ELF section name '%s'\n", name); 8500 + type_names = libbpf_get_type_names(true); 8501 + if (type_names != NULL) { 8502 + pr_debug("attachable section(type) names are:%s\n", type_names); 8503 + free(type_names); 8504 + } 8505 + 8506 + return libbpf_err(-EINVAL); 8503 8507 } 8504 8508 8505 - return libbpf_err(-EINVAL); 8509 + if (!sec_def->is_attachable) 8510 + return libbpf_err(-EINVAL); 8511 + 8512 + *attach_type = sec_def->expected_attach_type; 8513 + return 0; 8506 8514 } 8507 8515 8508 8516 int bpf_map__fd(const struct bpf_map *map) ··· 9376 9382 return bpf_program__attach_kprobe_opts(prog, func_name, &opts); 9377 9383 } 9378 9384 9379 - static struct bpf_link *attach_kprobe(const struct bpf_sec_def *sec, 9380 - struct bpf_program *prog) 9385 + static struct bpf_link *attach_kprobe(struct bpf_program *prog) 9381 9386 { 9382 9387 DECLARE_LIBBPF_OPTS(bpf_kprobe_opts, opts); 9383 9388 unsigned long offset = 0; ··· 9385 9392 char *func; 9386 9393 int n, err; 9387 9394 9388 - func_name = prog->sec_name + sec->len; 9389 - opts.retprobe = strcmp(sec->sec, "kretprobe/") == 0; 9395 + func_name = prog->sec_name + prog->sec_def->len; 9396 + opts.retprobe = strcmp(prog->sec_def->sec, "kretprobe/") == 0; 9390 9397 9391 9398 n = sscanf(func_name, "%m[a-zA-Z0-9_.]+%li", &func, &offset); 9392 9399 if (n < 1) { ··· 9549 9556 return bpf_program__attach_tracepoint_opts(prog, tp_category, tp_name, NULL); 9550 9557 } 9551 9558 9552 - static struct bpf_link *attach_tp(const struct bpf_sec_def *sec, 9553 - struct bpf_program *prog) 9559 + static struct bpf_link *attach_tp(struct bpf_program *prog) 9554 9560 { 9555 9561 char *sec_name, *tp_cat, *tp_name; 9556 9562 struct bpf_link *link; ··· 9559 9567 return libbpf_err_ptr(-ENOMEM); 9560 9568 9561 9569 /* extract "tp/<category>/<name>" */ 9562 - tp_cat = sec_name + sec->len; 9570 + tp_cat = sec_name + prog->sec_def->len; 9563 9571 tp_name = strchr(tp_cat, '/'); 9564 9572 if (!tp_name) { 9565 9573 free(sec_name); ··· 9603 9611 return link; 9604 9612 } 9605 9613 9606 - static struct bpf_link *attach_raw_tp(const struct bpf_sec_def *sec, 9607 - struct bpf_program *prog) 9614 + static struct bpf_link *attach_raw_tp(struct bpf_program *prog) 9608 9615 { 9609 - const char *tp_name = prog->sec_name + sec->len; 9616 + const char *tp_name = prog->sec_name + prog->sec_def->len; 9610 9617 9611 9618 return bpf_program__attach_raw_tracepoint(prog, tp_name); 9612 9619 } ··· 9650 9659 return bpf_program__attach_btf_id(prog); 9651 9660 } 9652 9661 9653 - static struct bpf_link *attach_trace(const struct bpf_sec_def *sec, 9654 - struct bpf_program *prog) 9662 + static struct bpf_link *attach_trace(struct bpf_program *prog) 9655 9663 { 9656 9664 return bpf_program__attach_trace(prog); 9657 9665 } 9658 9666 9659 - static struct bpf_link *attach_lsm(const struct bpf_sec_def *sec, 9660 - struct bpf_program *prog) 9667 + static struct bpf_link *attach_lsm(struct bpf_program *prog) 9661 9668 { 9662 9669 return bpf_program__attach_lsm(prog); 9663 9670 } ··· 9786 9797 return link; 9787 9798 } 9788 9799 9789 - static struct bpf_link *attach_iter(const struct bpf_sec_def *sec, 9790 - struct bpf_program *prog) 9800 + static struct bpf_link *attach_iter(struct bpf_program *prog) 9791 9801 { 9792 9802 return bpf_program__attach_iter(prog, NULL); 9793 9803 } 9794 9804 9795 9805 struct bpf_link *bpf_program__attach(struct bpf_program *prog) 9796 9806 { 9797 - const struct bpf_sec_def *sec_def; 9798 - 9799 - sec_def = find_sec_def(prog->sec_name); 9800 - if (!sec_def || !sec_def->attach_fn) 9807 + if (!prog->sec_def || !prog->sec_def->attach_fn) 9801 9808 return libbpf_err_ptr(-ESRCH); 9802 9809 9803 - return sec_def->attach_fn(sec_def, prog); 9810 + return prog->sec_def->attach_fn(prog); 9804 9811 } 9805 9812 9806 9813 static int bpf_link__detach_struct_ops(struct bpf_link *link) ··· 10875 10890 for (i = 0; i < s->prog_cnt; i++) { 10876 10891 struct bpf_program *prog = *s->progs[i].prog; 10877 10892 struct bpf_link **link = s->progs[i].link; 10878 - const struct bpf_sec_def *sec_def; 10879 10893 10880 10894 if (!prog->load) 10881 10895 continue; 10882 10896 10883 - sec_def = find_sec_def(prog->sec_name); 10884 - if (!sec_def || !sec_def->attach_fn) 10897 + /* auto-attaching not supported for this program */ 10898 + if (!prog->sec_def || !prog->sec_def->attach_fn) 10885 10899 continue; 10886 10900 10887 - *link = sec_def->attach_fn(sec_def, prog); 10901 + *link = prog->sec_def->attach_fn(prog); 10888 10902 err = libbpf_get_error(*link); 10889 10903 if (err) { 10890 10904 pr_warn("failed to auto-attach program '%s': %d\n",
+3 -9
tools/testing/selftests/bpf/progs/bpf_cubic.c
··· 169 169 ca->sample_cnt = 0; 170 170 } 171 171 172 - /* "struct_ops/" prefix is not a requirement 173 - * It will be recognized as BPF_PROG_TYPE_STRUCT_OPS 174 - * as long as it is used in one of the func ptr 175 - * under SEC(".struct_ops"). 176 - */ 172 + /* "struct_ops/" prefix is a requirement */ 177 173 SEC("struct_ops/bpf_cubic_init") 178 174 void BPF_PROG(bpf_cubic_init, struct sock *sk) 179 175 { ··· 184 188 tcp_sk(sk)->snd_ssthresh = initial_ssthresh; 185 189 } 186 190 187 - /* No prefix in SEC will also work. 188 - * The remaining tcp-cubic functions have an easier way. 189 - */ 190 - SEC("no-sec-prefix-bictcp_cwnd_event") 191 + /* "struct_ops" prefix is a requirement */ 192 + SEC("struct_ops/bpf_cubic_cwnd_event") 191 193 void BPF_PROG(bpf_cubic_cwnd_event, struct sock *sk, enum tcp_ca_event event) 192 194 { 193 195 if (event == CA_EVENT_TX_START) {