Re: [PATCH v2 2/3] LoongArch: BPF: Inline bpf_get_current_task{_btf}() helpers

From: Tiezhu Yang

Date: Wed Jun 10 2026 - 23:29:09 EST


On 2026/6/11 上午10:36, bot+bpf-ci@xxxxxxxxxx wrote:
The pointer to task_struct is always available in the $tp register,
the calls to bpf_get_current_task() and bpf_get_current_task_btf()
can be inlined into a single move instruction.

[ ... ]

This is similar with commit 2bb138cb20a6 ("bpf, arm64: Inline
bpf_get_current_task/_btf() helpers").

Additionally, a safety check for bpf_jit_enable is introduced in
bpf_jit_inlines_helper_call(). If CONFIG_BPF_JIT_ALWAYS_ON is not
set and JIT is disabled at runtime, the function returns false to
safely accommodate the fallback path to the BPF interpreter.

Without this check, bpf_jit_inlines_helper_call() unconditionally
returns true. As a result, the verifier would skip fixing up the
call offset, leaving insn->imm as the raw helper ID rather than
the expected "insn->imm = fn->func - __bpf_call_base".

When the fallback interpreter executes (__bpf_call_base + insn->imm)
with this raw ID, it jumps into an unaligned invalid address space,
triggering a fatal instruction alignment fault (ADEF) kernel panic.

[ ... ]

Signed-off-by: Tiezhu Yang <yangtiezhu@xxxxxxxxxxx>

The commit message describes a kernel panic on the interpreter fallback
path, where bpf_jit_inlines_helper_call() returning true caused the
verifier to skip rewriting insn->imm to (fn->func - __bpf_call_base),
so the interpreter ran (__bpf_call_base + raw_helper_id) and jumped to
an invalid address.

The bpf_jit_inlines_helper_call() contract, and the verifier logic that
skips the call-offset fixup when it returns true, were introduced
together with the unconditional return-true pattern that is now being
guarded with the !bpf_jit_enable check.

Should this carry a Fixes: tag pointing at that commit, for example:

Fixes: 2ddec2c80b44 ("riscv, bpf: inline bpf_get_smp_processor_id()")


This is a generic problem, as sashiko-bot@xxxxxxxxxx said:
"Could this root cause be addressed in the BPF core instead of being
handled as an architecture-specific workaround?"

I will do the following changes:

diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index 448162584c9a..4f2493c549f1 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -2384,10 +2384,6 @@ bool bpf_jit_supports_subprog_tailcalls(void)

bool bpf_jit_inlines_helper_call(s32 imm)
{
- /* Prevent interpreter panic when JIT is disabled at runtime */
- if (!bpf_jit_enable)
- return false;
-
switch (imm) {
case BPF_FUNC_get_current_task:
case BPF_FUNC_get_current_task_btf:
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index 6aa2a8b24030..8e08887e6534 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -2598,6 +2598,30 @@ static struct bpf_prog *bpf_prog_jit_compile(struct bpf_verifier_env *env, struc
return prog;
}

+/*
+ * Rewrite the helper call offset for inlined helpers when fallback to
+ * the interpreter happens due to JIT compilation failure or JIT disabled.
+ */
+static void bpf_fixup_fallback_inline_helpers(struct bpf_verifier_env *env, struct bpf_prog *fp)
+{
+ struct bpf_insn *insn = fp->insnsi;
+ const struct bpf_func_proto *fn;
+ int i;
+
+ if (!env || !env->ops->get_func_proto)
+ return;
+
+ for (i = 0; i < fp->len; i++, insn++) {
+ if (insn->code == (BPF_JMP | BPF_CALL) && insn->src_reg == 0) {
+ if (bpf_jit_inlines_helper_call(insn->imm)) {
+ fn = env->ops->get_func_proto(insn->imm, fp);
+ if (fn && fn->func)
+ insn->imm = fn->func - __bpf_call_base;
+ }
+ }
+ }
+}
+
struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct bpf_prog *fp,
int *err)
{
@@ -2629,6 +2653,15 @@ struct bpf_prog *__bpf_prog_select_runtime(struct bpf_verifier_env *env, struct

fp = bpf_prog_jit_compile(env, fp);
bpf_prog_jit_attempt_done(fp);
+
+ /*
+ * If JIT compilation failed or is disabled (!fp->jited), we are
+ * about to fall back to the interpreter path. Fix up the call
+ * offsets to prevent unaligned memory access panic.
+ */
+ if (!fp->jited)
+ bpf_fixup_fallback_inline_helpers(env, fp);
+
if (!fp->jited && jit_needed) {
*err = -ENOTSUPP;
return fp;

Thanks,
Tiezhu