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

bpf, selftests: Fix racing issue in btf_skc_cls_ingress test

The libbpf CI reported occasional failure in btf_skc_cls_ingress:

test_syncookie:FAIL:Unexpected syncookie states gen_cookie:80326634 recv_cookie:0
bpf prog error at line 97

"error at line 97" means the bpf prog cannot find the listening socket
when the final ack is received. It then skipped processing
the syncookie in the final ack which then led to "recv_cookie:0".

The problem is the userspace program did not do accept() and went
ahead to close(listen_fd) before the kernel (and the bpf prog) had
a chance to process the final ack.

The fix is to add accept() call so that the userspace will wait for
the kernel to finish processing the final ack first before close()-ing
everything.

Fixes: 9a856cae2217 ("bpf: selftest: Add test_btf_skc_cls_ingress")
Reported-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Martin KaFai Lau <kafai@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20211216191630.466151-1-kafai@fb.com

authored by

Martin KaFai Lau and committed by
Daniel Borkmann
c2fcbf81 7edc3fcb

+14 -2
+14 -2
tools/testing/selftests/bpf/prog_tests/btf_skc_cls_ingress.c
··· 90 90 91 91 static void test_conn(void) 92 92 { 93 - int listen_fd = -1, cli_fd = -1, err; 93 + int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; 94 94 socklen_t addrlen = sizeof(srv_sa6); 95 95 int srv_port; 96 96 ··· 110 110 111 111 cli_fd = connect_to_fd(listen_fd, 0); 112 112 if (CHECK_FAIL(cli_fd == -1)) 113 + goto done; 114 + 115 + srv_fd = accept(listen_fd, NULL, NULL); 116 + if (CHECK_FAIL(srv_fd == -1)) 113 117 goto done; 114 118 115 119 if (CHECK(skel->bss->listen_tp_sport != srv_port || ··· 138 134 close(listen_fd); 139 135 if (cli_fd != -1) 140 136 close(cli_fd); 137 + if (srv_fd != -1) 138 + close(srv_fd); 141 139 } 142 140 143 141 static void test_syncookie(void) 144 142 { 145 - int listen_fd = -1, cli_fd = -1, err; 143 + int listen_fd = -1, cli_fd = -1, srv_fd = -1, err; 146 144 socklen_t addrlen = sizeof(srv_sa6); 147 145 int srv_port; 148 146 ··· 165 159 166 160 cli_fd = connect_to_fd(listen_fd, 0); 167 161 if (CHECK_FAIL(cli_fd == -1)) 162 + goto done; 163 + 164 + srv_fd = accept(listen_fd, NULL, NULL); 165 + if (CHECK_FAIL(srv_fd == -1)) 168 166 goto done; 169 167 170 168 if (CHECK(skel->bss->listen_tp_sport != srv_port, ··· 198 188 close(listen_fd); 199 189 if (cli_fd != -1) 200 190 close(cli_fd); 191 + if (srv_fd != -1) 192 + close(srv_fd); 201 193 } 202 194 203 195 struct test {