Add tests that make the BPF programs skip the actual redirect and immediately return SK_DROP/SK_PASS. Suggested-by: Jiayuan Chen Signed-off-by: Michal Luczaj --- .../selftests/bpf/prog_tests/sockmap_redir.c | 74 +++++++++++++++++++--- 1 file changed, 65 insertions(+), 9 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c b/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c index f89df1ca1174800d801f221a819b099abf911450..4c752000bbd8c84684b2df81eb389be953d8ba02 100644 --- a/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c +++ b/tools/testing/selftests/bpf/prog_tests/sockmap_redir.c @@ -18,6 +18,10 @@ * AF_UNIX, SOCK_DGRAM * AF_VSOCK, SOCK_STREAM * AF_VSOCK, SOCK_SEQPACKET + * x + * SK_REDIRECT + * SK_DROP + * SK_PASS */ #include @@ -65,6 +69,10 @@ */ #define UNSUPPORTED_RACY_VERD _BITUL(1) +/* Mark for an immediate SK_DROP/SK_PASS, i.e. BPF program will not redirect. + */ +#define NO_REDIRECT _BITUL(2) + enum prog_type { SK_MSG_EGRESS, SK_MSG_INGRESS, @@ -154,8 +162,9 @@ static void fail_recv(const char *prefix, int fd, int more_flags) FAIL("%s: unexpected success: retval=%zd", prefix, n); } -static void handle_unsupported(int sd_send, int sd_peer, int sd_in, int sd_out, - int sd_recv, int map_verd, int status) +static void handle_unsupported(int sd_send, int send_flags, int sd_peer, + int sd_in, int sd_out, int sd_recv, + int map_verd, int status) { unsigned int drop, pass; char recv_buf; @@ -171,7 +180,7 @@ static void handle_unsupported(int sd_send, int sd_peer, int sd_in, int sd_out, goto get_verdict; } - if (pass != 0) { + if (pass && !(status & NO_REDIRECT)) { FAIL("unsupported: wanted verdict pass 0, have %u", pass); return; } @@ -237,14 +246,14 @@ static void test_send_recv(int sd_send, int send_flags, int sd_peer, int sd_in, FAIL("incomplete send"); if (n < 0) { /* sk_msg redirect combo not supported? */ - if (status & SUPPORTED || errno != EACCES) + if (errno != EACCES) FAIL_ERRNO("send"); goto out; } - if (!(status & SUPPORTED)) { - handle_unsupported(sd_send, sd_peer, sd_in, sd_out, sd_recv, - maps->verd, status); + if (!(status & SUPPORTED) || (status & NO_REDIRECT)) { + handle_unsupported(sd_send, send_flags, sd_peer, sd_in, sd_out, + sd_recv, maps->verd, status); goto out; } @@ -326,9 +335,10 @@ static int is_redir_supported(enum prog_type type, const char *in, static int get_support_status(enum prog_type type, const char *in, const char *out) { - int status = is_redir_supported(type, in, out); + int status = in ? is_redir_supported(type, in, out) : 0; - if (type == SK_SKB_INGRESS && strstarts(out, "v_")) + if ((type == SK_SKB_INGRESS || type == SK_SKB_EGRESS) && + strstarts(out, "v_")) status |= UNSUPPORTED_RACY_VERD; return status; @@ -370,6 +380,41 @@ static void test_redir(enum bpf_map_type type, struct redir_spec *redir, status); } +static void test_verdict(enum bpf_map_type type, struct redir_spec *redir, + struct maps *maps, struct socket_spec *s_in, + enum sk_action action) +{ + int fd_in, fd_out, fd_send, fd_peer, fd_recv, flags, status; + char s[MAX_TEST_NAME]; + const char *s_str; + + fd_in = s_in->in[0]; + fd_out = s_in->in[1]; + fd_send = s_in->in[redir->idx_send]; + fd_peer = s_in->in[redir->idx_send ^ 1]; + fd_recv = s_in->in[redir->idx_send ^ 1]; + flags = s_in->send_flags; + + s_str = socket_kind_to_str(fd_in); + status = get_support_status(redir->prog_type, NULL, s_str); + status |= NO_REDIRECT; + + snprintf(s, sizeof(s), + "%-4s %-17s %-7s %-5s%6s", + /* hash sk_skb-to-ingress u_str pass (OOB) */ + type == BPF_MAP_TYPE_SOCKMAP ? "map" : "hash", + redir->name, + s_str, + action == SK_PASS ? "pass" : "drop", + flags & MSG_OOB ? "(OOB)" : ""); + + if (!test__start_subtest(s)) + return; + + test_send_recv(fd_send, flags, fd_peer, fd_in, fd_out, fd_recv, maps, + status); +} + static void test_sockets(enum bpf_map_type type, struct redir_spec *redir, struct maps *maps, int *skel_redir_type) { @@ -413,6 +458,17 @@ static void test_sockets(enum bpf_map_type type, struct redir_spec *redir, test_redir(type, redir, maps, in, out); } } + + /* No redirect: SK_DROP */ + *skel_redir_type = __MAX_BPF_MAP_TYPE + SK_DROP; + for (s = sockets; s < sockets + ARRAY_SIZE(sockets); s++) + test_verdict(type, redir, maps, s, SK_DROP); + + /* No redirect: SK_PASS */ + *skel_redir_type = __MAX_BPF_MAP_TYPE + SK_PASS; + for (s = sockets; s < sockets + ARRAY_SIZE(sockets); s++) + test_verdict(type, redir, maps, s, SK_PASS); + out: while (--s >= sockets) socket_spec_close(s); -- 2.50.1