* [PATCH bpf-next v8 0/2] Introduce jit_required to prevent a kernel panic
@ 2026-07-06 4:00 Tiezhu Yang
2026-07-06 4:00 ` [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call() Tiezhu Yang
2026-07-06 4:00 ` [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available Tiezhu Yang
0 siblings, 2 replies; 13+ messages in thread
From: Tiezhu Yang @ 2026-07-06 4:00 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, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
This series introduces a 'jit_required' flag in struct bpf_prog
to track programs that strictly require JIT.
The aim is to prevent a kernel panic by rejecting programs with
inlined helpers when JIT is not available.
v8:
-- Completely remove bpf_prog_has_kfunc_call().
-- Set jit_required at the entry of bpf_add_kfunc_call().
-- Generalize the error message to:
"program requires BPF JIT compiler but it is not available"
Tiezhu Yang (2):
bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call()
bpf: Reject programs with inlined helpers if JIT is not available
include/linux/bpf.h | 9 ++-------
kernel/bpf/core.c | 3 +--
kernel/bpf/fixups.c | 9 +++++----
kernel/bpf/verifier.c | 7 ++-----
4 files changed, 10 insertions(+), 18 deletions(-)
--
2.42.0
^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call()
2026-07-06 4:00 [PATCH bpf-next v8 0/2] Introduce jit_required to prevent a kernel panic Tiezhu Yang
@ 2026-07-06 4:00 ` Tiezhu Yang
2026-07-06 11:39 ` KaFai Wan
2026-07-06 4:00 ` [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available Tiezhu Yang
1 sibling, 1 reply; 13+ messages in thread
From: Tiezhu Yang @ 2026-07-06 4:00 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, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
Introduce a 'jit_required' bitfield flag in struct bpf_prog. This bit
tracks whether a BPF program strictly requires the JIT compiler to run,
preventing dangerous runtime fallback to the interpreter for features
not implemented there.
Set the flag 'jit_required' to 1 at the entry of bpf_add_kfunc_call()
right after the kfunc_tab allocation succeeds. This cleanly marks the
lifecycle of any program attempting to utilize kernel functions.
Furthermore, completely remove the bpf_prog_has_kfunc_call() helper,
as its logic is now unified under the 'jit_required' flag.
In bpf_fixup_call_args(), check with 'prog->jit_required' rather than
bpf_prog_has_kfunc_call(), and generalize the error message to generic
BPF JIT availability.
In __bpf_prog_select_runtime(), check with 'fp->jit_required' rather
than bpf_prog_has_kfunc_call() to unify the logic.
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Suggested-by: KaFai Wan <kafai.wan@linux.dev>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
include/linux/bpf.h | 9 ++-------
kernel/bpf/core.c | 3 +--
kernel/bpf/fixups.c | 5 ++---
kernel/bpf/verifier.c | 7 ++-----
4 files changed, 7 insertions(+), 17 deletions(-)
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index ba09795e0bfd..0b620bfbbd9b 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1865,8 +1865,9 @@ struct bpf_prog_aux {
struct bpf_prog {
u16 pages; /* Number of allocated pages */
- u16 jited:1, /* Is our filter JIT'ed? */
+ u32 jited:1, /* Is our filter JIT'ed? */
jit_requested:1,/* archs need to JIT the prog */
+ jit_required:1, /* program strictly requires JIT compiler */
gpl_compatible:1, /* Is filter GPL compatible? */
cb_access:1, /* Is control block accessed? */
dst_needed:1, /* Do we need dst entry? */
@@ -3170,7 +3171,6 @@ const struct bpf_func_proto *bpf_base_func_proto(enum bpf_func_id func_id,
const struct bpf_prog *prog);
void bpf_task_storage_free(struct task_struct *task);
void bpf_cgrp_storage_free(struct cgroup *cgroup);
-bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog);
const struct btf_func_model *
bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
const struct bpf_insn *insn);
@@ -3509,11 +3509,6 @@ static inline void bpf_task_storage_free(struct task_struct *task)
{
}
-static inline bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
-{
- return false;
-}
-
static inline const struct btf_func_model *
bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
const struct bpf_insn *insn)
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 6e19a030da6f..faef1de84fa7 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2675,8 +2675,7 @@ struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct
if (fp->bpf_func)
goto finalize;
- if (IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON) ||
- bpf_prog_has_kfunc_call(fp))
+ if (IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON) || fp->jit_required)
jit_needed = true;
if (!bpf_prog_select_interpreter(fp))
diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index 12a8a4eb757f..02246df2f6c3 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -1378,7 +1378,6 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
struct bpf_prog *prog = env->prog;
struct bpf_insn *insn = prog->insnsi;
- bool has_kfunc_call = bpf_prog_has_kfunc_call(prog);
int depth;
#endif
int i, err = 0;
@@ -1404,8 +1403,8 @@ int bpf_fixup_call_args(struct bpf_verifier_env *env)
return err;
}
#ifndef CONFIG_BPF_JIT_ALWAYS_ON
- if (has_kfunc_call) {
- verbose(env, "calling kernel functions are not allowed in non-JITed programs\n");
+ if (prog->jit_required) {
+ verbose(env, "program requires BPF JIT compiler but it is not available\n");
return -EINVAL;
}
for (i = 0; i < env->subprog_cnt; i++) {
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index d46f7db20d8f..e188d55e8116 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2714,6 +2714,8 @@ int bpf_add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, u16 offset)
prog_aux->kfunc_tab = tab;
}
+ env->prog->jit_required = 1;
+
/* func_id == 0 is always invalid, but instead of returning an error, be
* conservative and wait until the code elimination pass before returning
* error, so that invalid calls that get pruned out can be in BPF programs
@@ -2768,11 +2770,6 @@ int bpf_add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, u16 offset)
return 0;
}
-bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
-{
- return !!prog->aux->kfunc_tab;
-}
-
static int add_subprog_and_kfunc(struct bpf_verifier_env *env)
{
struct bpf_subprog_info *subprog = env->subprog_info;
--
2.42.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-06 4:00 [PATCH bpf-next v8 0/2] Introduce jit_required to prevent a kernel panic Tiezhu Yang
2026-07-06 4:00 ` [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call() Tiezhu Yang
@ 2026-07-06 4:00 ` Tiezhu Yang
2026-07-06 21:41 ` Eduard Zingerman
1 sibling, 1 reply; 13+ messages in thread
From: Tiezhu Yang @ 2026-07-06 4:00 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, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
When an architecture (such as LoongArch, ARM64, and RISC-V) implements
bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
the helper is expected to be inlined by the JIT compiler. As a result,
insn->imm remains as the raw helper enum ID.
However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
if the JIT compilation later dynamically fails (e.g., due to OOM), the
core BPF subsystem falls back to the BPF interpreter.
When the interpreter executes (__bpf_call_base + insn->imm) with the
unpatched raw helper ID, it jumps into an unaligned invalid address
space, triggering an instruction alignment fault or a memory access
panic.
Fix this by setting 'jit_required' to 1 when helper call rewriting is
skipped for JIT inlining. Loading will be rejected early with -EINVAL
if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
selection if JIT compilation dynamically fails, effectively preventing
the kernel panic.
Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
Suggested-by: Alexei Starovoitov <ast@kernel.org>
Suggested-by: KaFai Wan <kafai.wan@linux.dev>
Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
---
kernel/bpf/fixups.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index 02246df2f6c3..d3be972714b2 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -1840,8 +1840,10 @@ int bpf_do_misc_fixups(struct bpf_verifier_env *env)
}
/* Skip inlining the helper call if the JIT does it. */
- if (bpf_jit_inlines_helper_call(insn->imm))
+ if (bpf_jit_inlines_helper_call(insn->imm)) {
+ prog->jit_required = 1;
goto next_insn;
+ }
if (insn->imm == BPF_FUNC_get_route_realm)
prog->dst_needed = 1;
--
2.42.0
^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call()
2026-07-06 4:00 ` [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call() Tiezhu Yang
@ 2026-07-06 11:39 ` KaFai Wan
2026-07-07 1:43 ` Tiezhu Yang
0 siblings, 1 reply; 13+ messages in thread
From: KaFai Wan @ 2026-07-06 11:39 UTC (permalink / raw)
To: Tiezhu Yang, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
> Introduce a 'jit_required' bitfield flag in struct bpf_prog. This bit
> tracks whether a BPF program strictly requires the JIT compiler to run,
> preventing dangerous runtime fallback to the interpreter for features
> not implemented there.
>
> Set the flag 'jit_required' to 1 at the entry of bpf_add_kfunc_call()
> right after the kfunc_tab allocation succeeds. This cleanly marks the
> lifecycle of any program attempting to utilize kernel functions.
>
> Furthermore, completely remove the bpf_prog_has_kfunc_call() helper,
> as its logic is now unified under the 'jit_required' flag.
>
> In bpf_fixup_call_args(), check with 'prog->jit_required' rather than
> bpf_prog_has_kfunc_call(), and generalize the error message to generic
> BPF JIT availability.
>
> In __bpf_prog_select_runtime(), check with 'fp->jit_required' rather
> than bpf_prog_has_kfunc_call() to unify the logic.
>
If you have a new version, I think we could simplify the description of the code details a bit.
The code is fine by me, others might have comments.
> Suggested-by: Alexei Starovoitov <ast@kernel.org>
> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
--
Thanks,
KaFai
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-06 4:00 ` [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available Tiezhu Yang
@ 2026-07-06 21:41 ` Eduard Zingerman
2026-07-07 1:37 ` Tiezhu Yang
2026-07-07 2:03 ` Leon Hwang
0 siblings, 2 replies; 13+ messages in thread
From: Eduard Zingerman @ 2026-07-06 21:41 UTC (permalink / raw)
To: Tiezhu Yang, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
> When an architecture (such as LoongArch, ARM64, and RISC-V) implements
> bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
> call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
> the helper is expected to be inlined by the JIT compiler. As a result,
> insn->imm remains as the raw helper enum ID.
>
> However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
> if the JIT compilation later dynamically fails (e.g., due to OOM), the
> core BPF subsystem falls back to the BPF interpreter.
>
> When the interpreter executes (__bpf_call_base + insn->imm) with the
> unpatched raw helper ID, it jumps into an unaligned invalid address
> space, triggering an instruction alignment fault or a memory access
> panic.
>
> Fix this by setting 'jit_required' to 1 when helper call rewriting is
> skipped for JIT inlining. Loading will be rejected early with -EINVAL
> if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
> selection if JIT compilation dynamically fails, effectively preventing
> the kernel panic.
>
> Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> Suggested-by: Alexei Starovoitov <ast@kernel.org>
> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> ---
Sorry, I'm late to the party.
As far as I understand, the patch #1 doesn't really change anything functionally,
it just adds the flag, right?
As for the patch #2 and looking at the helpers that jits currently inline:
- bpf_get_smp_processor_id (implemented as a function in the helpers.c)
- bpf_get_current_task (implemented as a function in the bpf_trace.c)
- bpf_get_current_task_btf (implemented as a function in the bpf_trace.c)
It is perfectly fine to call these as helper functions even if jit is
not available. But this was broken since:
2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
from May 2024, so I guess nobody really cares?
Imo, the simplest and least intrusive fix is to add a wrapper in the
verifier.c that would call both bpf_jit_inlines_helper_call() and
check if the jit is enabled and use that wrapper instead of direct
calls to bpf_jit_inlines_helper_call().
Anyway, since this was broken all-along, might as well land as-is.
Thoughts?
[...]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-06 21:41 ` Eduard Zingerman
@ 2026-07-07 1:37 ` Tiezhu Yang
2026-07-07 9:13 ` Eduard Zingerman
2026-07-07 2:03 ` Leon Hwang
1 sibling, 1 reply; 13+ messages in thread
From: Tiezhu Yang @ 2026-07-07 1:37 UTC (permalink / raw)
To: Eduard Zingerman, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
On 2026/7/7 上午5:41, Eduard Zingerman wrote:
> On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
>> When an architecture (such as LoongArch, ARM64, and RISC-V) implements
>> bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
>> call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
>> the helper is expected to be inlined by the JIT compiler. As a result,
>> insn->imm remains as the raw helper enum ID.
>>
>> However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
>> if the JIT compilation later dynamically fails (e.g., due to OOM), the
>> core BPF subsystem falls back to the BPF interpreter.
>>
>> When the interpreter executes (__bpf_call_base + insn->imm) with the
>> unpatched raw helper ID, it jumps into an unaligned invalid address
>> space, triggering an instruction alignment fault or a memory access
>> panic.
>>
>> Fix this by setting 'jit_required' to 1 when helper call rewriting is
>> skipped for JIT inlining. Loading will be rejected early with -EINVAL
>> if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
>> selection if JIT compilation dynamically fails, effectively preventing
>> the kernel panic.
>>
>> Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
>> Suggested-by: Alexei Starovoitov <ast@kernel.org>
>> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>> ---
>
> Sorry, I'm late to the party.
> As far as I understand, the patch #1 doesn't really change anything functionally,
> it just adds the flag, right?
>
> As for the patch #2 and looking at the helpers that jits currently inline:
> - bpf_get_smp_processor_id (implemented as a function in the helpers.c)
> - bpf_get_current_task (implemented as a function in the bpf_trace.c)
> - bpf_get_current_task_btf (implemented as a function in the bpf_trace.c)
>
> It is perfectly fine to call these as helper functions even if jit is
> not available. But this was broken since:
> 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> from May 2024, so I guess nobody really cares?
>
> Imo, the simplest and least intrusive fix is to add a wrapper in the
> verifier.c that would call both bpf_jit_inlines_helper_call() and
> check if the jit is enabled and use that wrapper instead of direct
> calls to bpf_jit_inlines_helper_call().
>
> Anyway, since this was broken all-along, might as well land as-is.
> Thoughts?
In the previous v4 [1], there is a similar way to fix unaligned
interpreter panic on JIT fallback path, but it was explicitly
rejected by the BPF maintainer Alexei [2]. Furthermore, Alexei
said "The interpreter has to be removed completely... sooner
or later." [3]. So if JIT is not available, rejecting the program
load is the intended design.
[1]
https://lore.kernel.org/bpf/20260615025316.24429-1-yangtiezhu@loongson.cn/
[2] https://lore.kernel.org/bpf/DJMRIZ5PDWP4.12OOZ8H881H6O@gmail.com/
[3] https://lore.kernel.org/bpf/DJN001X0S57Y.18CKUS4NDDQT1@gmail.com/
Thanks,
Tiezhu
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call()
2026-07-06 11:39 ` KaFai Wan
@ 2026-07-07 1:43 ` Tiezhu Yang
0 siblings, 0 replies; 13+ messages in thread
From: Tiezhu Yang @ 2026-07-07 1:43 UTC (permalink / raw)
To: KaFai Wan, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
On 2026/7/6 下午7:39, KaFai Wan wrote:
> On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
>> Introduce a 'jit_required' bitfield flag in struct bpf_prog. This bit
>> tracks whether a BPF program strictly requires the JIT compiler to run,
>> preventing dangerous runtime fallback to the interpreter for features
>> not implemented there.
>>
>> Set the flag 'jit_required' to 1 at the entry of bpf_add_kfunc_call()
>> right after the kfunc_tab allocation succeeds. This cleanly marks the
>> lifecycle of any program attempting to utilize kernel functions.
>>
>> Furthermore, completely remove the bpf_prog_has_kfunc_call() helper,
>> as its logic is now unified under the 'jit_required' flag.
>>
>> In bpf_fixup_call_args(), check with 'prog->jit_required' rather than
>> bpf_prog_has_kfunc_call(), and generalize the error message to generic
>> BPF JIT availability.
>>
>> In __bpf_prog_select_runtime(), check with 'fp->jit_required' rather
>> than bpf_prog_has_kfunc_call() to unify the logic.
>>
>
> If you have a new version, I think we could simplify the description of the code details a bit.
OK, will do it in v9.
> The code is fine by me, others might have comments.
As suggested by Leon and you, I will modify the code to:
"fp->jit_required = IS_ENABLED(CONFIG_BPF_JIT_ALWAYS_ON)"
in v9.
Thanks,
Tiezhu
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-06 21:41 ` Eduard Zingerman
2026-07-07 1:37 ` Tiezhu Yang
@ 2026-07-07 2:03 ` Leon Hwang
2026-07-07 9:27 ` Eduard Zingerman
1 sibling, 1 reply; 13+ messages in thread
From: Leon Hwang @ 2026-07-07 2:03 UTC (permalink / raw)
To: Eduard Zingerman, Tiezhu Yang, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Puranjay Mohan, Björn Töpel
On 7/7/26 05:41, Eduard Zingerman wrote:
> On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
>> When an architecture (such as LoongArch, ARM64, and RISC-V) implements
>> bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
>> call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
>> the helper is expected to be inlined by the JIT compiler. As a result,
>> insn->imm remains as the raw helper enum ID.
>>
>> However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
>> if the JIT compilation later dynamically fails (e.g., due to OOM), the
>> core BPF subsystem falls back to the BPF interpreter.
>>
>> When the interpreter executes (__bpf_call_base + insn->imm) with the
>> unpatched raw helper ID, it jumps into an unaligned invalid address
>> space, triggering an instruction alignment fault or a memory access
>> panic.
>>
>> Fix this by setting 'jit_required' to 1 when helper call rewriting is
>> skipped for JIT inlining. Loading will be rejected early with -EINVAL
>> if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
>> selection if JIT compilation dynamically fails, effectively preventing
>> the kernel panic.
>>
>> Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
>> Suggested-by: Alexei Starovoitov <ast@kernel.org>
>> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>> ---
>
> Sorry, I'm late to the party.
> As far as I understand, the patch #1 doesn't really change anything functionally,
> it just adds the flag, right?
>
> As for the patch #2 and looking at the helpers that jits currently inline:
> - bpf_get_smp_processor_id (implemented as a function in the helpers.c)
> - bpf_get_current_task (implemented as a function in the bpf_trace.c)
> - bpf_get_current_task_btf (implemented as a function in the bpf_trace.c)
>
> It is perfectly fine to call these as helper functions even if jit is
> not available. But this was broken since:
> 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> from May 2024, so I guess nobody really cares?
Vincent Thiberville reported an interpreter fallback issue for the
internal BPF_ADDR_PERCPU insn [1]. And, I was trying to fix assorted
interpreter fallback issues [2].
I think it is worth fixing the interpreter fallback issue for the JIT
inlineable helper.
[1]
https://lore.kernel.org/bpf/MR1P264MB331494502C9D13D8A9EAFB99B7E82@MR1P264MB3314.FRAP264.PROD.OUTLOOK.COM/
[2] https://lore.kernel.org/bpf/20260626154330.33619-1-leon.hwang@linux.dev/
Thanks,
Leon
>
> Imo, the simplest and least intrusive fix is to add a wrapper in the
> verifier.c that would call both bpf_jit_inlines_helper_call() and
> check if the jit is enabled and use that wrapper instead of direct
> calls to bpf_jit_inlines_helper_call().
>
> Anyway, since this was broken all-along, might as well land as-is.
> Thoughts?
>
> [...]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-07 1:37 ` Tiezhu Yang
@ 2026-07-07 9:13 ` Eduard Zingerman
2026-07-07 10:39 ` Tiezhu Yang
0 siblings, 1 reply; 13+ messages in thread
From: Eduard Zingerman @ 2026-07-07 9:13 UTC (permalink / raw)
To: Tiezhu Yang, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
On Tue, 2026-07-07 at 09:37 +0800, Tiezhu Yang wrote:
> On 2026/7/7 上午5:41, Eduard Zingerman wrote:
> > On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
> > > When an architecture (such as LoongArch, ARM64, and RISC-V) implements
> > > bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
> > > call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
> > > the helper is expected to be inlined by the JIT compiler. As a result,
> > > insn->imm remains as the raw helper enum ID.
> > >
> > > However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
> > > if the JIT compilation later dynamically fails (e.g., due to OOM), the
> > > core BPF subsystem falls back to the BPF interpreter.
> > >
> > > When the interpreter executes (__bpf_call_base + insn->imm) with the
> > > unpatched raw helper ID, it jumps into an unaligned invalid address
> > > space, triggering an instruction alignment fault or a memory access
> > > panic.
> > >
> > > Fix this by setting 'jit_required' to 1 when helper call rewriting is
> > > skipped for JIT inlining. Loading will be rejected early with -EINVAL
> > > if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
> > > selection if JIT compilation dynamically fails, effectively preventing
> > > the kernel panic.
> > >
> > > Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> > > Suggested-by: Alexei Starovoitov <ast@kernel.org>
> > > Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> > > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> > > ---
> >
> > Sorry, I'm late to the party.
> > As far as I understand, the patch #1 doesn't really change anything functionally,
> > it just adds the flag, right?
> >
> > As for the patch #2 and looking at the helpers that jits currently inline:
> > - bpf_get_smp_processor_id (implemented as a function in the helpers.c)
> > - bpf_get_current_task (implemented as a function in the bpf_trace.c)
> > - bpf_get_current_task_btf (implemented as a function in the bpf_trace.c)
> >
> > It is perfectly fine to call these as helper functions even if jit is
> > not available. But this was broken since:
> > 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> > from May 2024, so I guess nobody really cares?
> >
> > Imo, the simplest and least intrusive fix is to add a wrapper in the
> > verifier.c that would call both bpf_jit_inlines_helper_call() and
> > check if the jit is enabled and use that wrapper instead of direct
> > calls to bpf_jit_inlines_helper_call().
> >
> > Anyway, since this was broken all-along, might as well land as-is.
> > Thoughts?
>
> In the previous v4 [1], there is a similar way to fix unaligned
> interpreter panic on JIT fallback path, but it was explicitly
> rejected by the BPF maintainer Alexei [2].
bpf_fixup_fallback_helpers() is not at all what I suggest and is
indeed a terrible idea. What I suggest is something like:
bool bpf_inline_helper_call(...)
{
return bpf_jit_inlines_helper_call(...) && <jit-is-enabled>;
}
Used in verifier.c and fixups.c to decide whether to inline the helper.
> Furthermore, Alexei
> said "The interpreter has to be removed completely... sooner
> or later." [3]. So if JIT is not available, rejecting the program
> load is the intended design.
>
> [1]
> https://lore.kernel.org/bpf/20260615025316.24429-1-yangtiezhu@loongson.cn/
> [2] https://lore.kernel.org/bpf/DJMRIZ5PDWP4.12OOZ8H881H6O@gmail.com/
> [3] https://lore.kernel.org/bpf/DJN001X0S57Y.18CKUS4NDDQT1@gmail.com/
>
> Thanks,
> Tiezhu
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-07 2:03 ` Leon Hwang
@ 2026-07-07 9:27 ` Eduard Zingerman
2026-07-07 13:42 ` Leon Hwang
0 siblings, 1 reply; 13+ messages in thread
From: Eduard Zingerman @ 2026-07-07 9:27 UTC (permalink / raw)
To: Leon Hwang, Tiezhu Yang, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Puranjay Mohan, Björn Töpel
On Tue, 2026-07-07 at 10:03 +0800, Leon Hwang wrote:
> On 7/7/26 05:41, Eduard Zingerman wrote:
> > On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
> > > When an architecture (such as LoongArch, ARM64, and RISC-V) implements
> > > bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
> > > call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
> > > the helper is expected to be inlined by the JIT compiler. As a result,
> > > insn->imm remains as the raw helper enum ID.
> > >
> > > However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
> > > if the JIT compilation later dynamically fails (e.g., due to OOM), the
> > > core BPF subsystem falls back to the BPF interpreter.
> > >
> > > When the interpreter executes (__bpf_call_base + insn->imm) with the
> > > unpatched raw helper ID, it jumps into an unaligned invalid address
> > > space, triggering an instruction alignment fault or a memory access
> > > panic.
> > >
> > > Fix this by setting 'jit_required' to 1 when helper call rewriting is
> > > skipped for JIT inlining. Loading will be rejected early with -EINVAL
> > > if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
> > > selection if JIT compilation dynamically fails, effectively preventing
> > > the kernel panic.
> > >
> > > Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> > > Suggested-by: Alexei Starovoitov <ast@kernel.org>
> > > Suggested-by: KaFai Wan <kafai.wan@linux.dev>
> > > Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
> > > ---
> >
> > Sorry, I'm late to the party.
> > As far as I understand, the patch #1 doesn't really change anything functionally,
> > it just adds the flag, right?
> >
> > As for the patch #2 and looking at the helpers that jits currently inline:
> > - bpf_get_smp_processor_id (implemented as a function in the helpers.c)
> > - bpf_get_current_task (implemented as a function in the bpf_trace.c)
> > - bpf_get_current_task_btf (implemented as a function in the bpf_trace.c)
> >
> > It is perfectly fine to call these as helper functions even if jit is
> > not available. But this was broken since:
> > 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
> > from May 2024, so I guess nobody really cares?
>
>
> Vincent Thiberville reported an interpreter fallback issue for the
> internal BPF_ADDR_PERCPU insn [1].
As far as I understand, [1] is caused by map lookup helper inlining,
bpf_jit_inlines_helper_call() is unrelated this mechanism and only
covers that three helpers I listed above.
> And, I was trying to fix assorted interpreter fallback issues [2].
>
> I think it is worth fixing the interpreter fallback issue for the JIT
> inlineable helper.
Meaning that you'd prefer the bpf_get_smp_processor_id() and co to
work correctly w/o JIT, do I understand you correctly?
>
> [1]
> https://lore.kernel.org/bpf/MR1P264MB331494502C9D13D8A9EAFB99B7E82@MR1P264MB3314.FRAP264.PROD.OUTLOOK.COM/
> [2] https://lore.kernel.org/bpf/20260626154330.33619-1-leon.hwang@linux.dev/
>
> Thanks,
> Leon
>
> >
> > Imo, the simplest and least intrusive fix is to add a wrapper in the
> > verifier.c that would call both bpf_jit_inlines_helper_call() and
> > check if the jit is enabled and use that wrapper instead of direct
> > calls to bpf_jit_inlines_helper_call().
> >
> > Anyway, since this was broken all-along, might as well land as-is.
> > Thoughts?
> >
> > [...]
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-07 9:13 ` Eduard Zingerman
@ 2026-07-07 10:39 ` Tiezhu Yang
0 siblings, 0 replies; 13+ messages in thread
From: Tiezhu Yang @ 2026-07-07 10:39 UTC (permalink / raw)
To: Eduard Zingerman, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Leon Hwang, Puranjay Mohan, Björn Töpel
On 2026/7/7 下午5:13, Eduard Zingerman wrote:
> On Tue, 2026-07-07 at 09:37 +0800, Tiezhu Yang wrote:
>> On 2026/7/7 上午5:41, Eduard Zingerman wrote:
>>> On Mon, 2026-07-06 at 12:00 +0800, Tiezhu Yang wrote:
>>>> When an architecture (such as LoongArch, ARM64, and RISC-V) implements
>>>> bpf_jit_inlines_helper_call(), the verifier skips rewriting the helper
>>>> call offset (insn->imm) during the bpf_do_misc_fixups() phase, because
>>>> the helper is expected to be inlined by the JIT compiler. As a result,
>>>> insn->imm remains as the raw helper enum ID.
>>>>
>>>> However, if JIT is disabled at runtime (net.core.bpf_jit_enable=0) or
>>>> if the JIT compilation later dynamically fails (e.g., due to OOM), the
>>>> core BPF subsystem falls back to the BPF interpreter.
>>>>
>>>> When the interpreter executes (__bpf_call_base + insn->imm) with the
>>>> unpatched raw helper ID, it jumps into an unaligned invalid address
>>>> space, triggering an instruction alignment fault or a memory access
>>>> panic.
>>>>
>>>> Fix this by setting 'jit_required' to 1 when helper call rewriting is
>>>> skipped for JIT inlining. Loading will be rejected early with -EINVAL
>>>> if JIT is disabled, or safely rejected with -ENOTSUPP during runtime
>>>> selection if JIT compilation dynamically fails, effectively preventing
>>>> the kernel panic.
>>>>
>>>> Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
>>>> Suggested-by: Alexei Starovoitov <ast@kernel.org>
>>>> Suggested-by: KaFai Wan <kafai.wan@linux.dev>
>>>> Signed-off-by: Tiezhu Yang <yangtiezhu@loongson.cn>
>>>> ---
>>>
>>> Sorry, I'm late to the party.
>>> As far as I understand, the patch #1 doesn't really change anything functionally,
>>> it just adds the flag, right?
>>>
>>> As for the patch #2 and looking at the helpers that jits currently inline:
>>> - bpf_get_smp_processor_id (implemented as a function in the helpers.c)
>>> - bpf_get_current_task (implemented as a function in the bpf_trace.c)
>>> - bpf_get_current_task_btf (implemented as a function in the bpf_trace.c)
>>>
>>> It is perfectly fine to call these as helper functions even if jit is
>>> not available. But this was broken since:
>>> 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")
>>> from May 2024, so I guess nobody really cares?
>>>
>>> Imo, the simplest and least intrusive fix is to add a wrapper in the
>>> verifier.c that would call both bpf_jit_inlines_helper_call() and
>>> check if the jit is enabled and use that wrapper instead of direct
>>> calls to bpf_jit_inlines_helper_call().
>>>
>>> Anyway, since this was broken all-along, might as well land as-is.
>>> Thoughts?
>>
>> In the previous v4 [1], there is a similar way to fix unaligned
>> interpreter panic on JIT fallback path, but it was explicitly
>> rejected by the BPF maintainer Alexei [2].
>
> bpf_fixup_fallback_helpers() is not at all what I suggest and is
> indeed a terrible idea. What I suggest is something like:
>
> bool bpf_inline_helper_call(...)
> {
> return bpf_jit_inlines_helper_call(...) && <jit-is-enabled>;
> }
>
> Used in verifier.c and fixups.c to decide whether to inline the helper.
Hi Eduard,
Sorry for the misunderstanding.
Your wrapper handles the load-time JIT-disabled case nicely.
The problem is, it cannot protect against the case where JIT
is enabled during verification but dynamically fails later.
In that scenario, the verifier would have already skipped the
rewrite based on the wrapper, and the fallback to interpreter
would still trigger the kernel panic.
By using the 'jit_required' flag, we can cleanly catch both
cases, and reject early or return -ENOTSUPP at runtime.
Please see the test log for the detailed fallback behaviors:
https://lore.kernel.org/loongarch/aa26b3fc-9717-4273-dd76-a0dd6b15ff61@loongson.cn/
Since you mentioned it "might as well land as-is", I will
proceed with v9 using this flag architecture.
Thanks,
Tiezhu
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-07 9:27 ` Eduard Zingerman
@ 2026-07-07 13:42 ` Leon Hwang
2026-07-07 16:31 ` Eduard Zingerman
0 siblings, 1 reply; 13+ messages in thread
From: Leon Hwang @ 2026-07-07 13:42 UTC (permalink / raw)
To: Eduard Zingerman, Tiezhu Yang, Alexei Starovoitov,
Daniel Borkmann, Andrii Nakryiko, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Puranjay Mohan, Björn Töpel
On 2026/7/7 17:27, Eduard Zingerman wrote:
> On Tue, 2026-07-07 at 10:03 +0800, Leon Hwang wrote:
[...]
>>
>> Vincent Thiberville reported an interpreter fallback issue for the
>> internal BPF_ADDR_PERCPU insn [1].
>
> As far as I understand, [1] is caused by map lookup helper inlining,
Correct.
> bpf_jit_inlines_helper_call() is unrelated this mechanism and only
> covers that three helpers I listed above.
Yes.
>
>> And, I was trying to fix assorted interpreter fallback issues [2].
>>
>> I think it is worth fixing the interpreter fallback issue for the JIT
>> inlineable helper.
>
> Meaning that you'd prefer the bpf_get_smp_processor_id() and co to
> work correctly w/o JIT, do I understand you correctly?
>
Hmm, no. According to Alexei's comment [1], we should reject the helper
by the way of this patch.
[1] https://lore.kernel.org/bpf/DJN001X0S57Y.18CKUS4NDDQT1@gmail.com/
Thanks,
Leon
^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available
2026-07-07 13:42 ` Leon Hwang
@ 2026-07-07 16:31 ` Eduard Zingerman
0 siblings, 0 replies; 13+ messages in thread
From: Eduard Zingerman @ 2026-07-07 16:31 UTC (permalink / raw)
To: Leon Hwang, Tiezhu Yang, Alexei Starovoitov, Daniel Borkmann,
Andrii Nakryiko, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis, KaFai Wan
Cc: bpf, loongarch, Puranjay Mohan, Björn Töpel
On Tue, 2026-07-07 at 21:42 +0800, Leon Hwang wrote:
> On 2026/7/7 17:27, Eduard Zingerman wrote:
[...]
> > Meaning that you'd prefer the bpf_get_smp_processor_id() and co to
> > work correctly w/o JIT, do I understand you correctly?
> >
> Hmm, no. According to Alexei's comment [1], we should reject the helper
> by the way of this patch.
>
> [1] https://lore.kernel.org/bpf/DJN001X0S57Y.18CKUS4NDDQT1@gmail.com/
Ok, good, the sooner the better. Thank you.
^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2026-07-07 16:32 UTC | newest]
Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-06 4:00 [PATCH bpf-next v8 0/2] Introduce jit_required to prevent a kernel panic Tiezhu Yang
2026-07-06 4:00 ` [PATCH bpf-next v8 1/2] bpf: Introduce jit_required flag and remove bpf_prog_has_kfunc_call() Tiezhu Yang
2026-07-06 11:39 ` KaFai Wan
2026-07-07 1:43 ` Tiezhu Yang
2026-07-06 4:00 ` [PATCH bpf-next v8 2/2] bpf: Reject programs with inlined helpers if JIT is not available Tiezhu Yang
2026-07-06 21:41 ` Eduard Zingerman
2026-07-07 1:37 ` Tiezhu Yang
2026-07-07 9:13 ` Eduard Zingerman
2026-07-07 10:39 ` Tiezhu Yang
2026-07-07 2:03 ` Leon Hwang
2026-07-07 9:27 ` Eduard Zingerman
2026-07-07 13:42 ` Leon Hwang
2026-07-07 16:31 ` Eduard Zingerman
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.