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

Configure Feed

Select the types of activity you want to include in your feed.

bpf: Introduce struct bpf_kfunc_meta

There is code duplication between add_kfunc_call() and
fetch_kfunc_meta() collecting information about a kfunc from BTF.

Introduce struct bpf_kfunc_meta to hold common kfunc BTF data and
implement fetch_kfunc_meta() to fill it in, instead of struct
bpf_kfunc_call_arg_meta directly.

Then use these in add_kfunc_call() and (new) fetch_kfunc_arg_meta()
functions, and fixup previous usages of fetch_kfunc_meta() to
fetch_kfunc_arg_meta().

Besides the code dedup, this change enables add_kfunc_call() to access
kfunc->flags.

Acked-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Link: https://lore.kernel.org/r/20260120222638.3976562-3-ihor.solodrai@linux.dev
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Ihor Solodrai and committed by
Alexei Starovoitov
08ca87d6 ea073d18

+93 -67
+93 -67
kernel/bpf/verifier.c
··· 294 294 s64 const_map_key; 295 295 }; 296 296 297 + struct bpf_kfunc_meta { 298 + struct btf *btf; 299 + const struct btf_type *proto; 300 + const char *name; 301 + const u32 *flags; 302 + s32 id; 303 + }; 304 + 297 305 struct bpf_kfunc_call_arg_meta { 298 306 /* In parameters */ 299 307 struct btf *btf; ··· 3271 3263 return btf_vmlinux ?: ERR_PTR(-ENOENT); 3272 3264 } 3273 3265 3274 - static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset) 3266 + static int fetch_kfunc_meta(struct bpf_verifier_env *env, 3267 + s32 func_id, 3268 + s16 offset, 3269 + struct bpf_kfunc_meta *kfunc) 3275 3270 { 3276 3271 const struct btf_type *func, *func_proto; 3272 + const char *func_name; 3273 + u32 *kfunc_flags; 3274 + struct btf *btf; 3275 + 3276 + if (func_id <= 0) { 3277 + verbose(env, "invalid kernel function btf_id %d\n", func_id); 3278 + return -EINVAL; 3279 + } 3280 + 3281 + btf = find_kfunc_desc_btf(env, offset); 3282 + if (IS_ERR(btf)) { 3283 + verbose(env, "failed to find BTF for kernel function\n"); 3284 + return PTR_ERR(btf); 3285 + } 3286 + 3287 + /* 3288 + * Note that kfunc_flags may be NULL at this point, which 3289 + * means that we couldn't find func_id in any relevant 3290 + * kfunc_id_set. This most likely indicates an invalid kfunc 3291 + * call. However we don't fail with an error here, 3292 + * and let the caller decide what to do with NULL kfunc->flags. 3293 + */ 3294 + kfunc_flags = btf_kfunc_flags(btf, func_id, env->prog); 3295 + 3296 + func = btf_type_by_id(btf, func_id); 3297 + if (!func || !btf_type_is_func(func)) { 3298 + verbose(env, "kernel btf_id %d is not a function\n", func_id); 3299 + return -EINVAL; 3300 + } 3301 + 3302 + func_name = btf_name_by_offset(btf, func->name_off); 3303 + func_proto = btf_type_by_id(btf, func->type); 3304 + if (!func_proto || !btf_type_is_func_proto(func_proto)) { 3305 + verbose(env, "kernel function btf_id %d does not have a valid func_proto\n", 3306 + func_id); 3307 + return -EINVAL; 3308 + } 3309 + 3310 + memset(kfunc, 0, sizeof(*kfunc)); 3311 + kfunc->btf = btf; 3312 + kfunc->id = func_id; 3313 + kfunc->name = func_name; 3314 + kfunc->proto = func_proto; 3315 + kfunc->flags = kfunc_flags; 3316 + 3317 + return 0; 3318 + } 3319 + 3320 + static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset) 3321 + { 3277 3322 struct bpf_kfunc_btf_tab *btf_tab; 3278 3323 struct btf_func_model func_model; 3279 3324 struct bpf_kfunc_desc_tab *tab; 3280 3325 struct bpf_prog_aux *prog_aux; 3326 + struct bpf_kfunc_meta kfunc; 3281 3327 struct bpf_kfunc_desc *desc; 3282 - const char *func_name; 3283 - struct btf *desc_btf; 3284 3328 unsigned long addr; 3285 3329 int err; 3286 3330 ··· 3382 3322 prog_aux->kfunc_btf_tab = btf_tab; 3383 3323 } 3384 3324 3385 - desc_btf = find_kfunc_desc_btf(env, offset); 3386 - if (IS_ERR(desc_btf)) { 3387 - verbose(env, "failed to find BTF for kernel function\n"); 3388 - return PTR_ERR(desc_btf); 3389 - } 3390 - 3391 3325 if (find_kfunc_desc(env->prog, func_id, offset)) 3392 3326 return 0; 3393 3327 ··· 3390 3336 return -E2BIG; 3391 3337 } 3392 3338 3393 - func = btf_type_by_id(desc_btf, func_id); 3394 - if (!func || !btf_type_is_func(func)) { 3395 - verbose(env, "kernel btf_id %u is not a function\n", 3396 - func_id); 3397 - return -EINVAL; 3398 - } 3399 - func_proto = btf_type_by_id(desc_btf, func->type); 3400 - if (!func_proto || !btf_type_is_func_proto(func_proto)) { 3401 - verbose(env, "kernel function btf_id %u does not have a valid func_proto\n", 3402 - func_id); 3403 - return -EINVAL; 3404 - } 3339 + err = fetch_kfunc_meta(env, func_id, offset, &kfunc); 3340 + if (err) 3341 + return err; 3405 3342 3406 - func_name = btf_name_by_offset(desc_btf, func->name_off); 3407 - addr = kallsyms_lookup_name(func_name); 3343 + addr = kallsyms_lookup_name(kfunc.name); 3408 3344 if (!addr) { 3409 - verbose(env, "cannot find address for kernel function %s\n", 3410 - func_name); 3345 + verbose(env, "cannot find address for kernel function %s\n", kfunc.name); 3411 3346 return -EINVAL; 3412 3347 } 3413 3348 ··· 3406 3363 return err; 3407 3364 } 3408 3365 3409 - err = btf_distill_func_proto(&env->log, desc_btf, 3410 - func_proto, func_name, 3411 - &func_model); 3366 + err = btf_distill_func_proto(&env->log, kfunc.btf, kfunc.proto, kfunc.name, &func_model); 3412 3367 if (err) 3413 3368 return err; 3414 3369 ··· 13737 13696 return 0; 13738 13697 } 13739 13698 13740 - static int fetch_kfunc_meta(struct bpf_verifier_env *env, 13741 - struct bpf_insn *insn, 13742 - struct bpf_kfunc_call_arg_meta *meta, 13743 - const char **kfunc_name) 13699 + static int fetch_kfunc_arg_meta(struct bpf_verifier_env *env, 13700 + s32 func_id, 13701 + s16 offset, 13702 + struct bpf_kfunc_call_arg_meta *meta) 13744 13703 { 13745 - const struct btf_type *func, *func_proto; 13746 - u32 func_id, *kfunc_flags; 13747 - const char *func_name; 13748 - struct btf *desc_btf; 13704 + struct bpf_kfunc_meta kfunc; 13705 + int err; 13749 13706 13750 - if (kfunc_name) 13751 - *kfunc_name = NULL; 13752 - 13753 - if (!insn->imm) 13754 - return -EINVAL; 13755 - 13756 - desc_btf = find_kfunc_desc_btf(env, insn->off); 13757 - if (IS_ERR(desc_btf)) 13758 - return PTR_ERR(desc_btf); 13759 - 13760 - func_id = insn->imm; 13761 - func = btf_type_by_id(desc_btf, func_id); 13762 - func_name = btf_name_by_offset(desc_btf, func->name_off); 13763 - if (kfunc_name) 13764 - *kfunc_name = func_name; 13765 - func_proto = btf_type_by_id(desc_btf, func->type); 13766 - 13767 - if (!btf_kfunc_is_allowed(desc_btf, func_id, env->prog)) 13768 - return -EACCES; 13769 - 13770 - kfunc_flags = btf_kfunc_flags(desc_btf, func_id, env->prog); 13707 + err = fetch_kfunc_meta(env, func_id, offset, &kfunc); 13708 + if (err) 13709 + return err; 13771 13710 13772 13711 memset(meta, 0, sizeof(*meta)); 13773 - meta->btf = desc_btf; 13774 - meta->func_id = func_id; 13775 - meta->kfunc_flags = *kfunc_flags; 13776 - meta->func_proto = func_proto; 13777 - meta->func_name = func_name; 13712 + meta->btf = kfunc.btf; 13713 + meta->func_id = kfunc.id; 13714 + meta->func_proto = kfunc.proto; 13715 + meta->func_name = kfunc.name; 13716 + 13717 + if (!kfunc.flags || !btf_kfunc_is_allowed(kfunc.btf, kfunc.id, env->prog)) 13718 + return -EACCES; 13719 + 13720 + meta->kfunc_flags = *kfunc.flags; 13778 13721 13779 13722 return 0; 13780 13723 } ··· 13963 13938 if (!insn->imm) 13964 13939 return 0; 13965 13940 13966 - err = fetch_kfunc_meta(env, insn, &meta, &func_name); 13967 - if (err == -EACCES && func_name) 13968 - verbose(env, "calling kernel function %s is not allowed\n", func_name); 13941 + err = fetch_kfunc_arg_meta(env, insn->imm, insn->off, &meta); 13942 + if (err == -EACCES && meta.func_name) 13943 + verbose(env, "calling kernel function %s is not allowed\n", meta.func_name); 13969 13944 if (err) 13970 13945 return err; 13971 13946 desc_btf = meta.btf; 13947 + func_name = meta.func_name; 13972 13948 insn_aux = &env->insn_aux_data[insn_idx]; 13973 13949 13974 13950 insn_aux->is_iter_next = is_iter_next_kfunc(&meta); ··· 17815 17789 if (bpf_pseudo_kfunc_call(call)) { 17816 17790 int err; 17817 17791 17818 - err = fetch_kfunc_meta(env, call, &meta, NULL); 17792 + err = fetch_kfunc_arg_meta(env, call->imm, call->off, &meta); 17819 17793 if (err < 0) 17820 17794 /* error would be reported later */ 17821 17795 return false; ··· 18323 18297 } else if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) { 18324 18298 struct bpf_kfunc_call_arg_meta meta; 18325 18299 18326 - ret = fetch_kfunc_meta(env, insn, &meta, NULL); 18300 + ret = fetch_kfunc_arg_meta(env, insn->imm, insn->off, &meta); 18327 18301 if (ret == 0 && is_iter_next_kfunc(&meta)) { 18328 18302 mark_prune_point(env, t); 18329 18303 /* Checking and saving state checkpoints at iter_next() call