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

selftests/bpf: Add test for freplace program with expected_attach_type

This adds a new selftest that tests the ability to attach an freplace
program to a program type that relies on the expected_attach_type of the
target program to pass verification.

Signed-off-by: Toke Høiland-Jørgensen <toke@redhat.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://lore.kernel.org/bpf/158773526831.293902.16011743438619684815.stgit@toke.dk

authored by

Toke Høiland-Jørgensen and committed by
Alexei Starovoitov
1d8a0af5 03f87c0b

+58 -18
+24 -6
tools/testing/selftests/bpf/prog_tests/fexit_bpf2bpf.c
··· 5 5 static void test_fexit_bpf2bpf_common(const char *obj_file, 6 6 const char *target_obj_file, 7 7 int prog_cnt, 8 - const char **prog_name) 8 + const char **prog_name, 9 + bool run_prog) 9 10 { 10 11 struct bpf_object *obj = NULL, *pkt_obj; 11 12 int err, pkt_fd, i; ··· 19 18 20 19 err = bpf_prog_load(target_obj_file, BPF_PROG_TYPE_UNSPEC, 21 20 &pkt_obj, &pkt_fd); 22 - if (CHECK(err, "prog_load sched cls", "err %d errno %d\n", err, errno)) 21 + if (CHECK(err, "tgt_prog_load", "file %s err %d errno %d\n", 22 + target_obj_file, err, errno)) 23 23 return; 24 24 DECLARE_LIBBPF_OPTS(bpf_object_open_opts, opts, 25 25 .attach_prog_fd = pkt_fd, ··· 35 33 36 34 obj = bpf_object__open_file(obj_file, &opts); 37 35 if (CHECK(IS_ERR_OR_NULL(obj), "obj_open", 38 - "failed to open fexit_bpf2bpf: %ld\n", 36 + "failed to open %s: %ld\n", obj_file, 39 37 PTR_ERR(obj))) 40 38 goto close_prog; 41 39 ··· 51 49 if (CHECK(IS_ERR(link[i]), "attach_trace", "failed to link\n")) 52 50 goto close_prog; 53 51 } 52 + 53 + if (!run_prog) 54 + goto close_prog; 55 + 54 56 data_map = bpf_object__find_map_by_name(obj, "fexit_bp.bss"); 55 57 if (CHECK(!data_map, "find_data_map", "data map not found\n")) 56 58 goto close_prog; ··· 95 89 test_fexit_bpf2bpf_common("./fexit_bpf2bpf_simple.o", 96 90 "./test_pkt_md_access.o", 97 91 ARRAY_SIZE(prog_name), 98 - prog_name); 92 + prog_name, true); 99 93 } 100 94 101 95 static void test_target_yes_callees(void) ··· 109 103 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o", 110 104 "./test_pkt_access.o", 111 105 ARRAY_SIZE(prog_name), 112 - prog_name); 106 + prog_name, true); 113 107 } 114 108 115 109 static void test_func_replace(void) ··· 126 120 test_fexit_bpf2bpf_common("./fexit_bpf2bpf.o", 127 121 "./test_pkt_access.o", 128 122 ARRAY_SIZE(prog_name), 129 - prog_name); 123 + prog_name, true); 124 + } 125 + 126 + static void test_func_replace_verify(void) 127 + { 128 + const char *prog_name[] = { 129 + "freplace/do_bind", 130 + }; 131 + test_fexit_bpf2bpf_common("./freplace_connect4.o", 132 + "./connect4_prog.o", 133 + ARRAY_SIZE(prog_name), 134 + prog_name, false); 130 135 } 131 136 132 137 void test_fexit_bpf2bpf(void) ··· 145 128 test_target_no_callees(); 146 129 test_target_yes_callees(); 147 130 test_func_replace(); 131 + test_func_replace_verify(); 148 132 }
+16 -12
tools/testing/selftests/bpf/progs/connect4_prog.c
··· 18 18 19 19 int _version SEC("version") = 1; 20 20 21 + __attribute__ ((noinline)) 22 + int do_bind(struct bpf_sock_addr *ctx) 23 + { 24 + struct sockaddr_in sa = {}; 25 + 26 + sa.sin_family = AF_INET; 27 + sa.sin_port = bpf_htons(0); 28 + sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4); 29 + 30 + if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0) 31 + return 0; 32 + 33 + return 1; 34 + } 35 + 21 36 SEC("cgroup/connect4") 22 37 int connect_v4_prog(struct bpf_sock_addr *ctx) 23 38 { 24 39 struct bpf_sock_tuple tuple = {}; 25 - struct sockaddr_in sa; 26 40 struct bpf_sock *sk; 27 41 28 42 /* Verify that new destination is available. */ ··· 70 56 ctx->user_ip4 = bpf_htonl(DST_REWRITE_IP4); 71 57 ctx->user_port = bpf_htons(DST_REWRITE_PORT4); 72 58 73 - /* Rewrite source. */ 74 - memset(&sa, 0, sizeof(sa)); 75 - 76 - sa.sin_family = AF_INET; 77 - sa.sin_port = bpf_htons(0); 78 - sa.sin_addr.s_addr = bpf_htonl(SRC_REWRITE_IP4); 79 - 80 - if (bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)) != 0) 81 - return 0; 82 - 83 - return 1; 59 + return do_bind(ctx) ? 1 : 0; 84 60 } 85 61 86 62 char _license[] SEC("license") = "GPL";
+18
tools/testing/selftests/bpf/progs/freplace_connect4.c
··· 1 + #include <linux/stddef.h> 2 + #include <linux/ipv6.h> 3 + #include <linux/bpf.h> 4 + #include <linux/in.h> 5 + #include <sys/socket.h> 6 + #include <bpf/bpf_helpers.h> 7 + #include <bpf/bpf_endian.h> 8 + 9 + SEC("freplace/do_bind") 10 + int new_do_bind(struct bpf_sock_addr *ctx) 11 + { 12 + struct sockaddr_in sa = {}; 13 + 14 + bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa)); 15 + return 0; 16 + } 17 + 18 + char _license[] SEC("license") = "GPL";