Hi Leon, On 2025/1/21 22:27, Leon Hwang wrote: > 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. What a great suggestion, I can't believe I didn't think of it! Haha. I will resend a v2 version later. Thanks, Leon. > > 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); >> } >