From: Josef Bacik <josef@toxicpanda.com>
bpf_sk_lookup_assign() accepts only sockets which are freed by RCU, and
takes no reference. bpf_prog_test_run_sk_lookup() looks at sk_reuseport of
the selected socket and generates its cookie, which is a write, behind
bpf_test_timer_leave(), that is outside of the RCU read side critical
section in which the program ran. If the socket is closed in the meantime
it may be gone.
Do both before the section ends.
Fixes: 7c32e8f8bc33 ("bpf: Add PROG_TEST_RUN support for sk_lookup programs")
Signed-off-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
---
net/bpf/test_run.c | 19 +++++++++----------
1 file changed, 9 insertions(+), 10 deletions(-)
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index d73cd247f8cd..3043a7393c29 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -1656,20 +1656,19 @@ int bpf_prog_test_run_sk_lookup(struct bpf_prog *prog, const union bpf_attr *kat
ctx.selected_sk = NULL;
retval = BPF_PROG_SK_LOOKUP_RUN_ARRAY(progs, ctx, bpf_prog_run);
} while (bpf_test_timer_continue(&t, 1, repeat, &ret, &duration));
- bpf_test_timer_leave(&t);
-
- if (ret < 0)
- goto out;
+ /* Nothing but RCU keeps the selected socket */
user_ctx->cookie = 0;
- if (ctx.selected_sk) {
- if (ctx.selected_sk->sk_reuseport && !ctx.no_reuseport) {
+ if (!ret && ctx.selected_sk) {
+ if (ctx.selected_sk->sk_reuseport && !ctx.no_reuseport)
ret = -EOPNOTSUPP;
- goto out;
- }
-
- user_ctx->cookie = sock_gen_cookie(ctx.selected_sk);
+ else
+ user_ctx->cookie = sock_gen_cookie(ctx.selected_sk);
}
+ bpf_test_timer_leave(&t);
+
+ if (ret < 0)
+ goto out;
ret = bpf_test_finish(kattr, uattr, NULL, NULL, 0, 0, retval, duration);
if (!ret)--
2.55.0