* [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args
@ 2026-06-19 22:49 Aelin Reidel
2026-06-19 23:48 ` bot+bpf-ci
2026-06-26 5:26 ` Ihor Solodrai
0 siblings, 2 replies; 5+ messages in thread
From: Aelin Reidel @ 2026-06-19 22:49 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Ihor Solodrai
Cc: bpf, linux-kernel, stable, Aelin Reidel
process_kfunc_with_implicit_args() obtains parameter names through
btf__name_by_offset() and passes them to btf__add_func_param() while
constructing a new function prototype. Tag names are processed in a
similar fashion.
The returned name pointer references memory owned by the BTF object.
btf__add_func_param(), btf__add_decl_tag(), etc. modify the same BTF and
may grow its internal storage, invalidating previously returned string
pointers.
This can result in btf__add_func_param(), btf__add_decl_tag(), etc.
dereferencing a stale pointer when copying the string, leading to crashes
in strset__add_str().
Duplicate the parameter name before calling btf__add_func_param() so it
remains valid across BTF updates.
Fixes: 9d199965990c ("resolve_btfids: Support for KF_IMPLICIT_ARGS")
Cc: stable@vger.kernel.org
Signed-off-by: Aelin Reidel <aelin@mainlining.org>
---
We were noticing resolve_btfids crashing almost all the time when
building our kernels with BTF debuginfo in postmarketOS. I'm not sure
why specificially our environment triggered this extremely reliably, but
I'm glad I was able to track down the issue. With the patch, I haven't
seen any further issues and our kernel builds are succeeding again.
---
Changes in v2:
- Apply the same fix to tag_name and adjust the commit message
accordingly
- Fix the remaining use-after-free in the error handling path
- Link to v1: https://patch.msgid.link/20260619-resolve-btfids-implicit-args-use-after-free-v1-1-2af87d4704c8@mainlining.org
To: Alexei Starovoitov <ast@kernel.org>
To: Daniel Borkmann <daniel@iogearbox.net>
To: Andrii Nakryiko <andrii@kernel.org>
To: Eduard Zingerman <eddyz87@gmail.com>
To: Kumar Kartikeya Dwivedi <memxor@gmail.com>
To: Martin KaFai Lau <martin.lau@linux.dev>
To: Song Liu <song@kernel.org>
To: Yonghong Song <yonghong.song@linux.dev>
To: Jiri Olsa <jolsa@kernel.org>
To: Emil Tsalapatis <emil@etsalapatis.com>
To: Ihor Solodrai <ihor.solodrai@linux.dev>
Cc: bpf@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
tools/bpf/resolve_btfids/main.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
index f8a91fa7584f..94b89e9c942e 100644
--- a/tools/bpf/resolve_btfids/main.c
+++ b/tools/bpf/resolve_btfids/main.c
@@ -1113,6 +1113,7 @@ static int process_kfunc_with_implicit_args(struct btf2btf_context *ctx, struct
{
s32 idx, new_proto_id, new_func_id, proto_id;
const char *param_name, *tag_name;
+ char *tmp_param_name, *tmp_tag_name;
const struct btf_param *params;
enum btf_func_linkage linkage;
char tmp_name[KSYM_NAME_LEN];
@@ -1163,18 +1164,22 @@ static int process_kfunc_with_implicit_args(struct btf2btf_context *ctx, struct
if (strcmp(tag_name, "bpf_kfunc") == 0)
continue;
+ tmp_tag_name = strdup(tag_name);
idx = btf_decl_tag(t)->component_idx;
if (btf_kflag(t))
- err = btf__add_decl_attr(btf, tag_name, new_func_id, idx);
+ err = btf__add_decl_attr(btf, tmp_tag_name, new_func_id, idx);
else
- err = btf__add_decl_tag(btf, tag_name, new_func_id, idx);
+ err = btf__add_decl_tag(btf, tmp_tag_name, new_func_id, idx);
if (err < 0) {
pr_err("ERROR: resolve_btfids: failed to add decl tag %s for %s\n",
- tag_name, tmp_name);
+ tmp_tag_name, tmp_name);
+ free(tmp_tag_name);
return -EINVAL;
}
+
+ free(tmp_tag_name);
}
add_new_proto:
@@ -1193,12 +1198,17 @@ static int process_kfunc_with_implicit_args(struct btf2btf_context *ctx, struct
if (is_kf_implicit_arg(btf, ¶ms[i]))
break;
param_name = btf__name_by_offset(btf, params[i].name_off);
- err = btf__add_func_param(btf, param_name, params[i].type);
+ tmp_param_name = strdup(param_name);
+ if (!tmp_param_name)
+ return -ENOMEM;
+ err = btf__add_func_param(btf, tmp_param_name, params[i].type);
if (err < 0) {
pr_err("ERROR: resolve_btfids: failed to add param %s for %s\n",
- param_name, kfunc->name);
+ tmp_param_name, kfunc->name);
+ free(tmp_param_name);
return err;
}
+ free(tmp_param_name);
t = (struct btf_type *)btf__type_by_id(btf, proto_id);
}
---
base-commit: 598c7067dd8b65b93f3ccada47e9014a13137f1b
change-id: 20260619-resolve-btfids-implicit-args-use-after-free-16fc2939529e
Best regards,
--
Aelin Reidel <aelin@mainlining.org>
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args
2026-06-19 22:49 [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args Aelin Reidel
@ 2026-06-19 23:48 ` bot+bpf-ci
2026-06-26 5:26 ` Ihor Solodrai
1 sibling, 0 replies; 5+ messages in thread
From: bot+bpf-ci @ 2026-06-19 23:48 UTC (permalink / raw)
To: aelin, ast, daniel, andrii, eddyz87, memxor, martin.lau, song,
yonghong.song, jolsa, emil, ihor.solodrai
Cc: bpf, linux-kernel, stable, aelin, ast, andrii, daniel, martin.lau,
eddyz87, yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 1599 bytes --]
> process_kfunc_with_implicit_args() obtains parameter names through
> btf__name_by_offset() and passes them to btf__add_func_param() while
> constructing a new function prototype. Tag names are processed in a
> similar fashion.
>
> The returned name pointer references memory owned by the BTF object.
> btf__add_func_param(), btf__add_decl_tag(), etc. modify the same BTF and
> may grow its internal storage, invalidating previously returned string
> pointers.
>
> This can result in btf__add_func_param(), btf__add_decl_tag(), etc.
> dereferencing a stale pointer when copying the string, leading to crashes
> in strset__add_str().
This isn't a bug, but could the crash path in strset__add_str() be spelled
out a little more?
btf__name_by_offset() returns a pointer into btf->strs_set->strs_data (while
the BTF is still modifiable and btf->strs_data is NULL), and
strset_str_append() in tools/lib/bpf/strset.c already reconstructs that
pointer if the buffer was reallocated before it copies:
tools/lib/bpf/strset.c:strset_str_append() {
...
old_data = set->strs_data;
...
if (old_data != set->strs_data)
s = set->strs_data + (old_s - old_data);
memcpy((void *)s, ...);
...
}
Given that reconstruction, what crash in strset__add_str() remains, or is the
strdup intended as a defensive/robustness change rather than a fix for an
observed crash?
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/27852582382
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args
2026-06-19 22:49 [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args Aelin Reidel
2026-06-19 23:48 ` bot+bpf-ci
@ 2026-06-26 5:26 ` Ihor Solodrai
2026-07-07 7:55 ` Henrik Grimler
1 sibling, 1 reply; 5+ messages in thread
From: Ihor Solodrai @ 2026-06-26 5:26 UTC (permalink / raw)
To: Aelin Reidel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis
Cc: bpf, linux-kernel, stable
On 2026-06-19 3:49 p.m., Aelin Reidel wrote:
> process_kfunc_with_implicit_args() obtains parameter names through
> btf__name_by_offset() and passes them to btf__add_func_param() while
> constructing a new function prototype. Tag names are processed in a
> similar fashion.
>
> The returned name pointer references memory owned by the BTF object.
> btf__add_func_param(), btf__add_decl_tag(), etc. modify the same BTF and
> may grow its internal storage, invalidating previously returned string
> pointers.
>
> This can result in btf__add_func_param(), btf__add_decl_tag(), etc.
> dereferencing a stale pointer when copying the string, leading to crashes
> in strset__add_str().
>
> Duplicate the parameter name before calling btf__add_func_param() so it
> remains valid across BTF updates.
>
> Fixes: 9d199965990c ("resolve_btfids: Support for KF_IMPLICIT_ARGS")
> Cc: stable@vger.kernel.org
> Signed-off-by: Aelin Reidel <aelin@mainlining.org>
> ---
> We were noticing resolve_btfids crashing almost all the time when
> building our kernels with BTF debuginfo in postmarketOS. I'm not sure
> why specificially our environment triggered this extremely reliably, but
> I'm glad I was able to track down the issue. With the patch, I haven't
> seen any further issues and our kernel builds are succeeding again.
Hi Aelin, thank you for the report and patch.
My first instinct was to dismiss the patch as over defensive, because
libbpf gracefully handles reallocation of existing strings, and we
don't add new strings here.
Take a look at strset_str_append() in libbpf (strset.c:131):
static long strset_str_append(struct strset *set, const char *s)
{
[...]
/*
* The set->strs_data might have reallocated and if 's' pointed
* to an internal string within the old buffer, then it became
* dangling and needs to be reconstructed before the copy.
*/
if (old_data && old_data != (uintptr_t)set->strs_data &&
old_s >= old_data && old_s < old_data + old_data_len)
s = set->strs_data + (old_s - old_data);
memcpy(p, s, len);
return len;
}
In process_kfunc_with_implicit_args() both tag_name and param_name are
read *after* the first btf__add_func() / btf__add_func_proto() has
made the BTF modifiable, so btf__name_by_offset() should return a
pointer into btf->strs_set. I don't see where the bad pointer comes
from.
However you have a stable reproducer, so your strdup() change probably
covers a real UAF bug somewhere else (in libbpf?).
Let's track this down before coming up with a fix.
What version/commit of libbpf are you using in your kernel tree?
You could build resolve_btfids with ASAN, or run it with valgrind.
If you can share a reproducer that's easy to run, that would be
great too.
Thanks!
> ---
> Changes in v2:
> - Apply the same fix to tag_name and adjust the commit message
> accordingly
> - Fix the remaining use-after-free in the error handling path
> - Link to v1: https://patch.msgid.link/20260619-resolve-btfids-implicit-args-use-after-free-v1-1-2af87d4704c8@mainlining.org
>
> To: Alexei Starovoitov <ast@kernel.org>
> To: Daniel Borkmann <daniel@iogearbox.net>
> To: Andrii Nakryiko <andrii@kernel.org>
> To: Eduard Zingerman <eddyz87@gmail.com>
> To: Kumar Kartikeya Dwivedi <memxor@gmail.com>
> To: Martin KaFai Lau <martin.lau@linux.dev>
> To: Song Liu <song@kernel.org>
> To: Yonghong Song <yonghong.song@linux.dev>
> To: Jiri Olsa <jolsa@kernel.org>
> To: Emil Tsalapatis <emil@etsalapatis.com>
> To: Ihor Solodrai <ihor.solodrai@linux.dev>
> Cc: bpf@vger.kernel.org
> Cc: linux-kernel@vger.kernel.org
> ---
> tools/bpf/resolve_btfids/main.c | 20 +++++++++++++++-----
> 1 file changed, 15 insertions(+), 5 deletions(-)
>
> diff --git a/tools/bpf/resolve_btfids/main.c b/tools/bpf/resolve_btfids/main.c
> index f8a91fa7584f..94b89e9c942e 100644
> --- a/tools/bpf/resolve_btfids/main.c
> +++ b/tools/bpf/resolve_btfids/main.c
> @@ -1113,6 +1113,7 @@ static int process_kfunc_with_implicit_args(struct btf2btf_context *ctx, struct
> {
> s32 idx, new_proto_id, new_func_id, proto_id;
> const char *param_name, *tag_name;
> + char *tmp_param_name, *tmp_tag_name;
> const struct btf_param *params;
> enum btf_func_linkage linkage;
> char tmp_name[KSYM_NAME_LEN];
> @@ -1163,18 +1164,22 @@ static int process_kfunc_with_implicit_args(struct btf2btf_context *ctx, struct
> if (strcmp(tag_name, "bpf_kfunc") == 0)
> continue;
>
> + tmp_tag_name = strdup(tag_name);
> idx = btf_decl_tag(t)->component_idx;
>
> if (btf_kflag(t))
> - err = btf__add_decl_attr(btf, tag_name, new_func_id, idx);
> + err = btf__add_decl_attr(btf, tmp_tag_name, new_func_id, idx);
> else
> - err = btf__add_decl_tag(btf, tag_name, new_func_id, idx);
> + err = btf__add_decl_tag(btf, tmp_tag_name, new_func_id, idx);
>
> if (err < 0) {
> pr_err("ERROR: resolve_btfids: failed to add decl tag %s for %s\n",
> - tag_name, tmp_name);
> + tmp_tag_name, tmp_name);
> + free(tmp_tag_name);
> return -EINVAL;
> }
> +
> + free(tmp_tag_name);
> }
>
> add_new_proto:
> @@ -1193,12 +1198,17 @@ static int process_kfunc_with_implicit_args(struct btf2btf_context *ctx, struct
> if (is_kf_implicit_arg(btf, ¶ms[i]))
> break;
> param_name = btf__name_by_offset(btf, params[i].name_off);
> - err = btf__add_func_param(btf, param_name, params[i].type);
> + tmp_param_name = strdup(param_name);
> + if (!tmp_param_name)
> + return -ENOMEM;
> + err = btf__add_func_param(btf, tmp_param_name, params[i].type);
> if (err < 0) {
> pr_err("ERROR: resolve_btfids: failed to add param %s for %s\n",
> - param_name, kfunc->name);
> + tmp_param_name, kfunc->name);
> + free(tmp_param_name);
> return err;
> }
> + free(tmp_param_name);
> t = (struct btf_type *)btf__type_by_id(btf, proto_id);
> }
>
>
> ---
> base-commit: 598c7067dd8b65b93f3ccada47e9014a13137f1b
> change-id: 20260619-resolve-btfids-implicit-args-use-after-free-16fc2939529e
>
> Best regards,
> --
> Aelin Reidel <aelin@mainlining.org>
>
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args
2026-06-26 5:26 ` Ihor Solodrai
@ 2026-07-07 7:55 ` Henrik Grimler
2026-07-07 19:44 ` Ihor Solodrai
0 siblings, 1 reply; 5+ messages in thread
From: Henrik Grimler @ 2026-07-07 7:55 UTC (permalink / raw)
To: Ihor Solodrai
Cc: Aelin Reidel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, bpf, linux-kernel, stable
Hi Ihor,
On Thu, Jun 25, 2026 at 10:26:27PM -0700, Ihor Solodrai wrote:
> On 2026-06-19 3:49 p.m., Aelin Reidel wrote:
> > process_kfunc_with_implicit_args() obtains parameter names through
> > btf__name_by_offset() and passes them to btf__add_func_param() while
> > constructing a new function prototype. Tag names are processed in a
> > similar fashion.
> >
> > The returned name pointer references memory owned by the BTF object.
> > btf__add_func_param(), btf__add_decl_tag(), etc. modify the same BTF and
> > may grow its internal storage, invalidating previously returned string
> > pointers.
> >
> > This can result in btf__add_func_param(), btf__add_decl_tag(), etc.
> > dereferencing a stale pointer when copying the string, leading to crashes
> > in strset__add_str().
> >
> > Duplicate the parameter name before calling btf__add_func_param() so it
> > remains valid across BTF updates.
> >
> > Fixes: 9d199965990c ("resolve_btfids: Support for KF_IMPLICIT_ARGS")
> > Cc: stable@vger.kernel.org
> > Signed-off-by: Aelin Reidel <aelin@mainlining.org>
> > ---
> > We were noticing resolve_btfids crashing almost all the time when
> > building our kernels with BTF debuginfo in postmarketOS. I'm not sure
> > why specificially our environment triggered this extremely reliably, but
> > I'm glad I was able to track down the issue. With the patch, I haven't
> > seen any further issues and our kernel builds are succeeding again.
>
> Hi Aelin, thank you for the report and patch.
>
> My first instinct was to dismiss the patch as over defensive, because
> libbpf gracefully handles reallocation of existing strings, and we
> don't add new strings here.
>
> Take a look at strset_str_append() in libbpf (strset.c:131):
>
> static long strset_str_append(struct strset *set, const char *s)
> {
> [...]
>
> /*
> * The set->strs_data might have reallocated and if 's' pointed
> * to an internal string within the old buffer, then it became
> * dangling and needs to be reconstructed before the copy.
> */
> if (old_data && old_data != (uintptr_t)set->strs_data &&
> old_s >= old_data && old_s < old_data + old_data_len)
> s = set->strs_data + (old_s - old_data);
>
> memcpy(p, s, len);
>
> return len;
> }
>
> In process_kfunc_with_implicit_args() both tag_name and param_name are
> read *after* the first btf__add_func() / btf__add_func_proto() has
> made the BTF modifiable, so btf__name_by_offset() should return a
> pointer into btf->strs_set. I don't see where the bad pointer comes
> from.
>
> However you have a stable reproducer, so your strdup() change probably
> covers a real UAF bug somewhere else (in libbpf?).
>
> Let's track this down before coming up with a fix.
>
> What version/commit of libbpf are you using in your kernel tree?
I use the same build environment as Aelin and get the same issue with
resolve_btfids from linux v7.1.1. System libbpf is at v1.7.0 [1] (but
I guess this is not relevant? resolve_btfids is not linked against
it).
> You could build resolve_btfids with ASAN, or run it with valgrind.
Valgrind reports some invalid reads, see log here:
https://grimler.se/files/valgrind-resolve-btfids.txt
and if run under gdb I get:
```
$ gdb -ex r --args tools/bpf/resolve_btfids/resolve_btfids --fatal_warnings --verbose --btf .tmp_vmlinux1.BTF.1 .tmp_vmlinux1
[ ... ]
found kfunc tcp_reno_ssthresh in BTF_ID_FLAGS bpf_tcp_ca_check_kfunc_ids
found kfunc tcp_reno_undo_cwnd in BTF_ID_FLAGS bpf_tcp_ca_check_kfunc_ids
found kfunc tcp_slow_start in BTF_ID_FLAGS bpf_tcp_ca_check_kfunc_ids
resolve_btfids: function bpf_list_push_back_impl already exists in BTF
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7f7aaa0 in memcpy (dest=0x7fffebb05a93, src=<optimized out>, n=5) at src/string/memcpy.c:23
warning: 23 src/string/memcpy.c: No such file or directory
(gdb) bt
#0 0x00007ffff7f7aaa0 in memcpy (dest=0x7fffebb05a93, src=<optimized out>, n=5) at src/string/memcpy.c:23
#1 0x000055555559865b in _ZL6memcpyPvU17pass_object_size0PKvU17pass_object_size0m (__od=0x7fffeb115c71, __os=0x7fffeb115c71, __n=5) at /usr/include/fortify/string.h:57
#2 strset__add_str (set=0x7fffebb85fd0, s=s@entry=0x7fffeb115c71 <error: Cannot access memory at address 0x7fffeb115c71>) at strset.c:162
#3 0x0000555555587b2c in btf__add_str (btf=btf@entry=0x7fffebb860a0, s=0x7fffeb115c71 <error: Cannot access memory at address 0x7fffeb115c71>) at btf.c:2109
#4 0x00005555555898b1 in btf__add_func_param (btf=0x7fffebb860a0, name=0x7fffeb115c71 <error: Cannot access memory at address 0x7fffeb115c71>, type_id=11011) at btf.c:3108
#5 0x000055555555de50 in process_kfunc_with_implicit_args (ctx=0x7fffffffd7d0, kfunc=0x7fffebb739a0) at main.c:1196
#6 0x000055555555cc02 in btf2btf (obj=0x7fffffffd868) at main.c:1229
#7 0x000055555555b869 in main (argc=1, argv=0x7fffffffec08) at main.c:1535
```
> If you can share a reproducer that's easy to run, that would be
> great too.
I have uploaded .tmp_vmlinux1 and .tmp_vmlinux1.BTF.1 files (for an
ARM kernel) that reproduce the issue here:
https://grimler.se/files/tmp_vmlinux1
https://grimler.se/files/tmp_vmlinux1.BTF.1
When resolve_btfids is compiled with musl and alpine's toolchain, then
the following command segfaults roughly 50 % of the time:
tools/bpf/resolve_btfids/resolve_btfids --fatal_warnings --verbose --btf tmp_vmlinux1.BTF.1 tmp_vmlinux1
With a resolve_btfids compiled for glibc it does not segfault, but valgrind still reports invalid reads.
> Thanks!
[1] https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/main/libbpf/APKBUILD#L3
Best regards,
Henrik Grimler
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args
2026-07-07 7:55 ` Henrik Grimler
@ 2026-07-07 19:44 ` Ihor Solodrai
0 siblings, 0 replies; 5+ messages in thread
From: Ihor Solodrai @ 2026-07-07 19:44 UTC (permalink / raw)
To: Henrik Grimler
Cc: Aelin Reidel, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, bpf, linux-kernel, stable
On 7/7/26 12:55 AM, Henrik Grimler wrote:
> Hi Ihor,
>
> On Thu, Jun 25, 2026 at 10:26:27PM -0700, Ihor Solodrai wrote:
>> [...]
>>
>> However you have a stable reproducer, so your strdup() change probably
>> covers a real UAF bug somewhere else (in libbpf?).
>>
>> Let's track this down before coming up with a fix.
>>
>> What version/commit of libbpf are you using in your kernel tree?
>
> I use the same build environment as Aelin and get the same issue with
> resolve_btfids from linux v7.1.1. System libbpf is at v1.7.0 [1] (but
> I guess this is not relevant? resolve_btfids is not linked against
> it).
>
>> You could build resolve_btfids with ASAN, or run it with valgrind.
>
> Valgrind reports some invalid reads, see log here:
> https://grimler.se/files/valgrind-resolve-btfids.txt
>
> and if run under gdb I get:
>
> ```
> $ gdb -ex r --args tools/bpf/resolve_btfids/resolve_btfids --fatal_warnings --verbose --btf .tmp_vmlinux1.BTF.1 .tmp_vmlinux1
> [ ... ]
> found kfunc tcp_reno_ssthresh in BTF_ID_FLAGS bpf_tcp_ca_check_kfunc_ids
> found kfunc tcp_reno_undo_cwnd in BTF_ID_FLAGS bpf_tcp_ca_check_kfunc_ids
> found kfunc tcp_slow_start in BTF_ID_FLAGS bpf_tcp_ca_check_kfunc_ids
> resolve_btfids: function bpf_list_push_back_impl already exists in BTF
>
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007ffff7f7aaa0 in memcpy (dest=0x7fffebb05a93, src=<optimized out>, n=5) at src/string/memcpy.c:23
> warning: 23 src/string/memcpy.c: No such file or directory
> (gdb) bt
> #0 0x00007ffff7f7aaa0 in memcpy (dest=0x7fffebb05a93, src=<optimized out>, n=5) at src/string/memcpy.c:23
> #1 0x000055555559865b in _ZL6memcpyPvU17pass_object_size0PKvU17pass_object_size0m (__od=0x7fffeb115c71, __os=0x7fffeb115c71, __n=5) at /usr/include/fortify/string.h:57
> #2 strset__add_str (set=0x7fffebb85fd0, s=s@entry=0x7fffeb115c71 <error: Cannot access memory at address 0x7fffeb115c71>) at strset.c:162
> #3 0x0000555555587b2c in btf__add_str (btf=btf@entry=0x7fffebb860a0, s=0x7fffeb115c71 <error: Cannot access memory at address 0x7fffeb115c71>) at btf.c:2109
> #4 0x00005555555898b1 in btf__add_func_param (btf=0x7fffebb860a0, name=0x7fffeb115c71 <error: Cannot access memory at address 0x7fffeb115c71>, type_id=11011) at btf.c:3108
> #5 0x000055555555de50 in process_kfunc_with_implicit_args (ctx=0x7fffffffd7d0, kfunc=0x7fffebb739a0) at main.c:1196
> #6 0x000055555555cc02 in btf2btf (obj=0x7fffffffd868) at main.c:1229
> #7 0x000055555555b869 in main (argc=1, argv=0x7fffffffec08) at main.c:1535
> ```
>
>> If you can share a reproducer that's easy to run, that would be
>> great too.
>
> I have uploaded .tmp_vmlinux1 and .tmp_vmlinux1.BTF.1 files (for an
> ARM kernel) that reproduce the issue here:
>
> https://grimler.se/files/tmp_vmlinux1
> https://grimler.se/files/tmp_vmlinux1.BTF.1
Hi Henrik,
Thanks for the reproducer and the logs, very helpful.
The crash you hit is a real UAF that was recently fixed in libbpf:
b23705e6afb6 ("libbpf: Fix UAF in strset__add_str()") [1]
strset__add_str() reallocs its buffer, then copies from a string that
may point into that same buffer (what btf__name_by_offset() returns)
dangling after the realloc.
I ran unpatched resolve_btfids under valgrind on your binaries,
toggling only b23705e6afb6.
Reverting b23705e6afb6:
Invalid read of size 1
at memmove
by strset__add_str (strset.c:162)
by btf__add_str (btf.c:2109)
by btf__add_func_param (btf.c:3118)
by process_kfunc_with_implicit_args (main.c:1196)
by btf2btf (main.c:1229)
by main (main.c:1535)
Address 0x11dfb901 is 22,721 bytes inside a block of size 1,787,619 free'd
at realloc
by libbpf_add_mem (btf.c:224)
by strset_add_str_mem (strset.c:106)
by strset__add_str (strset.c:157)
[...]
ERROR SUMMARY: 5 errors from 2 contexts
With b23705e6afb6 there are no errors.
resolve_btfids statically links the in-tree tools/lib/bpf, so system
libbpf 1.7.0 is irrelevant, as you correctly noted. v7.1.1 predates
b23705e6afb6, which is why you are seeing the crash. It's been merged
into 7.2-rc1, so it will be in the 7.2 release.
I suggest you apply b23705e6afb6 for your build.
Let's drop this resolve_btfids patch, since the root cause has already been fixed.
Thank you!
[1] https://lore.kernel.org/bpf/20260523162722.2718940-1-cmllamas@google.com/
>
> When resolve_btfids is compiled with musl and alpine's toolchain, then
> the following command segfaults roughly 50 % of the time:
>
> tools/bpf/resolve_btfids/resolve_btfids --fatal_warnings --verbose --btf tmp_vmlinux1.BTF.1 tmp_vmlinux1
>
> With a resolve_btfids compiled for glibc it does not segfault, but valgrind still reports invalid reads.
>
>> Thanks!
>
> [1] https://gitlab.alpinelinux.org/alpine/aports/-/blob/master/main/libbpf/APKBUILD#L3
>
> Best regards,
> Henrik Grimler
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-07 19:45 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-19 22:49 [PATCH v2] resolve_btfids: preserve tag and parameter names when processing implicit args Aelin Reidel
2026-06-19 23:48 ` bot+bpf-ci
2026-06-26 5:26 ` Ihor Solodrai
2026-07-07 7:55 ` Henrik Grimler
2026-07-07 19:44 ` Ihor Solodrai
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox