diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h index 4a8c02cafa9a..8aec8769d944 100644 --- a/tools/include/uapi/linux/if_link.h +++ b/tools/include/uapi/linux/if_link.h @@ -167,6 +167,8 @@ enum { IFLA_NEW_IFINDEX, IFLA_MIN_MTU, IFLA_MAX_MTU, + IFLA_PROP_LIST, + IFLA_ALT_IFNAME, /* Alternative ifname */ __IFLA_MAX }; diff --git a/tools/lib/bpf/libbpf.c b/tools/lib/bpf/libbpf.c index 31c8acddc17b..803219d6898c 100644 --- a/tools/lib/bpf/libbpf.c +++ b/tools/lib/bpf/libbpf.c @@ -3611,6 +3611,7 @@ static struct bpf_object * __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz, struct bpf_object_open_opts *opts) { + struct bpf_program *prog; struct bpf_object *obj; const char *obj_name; char tmp_name[64]; @@ -3650,8 +3651,24 @@ __bpf_object__open(const char *path, const void *obj_buf, size_t obj_buf_sz, CHECK_ERR(bpf_object__probe_caps(obj), err, out); CHECK_ERR(bpf_object__elf_collect(obj, relaxed_maps), err, out); CHECK_ERR(bpf_object__collect_reloc(obj), err, out); - bpf_object__elf_finish(obj); + + bpf_object__for_each_program(prog, obj) { + enum bpf_prog_type prog_type; + enum bpf_attach_type attach_type; + + err = libbpf_prog_type_by_name(prog->section_name, &prog_type, + &attach_type); + if (err == -ESRCH) + /* couldn't guess, but user might manually specify */ + continue; + if (err) + goto out; + + bpf_program__set_type(prog, prog_type); + bpf_program__set_expected_attach_type(prog, attach_type); + } + return obj; out: bpf_object__close(obj); @@ -4463,6 +4480,11 @@ int bpf_program__nth_fd(const struct bpf_program *prog, int n) return fd; } +enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog) +{ + return prog->type; +} + void bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type) { prog->type = type; @@ -4497,6 +4519,12 @@ BPF_PROG_TYPE_FNS(raw_tracepoint, BPF_PROG_TYPE_RAW_TRACEPOINT); BPF_PROG_TYPE_FNS(xdp, BPF_PROG_TYPE_XDP); BPF_PROG_TYPE_FNS(perf_event, BPF_PROG_TYPE_PERF_EVENT); +enum bpf_attach_type +bpf_program__get_expected_attach_type(struct bpf_program *prog) +{ + return prog->expected_attach_type; +} + void bpf_program__set_expected_attach_type(struct bpf_program *prog, enum bpf_attach_type type) { @@ -4536,11 +4564,15 @@ static const struct { } section_names[] = { BPF_PROG_SEC("socket", BPF_PROG_TYPE_SOCKET_FILTER), BPF_PROG_SEC("kprobe/", BPF_PROG_TYPE_KPROBE), + BPF_PROG_SEC("uprobe/", BPF_PROG_TYPE_KPROBE), BPF_PROG_SEC("kretprobe/", BPF_PROG_TYPE_KPROBE), + BPF_PROG_SEC("uretprobe/", BPF_PROG_TYPE_KPROBE), BPF_PROG_SEC("classifier", BPF_PROG_TYPE_SCHED_CLS), BPF_PROG_SEC("action", BPF_PROG_TYPE_SCHED_ACT), BPF_PROG_SEC("tracepoint/", BPF_PROG_TYPE_TRACEPOINT), + BPF_PROG_SEC("tp/", BPF_PROG_TYPE_TRACEPOINT), BPF_PROG_SEC("raw_tracepoint/", BPF_PROG_TYPE_RAW_TRACEPOINT), + BPF_PROG_SEC("raw_tp/", BPF_PROG_TYPE_RAW_TRACEPOINT), BPF_PROG_BTF("tp_btf/", BPF_PROG_TYPE_RAW_TRACEPOINT), BPF_PROG_SEC("xdp", BPF_PROG_TYPE_XDP), BPF_PROG_SEC("perf_event", BPF_PROG_TYPE_PERF_EVENT), @@ -4676,7 +4708,7 @@ int libbpf_prog_type_by_name(const char *name, enum bpf_prog_type *prog_type, free(type_names); } - return -EINVAL; + return -ESRCH; } int libbpf_attach_type_by_name(const char *name, @@ -4706,15 +4738,6 @@ int libbpf_attach_type_by_name(const char *name, return -EINVAL; } -static int -bpf_program__identify_section(struct bpf_program *prog, - enum bpf_prog_type *prog_type, - enum bpf_attach_type *expected_attach_type) -{ - return libbpf_prog_type_by_name(prog->section_name, prog_type, - expected_attach_type); -} - int bpf_map__fd(const struct bpf_map *map) { return map ? map->fd : -EINVAL; @@ -4882,8 +4905,6 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr, { struct bpf_object_open_attr open_attr = {}; struct bpf_program *prog, *first_prog = NULL; - enum bpf_attach_type expected_attach_type; - enum bpf_prog_type prog_type; struct bpf_object *obj; struct bpf_map *map; int err; @@ -4901,26 +4922,27 @@ int bpf_prog_load_xattr(const struct bpf_prog_load_attr *attr, return -ENOENT; bpf_object__for_each_program(prog, obj) { + enum bpf_attach_type attach_type = attr->expected_attach_type; /* - * If type is not specified, try to guess it based on - * section name. + * to preserve backwards compatibility, bpf_prog_load treats + * attr->prog_type, if specified, as an override to whatever + * bpf_object__open guessed */ - prog_type = attr->prog_type; - prog->prog_ifindex = attr->ifindex; - expected_attach_type = attr->expected_attach_type; - if (prog_type == BPF_PROG_TYPE_UNSPEC) { - err = bpf_program__identify_section(prog, &prog_type, - &expected_attach_type); - if (err < 0) { - bpf_object__close(obj); - return -EINVAL; - } + if (attr->prog_type != BPF_PROG_TYPE_UNSPEC) { + bpf_program__set_type(prog, attr->prog_type); + bpf_program__set_expected_attach_type(prog, + attach_type); + } + if (bpf_program__get_type(prog) == BPF_PROG_TYPE_UNSPEC) { + /* + * we haven't guessed from section name and user + * didn't provide a fallback type, too bad... + */ + bpf_object__close(obj); + return -EINVAL; } - bpf_program__set_type(prog, prog_type); - bpf_program__set_expected_attach_type(prog, - expected_attach_type); - + prog->prog_ifindex = attr->ifindex; prog->log_level = attr->log_level; prog->prog_flags = attr->prog_flags; if (!first_prog) diff --git a/tools/lib/bpf/libbpf.h b/tools/lib/bpf/libbpf.h index 53ce212764e0..0fdf086beba7 100644 --- a/tools/lib/bpf/libbpf.h +++ b/tools/lib/bpf/libbpf.h @@ -302,8 +302,13 @@ LIBBPF_API int bpf_program__set_sched_cls(struct bpf_program *prog); LIBBPF_API int bpf_program__set_sched_act(struct bpf_program *prog); LIBBPF_API int bpf_program__set_xdp(struct bpf_program *prog); LIBBPF_API int bpf_program__set_perf_event(struct bpf_program *prog); + +LIBBPF_API enum bpf_prog_type bpf_program__get_type(struct bpf_program *prog); LIBBPF_API void bpf_program__set_type(struct bpf_program *prog, enum bpf_prog_type type); + +LIBBPF_API enum bpf_attach_type +bpf_program__get_expected_attach_type(struct bpf_program *prog); LIBBPF_API void bpf_program__set_expected_attach_type(struct bpf_program *prog, enum bpf_attach_type type); diff --git a/tools/lib/bpf/libbpf.map b/tools/lib/bpf/libbpf.map index 4d241fd92dd4..d1473ea4d7a5 100644 --- a/tools/lib/bpf/libbpf.map +++ b/tools/lib/bpf/libbpf.map @@ -195,4 +195,6 @@ LIBBPF_0.0.6 { global: bpf_object__open_file; bpf_object__open_mem; + bpf_program__get_expected_attach_type; + bpf_program__get_type; } LIBBPF_0.0.5; diff --git a/tools/testing/selftests/bpf/prog_tests/attach_probe.c b/tools/testing/selftests/bpf/prog_tests/attach_probe.c index 4f50d32c4abb..0ee1ce100a4a 100644 --- a/tools/testing/selftests/bpf/prog_tests/attach_probe.c +++ b/tools/testing/selftests/bpf/prog_tests/attach_probe.c @@ -99,11 +99,6 @@ void test_attach_probe(void) "prog '%s' not found\n", uretprobe_name)) goto cleanup; - bpf_program__set_kprobe(kprobe_prog); - bpf_program__set_kprobe(kretprobe_prog); - bpf_program__set_kprobe(uprobe_prog); - bpf_program__set_kprobe(uretprobe_prog); - /* create maps && load programs */ err = bpf_object__load(obj); if (CHECK(err, "obj_load", "err %d\n", err)) diff --git a/tools/testing/selftests/bpf/prog_tests/core_reloc.c b/tools/testing/selftests/bpf/prog_tests/core_reloc.c index 2b3586dc6c86..523dca82dc82 100644 --- a/tools/testing/selftests/bpf/prog_tests/core_reloc.c +++ b/tools/testing/selftests/bpf/prog_tests/core_reloc.c @@ -391,7 +391,6 @@ void test_core_reloc(void) if (CHECK(!prog, "find_probe", "prog '%s' not found\n", probe_name)) goto cleanup; - bpf_program__set_type(prog, BPF_PROG_TYPE_RAW_TRACEPOINT); load_attr.obj = obj; load_attr.log_level = 0; diff --git a/tools/testing/selftests/bpf/prog_tests/rdonly_maps.c b/tools/testing/selftests/bpf/prog_tests/rdonly_maps.c index 9bf9de0aaeea..d90acc13d1ec 100644 --- a/tools/testing/selftests/bpf/prog_tests/rdonly_maps.c +++ b/tools/testing/selftests/bpf/prog_tests/rdonly_maps.c @@ -36,10 +36,6 @@ void test_rdonly_maps(void) if (CHECK(IS_ERR(obj), "obj_open", "err %ld\n", PTR_ERR(obj))) return; - bpf_object__for_each_program(prog, obj) { - bpf_program__set_raw_tracepoint(prog); - } - err = bpf_object__load(obj); if (CHECK(err, "obj_load", "err %d errno %d\n", err, errno)) goto cleanup; diff --git a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c index 86cee820d4d3..4493ba277bd7 100644 --- a/tools/testing/selftests/bpf/prog_tests/reference_tracking.c +++ b/tools/testing/selftests/bpf/prog_tests/reference_tracking.c @@ -31,7 +31,8 @@ void test_reference_tracking(void) if (strstr(title, ".text") != NULL) continue; - bpf_program__set_type(prog, BPF_PROG_TYPE_SCHED_CLS); + if (!test__start_subtest(title)) + continue; /* Expect verifier failure if test name has 'fail' */ if (strstr(title, "fail") != NULL) { diff --git a/tools/testing/selftests/bpf/progs/test_sk_lookup_kern.c b/tools/testing/selftests/bpf/progs/test_sk_lookup_kern.c index e21cd736c196..cb49ccb707d1 100644 --- a/tools/testing/selftests/bpf/progs/test_sk_lookup_kern.c +++ b/tools/testing/selftests/bpf/progs/test_sk_lookup_kern.c @@ -53,7 +53,7 @@ static struct bpf_sock_tuple *get_tuple(void *data, __u64 nh_off, return result; } -SEC("sk_lookup_success") +SEC("classifier/sk_lookup_success") int bpf_sk_lookup_test0(struct __sk_buff *skb) { void *data_end = (void *)(long)skb->data_end; @@ -78,7 +78,7 @@ int bpf_sk_lookup_test0(struct __sk_buff *skb) return sk ? TC_ACT_OK : TC_ACT_UNSPEC; } -SEC("sk_lookup_success_simple") +SEC("classifier/sk_lookup_success_simple") int bpf_sk_lookup_test1(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -90,7 +90,7 @@ int bpf_sk_lookup_test1(struct __sk_buff *skb) return 0; } -SEC("fail_use_after_free") +SEC("classifier/fail_use_after_free") int bpf_sk_lookup_uaf(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -105,7 +105,7 @@ int bpf_sk_lookup_uaf(struct __sk_buff *skb) return family; } -SEC("fail_modify_sk_pointer") +SEC("classifier/fail_modify_sk_pointer") int bpf_sk_lookup_modptr(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -120,7 +120,7 @@ int bpf_sk_lookup_modptr(struct __sk_buff *skb) return 0; } -SEC("fail_modify_sk_or_null_pointer") +SEC("classifier/fail_modify_sk_or_null_pointer") int bpf_sk_lookup_modptr_or_null(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -134,7 +134,7 @@ int bpf_sk_lookup_modptr_or_null(struct __sk_buff *skb) return 0; } -SEC("fail_no_release") +SEC("classifier/fail_no_release") int bpf_sk_lookup_test2(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -143,7 +143,7 @@ int bpf_sk_lookup_test2(struct __sk_buff *skb) return 0; } -SEC("fail_release_twice") +SEC("classifier/fail_release_twice") int bpf_sk_lookup_test3(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -155,7 +155,7 @@ int bpf_sk_lookup_test3(struct __sk_buff *skb) return 0; } -SEC("fail_release_unchecked") +SEC("classifier/fail_release_unchecked") int bpf_sk_lookup_test4(struct __sk_buff *skb) { struct bpf_sock_tuple tuple = {}; @@ -172,7 +172,7 @@ void lookup_no_release(struct __sk_buff *skb) bpf_sk_lookup_tcp(skb, &tuple, sizeof(tuple), BPF_F_CURRENT_NETNS, 0); } -SEC("fail_no_release_subcall") +SEC("classifier/fail_no_release_subcall") int bpf_sk_lookup_test5(struct __sk_buff *skb) { lookup_no_release(skb); diff --git a/tools/testing/selftests/bpf/test_maps.c b/tools/testing/selftests/bpf/test_maps.c index 806b298397d3..02eae1e864c2 100644 --- a/tools/testing/selftests/bpf/test_maps.c +++ b/tools/testing/selftests/bpf/test_maps.c @@ -1142,7 +1142,6 @@ static void test_sockmap(unsigned int tasks, void *data) #define MAPINMAP_PROG "./test_map_in_map.o" static void test_map_in_map(void) { - struct bpf_program *prog; struct bpf_object *obj; struct bpf_map *map; int mim_fd, fd, err; @@ -1179,9 +1178,6 @@ static void test_map_in_map(void) goto out_map_in_map; } - bpf_object__for_each_program(prog, obj) { - bpf_program__set_xdp(prog); - } bpf_object__load(obj); map = bpf_object__find_map_by_name(obj, "mim_array"); diff --git a/tools/testing/selftests/bpf/test_progs.c b/tools/testing/selftests/bpf/test_progs.c index c7e52f4194e2..a05a807840c0 100644 --- a/tools/testing/selftests/bpf/test_progs.c +++ b/tools/testing/selftests/bpf/test_progs.c @@ -20,7 +20,7 @@ struct prog_test_def { bool tested; bool need_cgroup_cleanup; - const char *subtest_name; + char *subtest_name; int subtest_num; /* store counts before subtest started */ @@ -81,16 +81,17 @@ void test__end_subtest() fprintf(env.stdout, "#%d/%d %s:%s\n", test->test_num, test->subtest_num, test->subtest_name, sub_error_cnt ? "FAIL" : "OK"); + + free(test->subtest_name); + test->subtest_name = NULL; } bool test__start_subtest(const char *name) { struct prog_test_def *test = env.test; - if (test->subtest_name) { + if (test->subtest_name) test__end_subtest(); - test->subtest_name = NULL; - } test->subtest_num++; @@ -104,7 +105,13 @@ bool test__start_subtest(const char *name) if (!should_run(&env.subtest_selector, test->subtest_num, name)) return false; - test->subtest_name = name; + test->subtest_name = strdup(name); + if (!test->subtest_name) { + fprintf(env.stderr, + "Subtest #%d: failed to copy subtest name!\n", + test->subtest_num); + return false; + } env.test->old_error_cnt = env.test->error_cnt; return true;