From: Josef Bacik 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 Signed-off-by: Alexei Starovoitov --- 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