@@ -209,8 +209,6 @@ static void invalidate_non_owning_refs(struct bpf_verifier_env *env);
209209static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env);
210210static int ref_set_non_owning(struct bpf_verifier_env *env,
211211 struct bpf_reg_state *reg);
212- static void specialize_kfunc(struct bpf_verifier_env *env,
213- u32 func_id, u16 offset, unsigned long *addr);
214212static bool is_trusted_reg(const struct bpf_reg_state *reg);
215213
216214static bool bpf_map_ptr_poisoned(const struct bpf_insn_aux_data *aux)
@@ -3126,6 +3124,8 @@ struct bpf_kfunc_btf_tab {
31263124 u32 nr_descs;
31273125};
31283126
3127+ static int specialize_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_desc *desc);
3128+
31293129static int kfunc_desc_cmp_by_id_off(const void *a, const void *b)
31303130{
31313131 const struct bpf_kfunc_desc *d0 = a;
@@ -3143,7 +3143,7 @@ static int kfunc_btf_cmp_by_off(const void *a, const void *b)
31433143 return d0->offset - d1->offset;
31443144}
31453145
3146- static const struct bpf_kfunc_desc *
3146+ static struct bpf_kfunc_desc *
31473147find_kfunc_desc(const struct bpf_prog *prog, u32 func_id, u16 offset)
31483148{
31493149 struct bpf_kfunc_desc desc = {
@@ -3266,12 +3266,12 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
32663266{
32673267 const struct btf_type *func, *func_proto;
32683268 struct bpf_kfunc_btf_tab *btf_tab;
3269+ struct btf_func_model func_model;
32693270 struct bpf_kfunc_desc_tab *tab;
32703271 struct bpf_prog_aux *prog_aux;
32713272 struct bpf_kfunc_desc *desc;
32723273 const char *func_name;
32733274 struct btf *desc_btf;
3274- unsigned long call_imm;
32753275 unsigned long addr;
32763276 int err;
32773277
@@ -3355,38 +3355,27 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
33553355 func_name);
33563356 return -EINVAL;
33573357 }
3358- specialize_kfunc(env, func_id, offset, &addr);
3359-
3360- if (bpf_jit_supports_far_kfunc_call()) {
3361- call_imm = func_id;
3362- } else {
3363- call_imm = BPF_CALL_IMM(addr);
3364- /* Check whether the relative offset overflows desc->imm */
3365- if ((unsigned long)(s32)call_imm != call_imm) {
3366- verbose(env, "address of kernel function %s is out of range\n",
3367- func_name);
3368- return -EINVAL;
3369- }
3370- }
33713358
33723359 if (bpf_dev_bound_kfunc_id(func_id)) {
33733360 err = bpf_dev_bound_kfunc_check(&env->log, prog_aux);
33743361 if (err)
33753362 return err;
33763363 }
33773364
3365+ err = btf_distill_func_proto(&env->log, desc_btf,
3366+ func_proto, func_name,
3367+ &func_model);
3368+ if (err)
3369+ return err;
3370+
33783371 desc = &tab->descs[tab->nr_descs++];
33793372 desc->func_id = func_id;
3380- desc->imm = call_imm;
33813373 desc->offset = offset;
33823374 desc->addr = addr;
3383- err = btf_distill_func_proto(&env->log, desc_btf,
3384- func_proto, func_name,
3385- &desc->func_model);
3386- if (!err)
3387- sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
3388- kfunc_desc_cmp_by_id_off, NULL);
3389- return err;
3375+ desc->func_model = func_model;
3376+ sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
3377+ kfunc_desc_cmp_by_id_off, NULL);
3378+ return 0;
33903379}
33913380
33923381static int kfunc_desc_cmp_by_imm_off(const void *a, const void *b)
@@ -21880,46 +21869,57 @@ static int fixup_call_args(struct bpf_verifier_env *env)
2188021869}
2188121870
2188221871/* replace a generic kfunc with a specialized version if necessary */
21883- static void specialize_kfunc(struct bpf_verifier_env *env,
21884- u32 func_id, u16 offset, unsigned long *addr)
21872+ static int specialize_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_desc *desc)
2188521873{
2188621874 struct bpf_prog *prog = env->prog;
2188721875 bool seen_direct_write;
2188821876 void *xdp_kfunc;
2188921877 bool is_rdonly;
21878+ u32 func_id = desc->func_id;
21879+ u16 offset = desc->offset;
21880+ unsigned long addr = desc->addr, call_imm;
21881+
21882+ if (offset) /* return if module BTF is used */
21883+ goto set_imm;
2189021884
2189121885 if (bpf_dev_bound_kfunc_id(func_id)) {
2189221886 xdp_kfunc = bpf_dev_bound_resolve_kfunc(prog, func_id);
21893- if (xdp_kfunc) {
21894- *addr = (unsigned long)xdp_kfunc;
21895- return;
21896- }
21887+ if (xdp_kfunc)
21888+ addr = (unsigned long)xdp_kfunc;
2189721889 /* fallback to default kfunc when not supported by netdev */
21898- }
21899-
21900- if (offset)
21901- return;
21902-
21903- if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
21890+ } else if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
2190421891 seen_direct_write = env->seen_direct_write;
2190521892 is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE);
2190621893
2190721894 if (is_rdonly)
21908- * addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
21895+ addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
2190921896
2191021897 /* restore env->seen_direct_write to its original value, since
2191121898 * may_access_direct_pkt_data mutates it
2191221899 */
2191321900 env->seen_direct_write = seen_direct_write;
21901+ } else if (func_id == special_kfunc_list[KF_bpf_set_dentry_xattr]) {
21902+ if (bpf_lsm_has_d_inode_locked(prog))
21903+ addr = (unsigned long)bpf_set_dentry_xattr_locked;
21904+ } else if (func_id == special_kfunc_list[KF_bpf_remove_dentry_xattr]) {
21905+ if (bpf_lsm_has_d_inode_locked(prog))
21906+ addr = (unsigned long)bpf_remove_dentry_xattr_locked;
2191421907 }
2191521908
21916- if (func_id == special_kfunc_list[KF_bpf_set_dentry_xattr] &&
21917- bpf_lsm_has_d_inode_locked(prog))
21918- *addr = (unsigned long)bpf_set_dentry_xattr_locked;
21919-
21920- if (func_id == special_kfunc_list[KF_bpf_remove_dentry_xattr] &&
21921- bpf_lsm_has_d_inode_locked(prog))
21922- *addr = (unsigned long)bpf_remove_dentry_xattr_locked;
21909+ set_imm:
21910+ if (bpf_jit_supports_far_kfunc_call()) {
21911+ call_imm = func_id;
21912+ } else {
21913+ call_imm = BPF_CALL_IMM(addr);
21914+ /* Check whether the relative offset overflows desc->imm */
21915+ if ((unsigned long)(s32)call_imm != call_imm) {
21916+ verbose(env, "address of kernel func_id %u is out of range\n", func_id);
21917+ return -EINVAL;
21918+ }
21919+ }
21920+ desc->imm = call_imm;
21921+ desc->addr = addr;
21922+ return 0;
2192321923}
2192421924
2192521925static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
@@ -21942,7 +21942,8 @@ static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
2194221942static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
2194321943 struct bpf_insn *insn_buf, int insn_idx, int *cnt)
2194421944{
21945- const struct bpf_kfunc_desc *desc;
21945+ struct bpf_kfunc_desc *desc;
21946+ int err;
2194621947
2194721948 if (!insn->imm) {
2194821949 verbose(env, "invalid kernel function call not eliminated in verifier pass\n");
@@ -21962,6 +21963,10 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
2196221963 return -EFAULT;
2196321964 }
2196421965
21966+ err = specialize_kfunc(env, desc);
21967+ if (err)
21968+ return err;
21969+
2196521970 if (!bpf_jit_supports_far_kfunc_call())
2196621971 insn->imm = BPF_CALL_IMM(desc->addr);
2196721972 if (insn->off)
0 commit comments