* [PATCH bpf-next] bpf: verifier: initialize imm in kfunc_tab in add_kfunc_call()
@ 2025-11-11 16:09 Puranjay Mohan
2025-11-11 18:38 ` Mykyta Yatsenko
0 siblings, 1 reply; 3+ messages in thread
From: Puranjay Mohan @ 2025-11-11 16:09 UTC (permalink / raw)
To: bpf
Cc: Puranjay Mohan, Puranjay Mohan, Alexei Starovoitov,
Andrii Nakryiko, Daniel Borkmann, Martin KaFai Lau,
Eduard Zingerman, Kumar Kartikeya Dwivedi, kernel-team
Metadata about a kfunc call is added to the kfunc_tab in
add_kfunc_call() but the call instruction itself could get removed by
opt_remove_dead_code() later if it is not reachable.
If the call instruction is removed, specialize_kfunc() is never called
for it and the desc->imm in the kfunc_tab is never initialized for this
kfunc call. In this case, sort_kfunc_descs_by_imm_off(env->prog); in
do_misc_fixups() doesn't sort the table correctly.
This is a problem from s390 as its JIT uses this table to find the
addresses for kfuncs, and if this table is not sorted properly, JIT can
fail to find addresses for valid kfunc calls.
This was exposed by:
commit d869d56ca848 ("bpf: verifier: refactor kfunc specialization")
as before this commit, desc->imm was initialised in add_kfunc_call().
Initialize desc->imm to func_id, it will be overwritten in
specialize_kfunc() if the instruction is not removed.
Fixes: d869d56ca848 ("bpf: verifier: refactor kfunc specialization")
Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
---
This bug is not triggered by the CI currently, I am working on another
set for non-sleepbale arena allocations and as part of that I am adding
a new selftest that triggers this bug.
Selftest: https://github.com/kernel-patches/bpf/pull/10242/commits/1f681f022c6d685fd76695e5eafbe9d9ab4c0002
CI run: https://github.com/kernel-patches/bpf/actions/runs/19238699806/job/54996376908
---
kernel/bpf/verifier.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 1268fa075d4c..a667f761173c 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3371,6 +3371,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
desc = &tab->descs[tab->nr_descs++];
desc->func_id = func_id;
+ desc->imm = func_id;
desc->offset = offset;
desc->addr = addr;
desc->func_model = func_model;
--
2.47.3
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next] bpf: verifier: initialize imm in kfunc_tab in add_kfunc_call()
2025-11-11 16:09 [PATCH bpf-next] bpf: verifier: initialize imm in kfunc_tab in add_kfunc_call() Puranjay Mohan
@ 2025-11-11 18:38 ` Mykyta Yatsenko
2025-11-12 0:01 ` Puranjay Mohan
0 siblings, 1 reply; 3+ messages in thread
From: Mykyta Yatsenko @ 2025-11-11 18:38 UTC (permalink / raw)
To: Puranjay Mohan, bpf
Cc: Puranjay Mohan, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, kernel-team
On 11/11/25 16:09, Puranjay Mohan wrote:
> Metadata about a kfunc call is added to the kfunc_tab in
> add_kfunc_call() but the call instruction itself could get removed by
> opt_remove_dead_code() later if it is not reachable.
>
> If the call instruction is removed, specialize_kfunc() is never called
> for it and the desc->imm in the kfunc_tab is never initialized for this
> kfunc call. In this case, sort_kfunc_descs_by_imm_off(env->prog); in
> do_misc_fixups() doesn't sort the table correctly.
> This is a problem from s390 as its JIT uses this table to find the
> addresses for kfuncs, and if this table is not sorted properly, JIT can
> fail to find addresses for valid kfunc calls.
>
> This was exposed by:
>
> commit d869d56ca848 ("bpf: verifier: refactor kfunc specialization")
>
> as before this commit, desc->imm was initialised in add_kfunc_call().
>
> Initialize desc->imm to func_id, it will be overwritten in
> specialize_kfunc() if the instruction is not removed.
>
> Fixes: d869d56ca848 ("bpf: verifier: refactor kfunc specialization")
> Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
> ---
>
> This bug is not triggered by the CI currently, I am working on another
> set for non-sleepbale arena allocations and as part of that I am adding
> a new selftest that triggers this bug.
>
> Selftest: https://github.com/kernel-patches/bpf/pull/10242/commits/1f681f022c6d685fd76695e5eafbe9d9ab4c0002
> CI run: https://github.com/kernel-patches/bpf/actions/runs/19238699806/job/54996376908
>
> ---
> kernel/bpf/verifier.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 1268fa075d4c..a667f761173c 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -3371,6 +3371,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
>
> desc = &tab->descs[tab->nr_descs++];
> desc->func_id = func_id;
> + desc->imm = func_id;
> desc->offset = offset;
> desc->addr = addr;
> desc->func_model = func_model;
Thanks for sending the fix.
I'm not sure if this is enough, though. Don't you need to run entire
calculation
for the desc->imm, like in the original, before
d869d56ca848 ("bpf: verifier: refactor kfunc specialization")?
if (bpf_jit_supports_far_kfunc_call()) {
call_imm = func_id;
} else {
call_imm = BPF_CALL_IMM(addr);
/* Check whether the relative offset overflows desc->imm */
if ((unsigned long)(s32)call_imm != call_imm) {
verbose(env, "address of kernel func_id %u is out of
range\n", func_id);
return -EINVAL;
}
}
desc->imm = call_imm;
I think it would be right to reuse that hunk in both places:
add_kfunc_call() and specialize_kfunc().
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next] bpf: verifier: initialize imm in kfunc_tab in add_kfunc_call()
2025-11-11 18:38 ` Mykyta Yatsenko
@ 2025-11-12 0:01 ` Puranjay Mohan
0 siblings, 0 replies; 3+ messages in thread
From: Puranjay Mohan @ 2025-11-12 0:01 UTC (permalink / raw)
To: Mykyta Yatsenko
Cc: Puranjay Mohan, bpf, Alexei Starovoitov, Andrii Nakryiko,
Daniel Borkmann, Martin KaFai Lau, Eduard Zingerman,
Kumar Kartikeya Dwivedi, kernel-team
On Tue, Nov 11, 2025 at 7:38 PM Mykyta Yatsenko
<mykyta.yatsenko5@gmail.com> wrote:
>
> On 11/11/25 16:09, Puranjay Mohan wrote:
> > Metadata about a kfunc call is added to the kfunc_tab in
> > add_kfunc_call() but the call instruction itself could get removed by
> > opt_remove_dead_code() later if it is not reachable.
> >
> > If the call instruction is removed, specialize_kfunc() is never called
> > for it and the desc->imm in the kfunc_tab is never initialized for this
> > kfunc call. In this case, sort_kfunc_descs_by_imm_off(env->prog); in
> > do_misc_fixups() doesn't sort the table correctly.
> > This is a problem from s390 as its JIT uses this table to find the
> > addresses for kfuncs, and if this table is not sorted properly, JIT can
> > fail to find addresses for valid kfunc calls.
> >
> > This was exposed by:
> >
> > commit d869d56ca848 ("bpf: verifier: refactor kfunc specialization")
> >
> > as before this commit, desc->imm was initialised in add_kfunc_call().
> >
> > Initialize desc->imm to func_id, it will be overwritten in
> > specialize_kfunc() if the instruction is not removed.
> >
> > Fixes: d869d56ca848 ("bpf: verifier: refactor kfunc specialization")
> > Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
> > ---
> >
> > This bug is not triggered by the CI currently, I am working on another
> > set for non-sleepbale arena allocations and as part of that I am adding
> > a new selftest that triggers this bug.
> >
> > Selftest: https://github.com/kernel-patches/bpf/pull/10242/commits/1f681f022c6d685fd76695e5eafbe9d9ab4c0002
> > CI run: https://github.com/kernel-patches/bpf/actions/runs/19238699806/job/54996376908
> >
> > ---
> > kernel/bpf/verifier.c | 1 +
> > 1 file changed, 1 insertion(+)
> >
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 1268fa075d4c..a667f761173c 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -3371,6 +3371,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
> >
> > desc = &tab->descs[tab->nr_descs++];
> > desc->func_id = func_id;
> > + desc->imm = func_id;
> > desc->offset = offset;
> > desc->addr = addr;
> > desc->func_model = func_model;
> Thanks for sending the fix.
> I'm not sure if this is enough, though. Don't you need to run entire
> calculation
> for the desc->imm, like in the original, before
> d869d56ca848 ("bpf: verifier: refactor kfunc specialization")?
>
> if (bpf_jit_supports_far_kfunc_call()) {
> call_imm = func_id;
> } else {
> call_imm = BPF_CALL_IMM(addr);
> /* Check whether the relative offset overflows desc->imm */
> if ((unsigned long)(s32)call_imm != call_imm) {
> verbose(env, "address of kernel func_id %u is out of
> range\n", func_id);
> return -EINVAL;
> }
> }
> desc->imm = call_imm;
>
> I think it would be right to reuse that hunk in both places:
> add_kfunc_call() and specialize_kfunc().
Yes, I agree with you. Currently it doesn't make a difference because
only s390 uses it
and it needs the func_id to be in desc->imm, but for completeness we
should do the proper
calculation to not introduce bugs for later developments.
I will send v2 with this entire calculation. and we can remove:
if (bpf_jit_supports_far_kfunc_call()) {
call_imm = func_id;
from specialize_kfunc() as it is redundant.
Thanks,
Puranjay
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-11-12 0:01 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-11 16:09 [PATCH bpf-next] bpf: verifier: initialize imm in kfunc_tab in add_kfunc_call() Puranjay Mohan
2025-11-11 18:38 ` Mykyta Yatsenko
2025-11-12 0:01 ` Puranjay Mohan
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox