@@ -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,11 @@ struct bpf_kfunc_btf_tab {
31263124 u32 nr_descs;
31273125};
31283126
3127+ static int kfunc_call_imm(struct bpf_verifier_env *env, unsigned long func_addr, u32 func_id,
3128+ s32 *imm);
3129+
3130+ static int specialize_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_desc *desc);
3131+
31293132static int kfunc_desc_cmp_by_id_off(const void *a, const void *b)
31303133{
31313134 const struct bpf_kfunc_desc *d0 = a;
@@ -3143,7 +3146,7 @@ static int kfunc_btf_cmp_by_off(const void *a, const void *b)
31433146 return d0->offset - d1->offset;
31443147}
31453148
3146- static const struct bpf_kfunc_desc *
3149+ static struct bpf_kfunc_desc *
31473150find_kfunc_desc(const struct bpf_prog *prog, u32 func_id, u16 offset)
31483151{
31493152 struct bpf_kfunc_desc desc = {
@@ -3266,12 +3269,13 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
32663269{
32673270 const struct btf_type *func, *func_proto;
32683271 struct bpf_kfunc_btf_tab *btf_tab;
3272+ struct btf_func_model func_model;
32693273 struct bpf_kfunc_desc_tab *tab;
32703274 struct bpf_prog_aux *prog_aux;
32713275 struct bpf_kfunc_desc *desc;
32723276 const char *func_name;
32733277 struct btf *desc_btf;
3274- unsigned long call_imm;
3278+ s32 call_imm;
32753279 unsigned long addr;
32763280 int err;
32773281
@@ -3355,38 +3359,32 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
33553359 func_name);
33563360 return -EINVAL;
33573361 }
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- }
33713362
33723363 if (bpf_dev_bound_kfunc_id(func_id)) {
33733364 err = bpf_dev_bound_kfunc_check(&env->log, prog_aux);
33743365 if (err)
33753366 return err;
33763367 }
33773368
3369+ err = btf_distill_func_proto(&env->log, desc_btf,
3370+ func_proto, func_name,
3371+ &func_model);
3372+ if (err)
3373+ return err;
3374+
3375+ err = kfunc_call_imm(env, addr, func_id, &call_imm);
3376+ if (err)
3377+ return err;
3378+
33783379 desc = &tab->descs[tab->nr_descs++];
33793380 desc->func_id = func_id;
33803381 desc->imm = call_imm;
33813382 desc->offset = offset;
33823383 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;
3384+ desc->func_model = func_model;
3385+ sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
3386+ kfunc_desc_cmp_by_id_off, NULL);
3387+ return 0;
33903388}
33913389
33923390static int kfunc_desc_cmp_by_imm_off(const void *a, const void *b)
@@ -21861,47 +21859,73 @@ static int fixup_call_args(struct bpf_verifier_env *env)
2186121859 return err;
2186221860}
2186321861
21862+ static int kfunc_call_imm(struct bpf_verifier_env *env, unsigned long func_addr, u32 func_id,
21863+ s32 *imm)
21864+ {
21865+ unsigned long call_imm;
21866+
21867+ if (bpf_jit_supports_far_kfunc_call()) {
21868+ *imm = func_id;
21869+ return 0;
21870+ }
21871+
21872+ call_imm = BPF_CALL_IMM(func_addr);
21873+ /* Check whether the relative offset overflows desc->imm */
21874+ if ((unsigned long)(s32)call_imm != call_imm) {
21875+ verbose(env, "address of kernel func_id %u is out of range\n", func_id);
21876+ return -EINVAL;
21877+ }
21878+ *imm = call_imm;
21879+ return 0;
21880+ }
21881+
2186421882/* replace a generic kfunc with a specialized version if necessary */
21865- static void specialize_kfunc(struct bpf_verifier_env *env,
21866- u32 func_id, u16 offset, unsigned long *addr)
21883+ static int specialize_kfunc(struct bpf_verifier_env *env, struct bpf_kfunc_desc *desc)
2186721884{
2186821885 struct bpf_prog *prog = env->prog;
2186921886 bool seen_direct_write;
2187021887 void *xdp_kfunc;
2187121888 bool is_rdonly;
21889+ u32 func_id = desc->func_id;
21890+ u16 offset = desc->offset;
21891+ unsigned long addr = 0;
21892+ int err;
21893+
21894+ if (offset) /* return if module BTF is used */
21895+ return 0;
2187221896
2187321897 if (bpf_dev_bound_kfunc_id(func_id)) {
2187421898 xdp_kfunc = bpf_dev_bound_resolve_kfunc(prog, func_id);
21875- if (xdp_kfunc) {
21876- *addr = (unsigned long)xdp_kfunc;
21877- return;
21878- }
21899+ if (xdp_kfunc)
21900+ addr = (unsigned long)xdp_kfunc;
2187921901 /* fallback to default kfunc when not supported by netdev */
21880- }
21881-
21882- if (offset)
21883- return;
21884-
21885- if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
21902+ } else if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
2188621903 seen_direct_write = env->seen_direct_write;
2188721904 is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE);
2188821905
2188921906 if (is_rdonly)
21890- * addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
21907+ addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
2189121908
2189221909 /* restore env->seen_direct_write to its original value, since
2189321910 * may_access_direct_pkt_data mutates it
2189421911 */
2189521912 env->seen_direct_write = seen_direct_write;
21913+ } else if (func_id == special_kfunc_list[KF_bpf_set_dentry_xattr]) {
21914+ if (bpf_lsm_has_d_inode_locked(prog))
21915+ addr = (unsigned long)bpf_set_dentry_xattr_locked;
21916+ } else if (func_id == special_kfunc_list[KF_bpf_remove_dentry_xattr]) {
21917+ if (bpf_lsm_has_d_inode_locked(prog))
21918+ addr = (unsigned long)bpf_remove_dentry_xattr_locked;
2189621919 }
2189721920
21898- if (func_id == special_kfunc_list[KF_bpf_set_dentry_xattr] &&
21899- bpf_lsm_has_d_inode_locked(prog))
21900- *addr = (unsigned long)bpf_set_dentry_xattr_locked;
21921+ if (!addr) /* Nothing to patch with */
21922+ return 0;
2190121923
21902- if (func_id == special_kfunc_list[KF_bpf_remove_dentry_xattr] &&
21903- bpf_lsm_has_d_inode_locked(prog))
21904- *addr = (unsigned long)bpf_remove_dentry_xattr_locked;
21924+ err = kfunc_call_imm(env, addr, func_id, &desc->imm);
21925+ if (err)
21926+ return err;
21927+ desc->addr = addr;
21928+ return 0;
2190521929}
2190621930
2190721931static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
@@ -21924,7 +21948,8 @@ static void __fixup_collection_insert_kfunc(struct bpf_insn_aux_data *insn_aux,
2192421948static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
2192521949 struct bpf_insn *insn_buf, int insn_idx, int *cnt)
2192621950{
21927- const struct bpf_kfunc_desc *desc;
21951+ struct bpf_kfunc_desc *desc;
21952+ int err;
2192821953
2192921954 if (!insn->imm) {
2193021955 verbose(env, "invalid kernel function call not eliminated in verifier pass\n");
@@ -21944,6 +21969,10 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
2194421969 return -EFAULT;
2194521970 }
2194621971
21972+ err = specialize_kfunc(env, desc);
21973+ if (err)
21974+ return err;
21975+
2194721976 if (!bpf_jit_supports_far_kfunc_call())
2194821977 insn->imm = BPF_CALL_IMM(desc->addr);
2194921978 if (insn->off)
0 commit comments