* [PATCH bpf] selftests/bpf: Fix freplace_link segfault in tailcalls prog test
@ 2025-01-21 12:56 Tengda Wu
2025-01-21 14:27 ` Leon Hwang
0 siblings, 1 reply; 3+ messages in thread
From: Tengda Wu @ 2025-01-21 12:56 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
hffilwlqm, leon.hwang
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.
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.
Fixes: 021611d33e78 ("selftests/bpf: Add test to verify tailcall and freplace restrictions")
Signed-off-by: Tengda Wu <wutengda@huaweicloud.com>
---
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);
}
--
2.34.1
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf] selftests/bpf: Fix freplace_link segfault in tailcalls prog test
2025-01-21 12:56 [PATCH bpf] selftests/bpf: Fix freplace_link segfault in tailcalls prog test Tengda Wu
@ 2025-01-21 14:27 ` Leon Hwang
2025-01-22 0:59 ` Tengda Wu
0 siblings, 1 reply; 3+ messages in thread
From: Leon Hwang @ 2025-01-21 14:27 UTC (permalink / raw)
To: Tengda Wu, bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
hffilwlqm
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@huaweicloud.com>
> ---
> 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);
> }
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf] selftests/bpf: Fix freplace_link segfault in tailcalls prog test
2025-01-21 14:27 ` Leon Hwang
@ 2025-01-22 0:59 ` Tengda Wu
0 siblings, 0 replies; 3+ messages in thread
From: Tengda Wu @ 2025-01-22 0:59 UTC (permalink / raw)
To: Leon Hwang, bpf
Cc: Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Martin KaFai Lau, Eduard Zingerman, Song Liu,
Yonghong Song, KP Singh, Stanislav Fomichev, Hao Luo, Jiri Olsa,
hffilwlqm
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@huaweicloud.com>
>> ---
>> 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);
>> }
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-01-22 1:00 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-01-21 12:56 [PATCH bpf] selftests/bpf: Fix freplace_link segfault in tailcalls prog test Tengda Wu
2025-01-21 14:27 ` Leon Hwang
2025-01-22 0:59 ` Tengda Wu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox