Add a TC -> netfilter cross-hook test for bpf_dynptr_from_skb_ext(). A TC ingress program writes skb_ext on loopback, and a netfilter program at NF_INET_LOCAL_IN reads it back. Signed-off-by: Jakub Sitnicki --- .../bpf/prog_tests/xdp_context_test_run.c | 56 ++++++++++++++++++++++ tools/testing/selftests/bpf/progs/test_xdp_meta.c | 23 +++++++++ 2 files changed, 79 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c index 1e4e12d2b041..82c57ea3957e 100644 --- a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c +++ b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c @@ -2,6 +2,7 @@ #include #include #include +#include #include #include "test_xdp_context_test_run.skel.h" #include "test_xdp_meta.skel.h" @@ -1249,6 +1250,59 @@ static void test_cgrp_egress_to_kfree_skb(struct test_xdp_meta *skel) close(cgroup_fd); } +/* Test skb_ext survival across TC ingress -> netfilter hook */ +static void test_skb_ext_nf(struct test_xdp_meta *skel, const char *name) +{ + LIBBPF_OPTS(bpf_tc_hook, tc_hook, + .ifindex = 1 /* IFINDEX_LO */, + .attach_point = BPF_TC_INGRESS); + LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1); + LIBBPF_OPTS(bpf_netfilter_opts, nf_opts, + .pf = NFPROTO_IPV4, + .hooknum = NF_INET_LOCAL_IN, + .priority = 1); + struct bpf_link *reader_link = NULL; + struct netns_obj *ns = NULL; + int server_fd = -1; + int ret; + + ns = netns_new(name, true); + if (!ASSERT_OK_PTR(ns, "netns_new")) + return; + + server_fd = start_server(AF_INET, SOCK_DGRAM, "127.0.0.1", 0, 0); + if (!ASSERT_GE(server_fd, 0, "start_server")) + goto cleanup; + + skel->bss->test_pass = false; + + ret = bpf_tc_hook_create(&tc_hook); + if (!ASSERT_OK(ret, "bpf_tc_hook_create")) + goto cleanup; + + tc_opts.prog_fd = bpf_program__fd(skel->progs.tc_skb_ext_write); + ret = bpf_tc_attach(&tc_hook, &tc_opts); + if (!ASSERT_OK(ret, "bpf_tc_attach")) + goto cleanup; + + reader_link = bpf_program__attach_netfilter(skel->progs.nf_skb_ext_read, + &nf_opts); + if (!ASSERT_OK_PTR(reader_link, "attach_nf")) + goto cleanup; + + if (send_loopback_udp(server_fd)) + goto cleanup; + + ASSERT_TRUE(skel->bss->test_pass, "test_pass"); + +cleanup: + bpf_link__destroy(reader_link); + bpf_tc_hook_destroy(&tc_hook); + if (server_fd >= 0) + close(server_fd); + netns_free(ns); +} + void test_skb_ext_cross_hook(void) { struct test_xdp_meta *skel = NULL; @@ -1267,6 +1321,8 @@ void test_skb_ext_cross_hook(void) test_skb_ext_tcp(skel, "tc_to_skops", READER_SKOPS); if (test__start_subtest("cgrp_egress_to_kfree_skb")) test_cgrp_egress_to_kfree_skb(skel); + if (test__start_subtest("tc_to_nf")) + test_skb_ext_nf(skel, "tc_to_nf"); test_xdp_meta__destroy(skel); } diff --git a/tools/testing/selftests/bpf/progs/test_xdp_meta.c b/tools/testing/selftests/bpf/progs/test_xdp_meta.c index 415b33b32ef5..0688120f3d40 100644 --- a/tools/testing/selftests/bpf/progs/test_xdp_meta.c +++ b/tools/testing/selftests/bpf/progs/test_xdp_meta.c @@ -1066,4 +1066,27 @@ int BPF_PROG(tp_kfree_skb_ext_read, struct sk_buff *skb) return 0; } +#define NF_ACCEPT 1 + +SEC("netfilter") +int nf_skb_ext_read(struct bpf_nf_ctx *ctx) +{ + struct __sk_buff *skb = (struct __sk_buff *)ctx->skb; + __u8 meta_have[META_SIZE]; + struct bpf_dynptr meta; + + if (!skb) + return NF_ACCEPT; + + if (bpf_dynptr_from_skb_ext(skb, 0, 0, &meta)) + return NF_ACCEPT; + if (bpf_dynptr_read(meta_have, META_SIZE, &meta, 0, 0)) + return NF_ACCEPT; + if (!check_metadata(meta_have)) + return NF_ACCEPT; + + test_pass = true; + return NF_ACCEPT; +} + char _license[] SEC("license") = "GPL"; -- 2.43.0