From: Yazhou Tang In jit_subprogs(), restoring bpf_pseudo_call instructions truncates the 32-bit call_imm into the 16-bit insn->off. For large BPF programs (e.g., call_imm > 32767), this silent truncation causes find_subprog() to return an incorrect subprog ID, which is then stored in insn->imm. Consequently, "bpftool prog dump xlated" reads the corrupted insn->imm, fails to resolve the subprogram name, and incorrectly displays a raw kernel pointer. For example, dumping the xlated bytecode of the JIT-loaded selftest introduced in patch 2/3 (call_imm == 32768, i.e., 0x00008000) shows that it is truncated to 0x8000 and reinterpreted as -32768 in s16: Before this patch (with call_imm > 32767): 4: (85) call pc+2#bpf_prog_71cfe20590be813a_padding_subprog 5: (85) call pc-32768#0xffffffff814aed4e After this patch: 4: (85) call pc+2#bpf_prog_71cfe20590be813a_padding_subprog 5: (85) call pc-32768#bpf_prog_5dccd3f669bbe4e4_target_subprog This patch fixes the issue by passing the un-truncated 32-bit env->insn_aux_data[i].call_imm directly to find_subprog(). Note that the assignment to insn->off is retained. Although it still truncates for large jumps, it remains correct for the vast majority of BPF programs where the offset fits within s16 bounds. Keeping it ensures backward compatibility for existing user-space tools that rely on insn->off to display the relative offset. A comment is added to explicitly clarify this truncation behavior. Suggested-by: Puranjay Mohan Fixes: 7105e828c087 ("bpf: allow for correlation of maps and helpers in dump") Co-developed-by: Tianci Cao Signed-off-by: Tianci Cao Co-developed-by: Shenghao Yuan Signed-off-by: Shenghao Yuan Signed-off-by: Yazhou Tang Reviewed-by: Emil Tsalapatis --- kernel/bpf/verifier.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 702579f56f7d..e87fedb09e1b 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -23017,8 +23017,12 @@ static int jit_subprogs(struct bpf_verifier_env *env) } if (!bpf_pseudo_call(insn)) continue; + /* + * Note: If the original insn->imm is out of s16 bounds, + * insn->off here will be a truncated value. + */ insn->off = env->insn_aux_data[i].call_imm; - subprog = find_subprog(env, i + insn->off + 1); + subprog = find_subprog(env, i + env->insn_aux_data[i].call_imm + 1); insn->imm = subprog; } -- 2.53.0