From: Luxiao Xu In bpf_prog_test_run_sk_lookup(), bpf_test_timer_leave() is called immediately after the repeat loop finishes, which drops RCU read-side protection via rcu_read_unlock(). However, the subsequent code dereferences ctx.selected_sk (checking sk_reuseport and generating cookie via sock_gen_cookie()) outside the RCU read-side critical section. bpf_sk_lookup_assign() explicitly allows selecting non-refcounted sockets whose lifecycles rely on RCU grace periods. If the selected socket is concurrently destroyed and reclaimed by RCU callbacks after the timer loop leaves, accessing ctx.selected_sk results in a use-after-free (UAF). Fix this by deferring the bpf_test_timer_leave() call until after ctx.selected_sk has been accessed and processed. This ensures that ctx.selected_sk remains protected by the RCU read lock held during the final iteration, while preserving the cooperative scheduling and grace period progress (via cond_resched()) within bpf_test_timer_continue(). Fixes: 7c32e8f8bc33 ("bpf: Add PROG_TEST_RUN support for sk_lookup programs") Cc: stable@vger.kernel.org Reported-by: Vega Assisted-by: Codex:gpt-5.4 Signed-off-by: Luxiao Xu Signed-off-by: Ren Wei --- net/bpf/test_run.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c index 5d51f6cb7d15..e677ec3390e3 100644 --- a/net/bpf/test_run.c +++ b/net/bpf/test_run.c @@ -1650,21 +1650,21 @@ 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)); + + if (ret >= 0) { + user_ctx->cookie = 0; + if (ctx.selected_sk) { + if (ctx.selected_sk->sk_reuseport && !ctx.no_reuseport) + ret = -EOPNOTSUPP; + else + user_ctx->cookie = sock_gen_cookie(ctx.selected_sk); + } + } bpf_test_timer_leave(&t); if (ret < 0) goto out; - user_ctx->cookie = 0; - if (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); - } - ret = bpf_test_finish(kattr, uattr, NULL, NULL, 0, 0, retval, duration); if (!ret) ret = bpf_ctx_finish(kattr, uattr, user_ctx, sizeof(*user_ctx)); -- 2.43.0