Hi Tengda, On 2025/1/21 20:56, Tengda Wu wrote: > There are two bpf_link__destroy(freplace_link) calls in > test_tailcall_bpf2bpf_freplace(). After the first bpf_link__destroy() > is called, if the following bpf_map_{update,delete}_elem() throws an > exception, it will jump to the "out" label and call bpf_link__destroy() > again, causing double free and eventually leading to a segfault. > Thank you for pointing this out. > Fix this issue by moving bpf_link__destroy() out of the "out" label > and only calling it when freplace_link exists and has not been freed. > I think it would be better to reset freplace_link to NULL immediately after the first bpf_link__destroy(freplace_link) call. This would help avoid potential double-free scenarios. I’ve tested the following diff, which implements this change: diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c index 544144620ca61..a12fa0521ccc0 100644 --- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c +++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c @@ -1602,6 +1602,7 @@ static void test_tailcall_bpf2bpf_freplace(void) err = bpf_link__destroy(freplace_link); if (!ASSERT_OK(err, "destroy link")) goto out; + freplace_link = NULL; /* OK to update prog_array map then delete element from the map. */ Thanks, Leon > Fixes: 021611d33e78 ("selftests/bpf: Add test to verify tailcall and freplace restrictions") > Signed-off-by: Tengda Wu <wutengda@xxxxxxxxxxxxxxx> > --- > tools/testing/selftests/bpf/prog_tests/tailcalls.c | 8 ++++---- > 1 file changed, 4 insertions(+), 4 deletions(-) > > diff --git a/tools/testing/selftests/bpf/prog_tests/tailcalls.c b/tools/testing/selftests/bpf/prog_tests/tailcalls.c > index 544144620ca6..028439dd2c5f 100644 > --- a/tools/testing/selftests/bpf/prog_tests/tailcalls.c > +++ b/tools/testing/selftests/bpf/prog_tests/tailcalls.c > @@ -1624,7 +1624,7 @@ static void test_tailcall_bpf2bpf_freplace(void) > freplace_link = bpf_program__attach_freplace(freplace_skel->progs.entry_freplace, > prog_fd, "subprog_tc"); > if (!ASSERT_ERR_PTR(freplace_link, "attach_freplace failure")) > - goto out; > + goto out_free_link; > > err = bpf_map_delete_elem(map_fd, &key); > if (!ASSERT_OK(err, "delete_elem from jmp_table")) > @@ -1638,11 +1638,11 @@ static void test_tailcall_bpf2bpf_freplace(void) > goto out; > > err = bpf_map_update_elem(map_fd, &key, &prog_fd, BPF_ANY); > - if (!ASSERT_ERR(err, "update jmp_table failure")) > - goto out; > + ASSERT_ERR(err, "update jmp_table failure"); > > -out: > +out_free_link: > bpf_link__destroy(freplace_link); > +out: > tailcall_freplace__destroy(freplace_skel); > tc_bpf2bpf__destroy(tc_skel); > }