Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Search and add kfuncs in struct_ops prologue and epilogue

Currently, add_kfunc_call() is only invoked once before the main
verification loop. Therefore, the verifier could not find the
bpf_kfunc_btf_tab of a new kfunc call which is not seen in user defined
struct_ops operators but introduced in gen_prologue or gen_epilogue
during do_misc_fixup(). Fix this by searching kfuncs in the patching
instruction buffer and add them to prog->aux->kfunc_tab.

Signed-off-by: Amery Hung <amery.hung@bytedance.com>
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Acked-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20250225233545.285481-1-ameryhung@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Amery Hung and committed by
Alexei Starovoitov
d519594e f3c2d243

+24 -1
+24 -1
kernel/bpf/verifier.c
··· 3275 3275 return res ? &res->func_model : NULL; 3276 3276 } 3277 3277 3278 + static int add_kfunc_in_insns(struct bpf_verifier_env *env, 3279 + struct bpf_insn *insn, int cnt) 3280 + { 3281 + int i, ret; 3282 + 3283 + for (i = 0; i < cnt; i++, insn++) { 3284 + if (bpf_pseudo_kfunc_call(insn)) { 3285 + ret = add_kfunc_call(env, insn->imm, insn->off); 3286 + if (ret < 0) 3287 + return ret; 3288 + } 3289 + } 3290 + return 0; 3291 + } 3292 + 3278 3293 static int add_subprog_and_kfunc(struct bpf_verifier_env *env) 3279 3294 { 3280 3295 struct bpf_subprog_info *subprog = env->subprog_info; ··· 20448 20433 { 20449 20434 struct bpf_subprog_info *subprogs = env->subprog_info; 20450 20435 const struct bpf_verifier_ops *ops = env->ops; 20451 - int i, cnt, size, ctx_field_size, delta = 0, epilogue_cnt = 0; 20436 + int i, cnt, size, ctx_field_size, ret, delta = 0, epilogue_cnt = 0; 20452 20437 const int insn_cnt = env->prog->len; 20453 20438 struct bpf_insn *epilogue_buf = env->epilogue_buf; 20454 20439 struct bpf_insn *insn_buf = env->insn_buf; ··· 20477 20462 return -ENOMEM; 20478 20463 env->prog = new_prog; 20479 20464 delta += cnt - 1; 20465 + 20466 + ret = add_kfunc_in_insns(env, epilogue_buf, epilogue_cnt - 1); 20467 + if (ret < 0) 20468 + return ret; 20480 20469 } 20481 20470 } 20482 20471 ··· 20501 20482 20502 20483 env->prog = new_prog; 20503 20484 delta += cnt - 1; 20485 + 20486 + ret = add_kfunc_in_insns(env, insn_buf, cnt - 1); 20487 + if (ret < 0) 20488 + return ret; 20504 20489 } 20505 20490 } 20506 20491