@@ -195,6 +195,8 @@ static void invalidate_non_owning_refs(struct bpf_verifier_env *env);
195195static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env);
196196static int ref_set_non_owning(struct bpf_verifier_env *env,
197197 struct bpf_reg_state *reg);
198+ static void specialize_kfunc(struct bpf_verifier_env *env,
199+ u32 func_id, u16 offset, unsigned long *addr);
198200
199201static bool bpf_map_ptr_poisoned(const struct bpf_insn_aux_data *aux)
200202{
@@ -2374,6 +2376,7 @@ struct bpf_kfunc_desc {
23742376 u32 func_id;
23752377 s32 imm;
23762378 u16 offset;
2379+ unsigned long addr;
23772380};
23782381
23792382struct bpf_kfunc_btf {
@@ -2383,6 +2386,11 @@ struct bpf_kfunc_btf {
23832386};
23842387
23852388struct bpf_kfunc_desc_tab {
2389+ /* Sorted by func_id (BTF ID) and offset (fd_array offset) during
2390+ * verification. JITs do lookups by bpf_insn, where func_id may not be
2391+ * available, therefore at the end of verification do_misc_fixups()
2392+ * sorts this by imm and offset.
2393+ */
23862394 struct bpf_kfunc_desc descs[MAX_KFUNC_DESCS];
23872395 u32 nr_descs;
23882396};
@@ -2423,6 +2431,19 @@ find_kfunc_desc(const struct bpf_prog *prog, u32 func_id, u16 offset)
24232431 sizeof(tab->descs[0]), kfunc_desc_cmp_by_id_off);
24242432}
24252433
2434+ int bpf_get_kfunc_addr(const struct bpf_prog *prog, u32 func_id,
2435+ u16 btf_fd_idx, u8 **func_addr)
2436+ {
2437+ const struct bpf_kfunc_desc *desc;
2438+
2439+ desc = find_kfunc_desc(prog, func_id, btf_fd_idx);
2440+ if (!desc)
2441+ return -EFAULT;
2442+
2443+ *func_addr = (u8 *)desc->addr;
2444+ return 0;
2445+ }
2446+
24262447static struct btf *__find_kfunc_desc_btf(struct bpf_verifier_env *env,
24272448 s16 offset)
24282449{
@@ -2602,13 +2623,18 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
26022623 func_name);
26032624 return -EINVAL;
26042625 }
2626+ specialize_kfunc(env, func_id, offset, &addr);
26052627
2606- call_imm = BPF_CALL_IMM(addr);
2607- /* Check whether or not the relative offset overflows desc->imm */
2608- if ((unsigned long)(s32)call_imm != call_imm) {
2609- verbose(env, "address of kernel function %s is out of range\n",
2610- func_name);
2611- return -EINVAL;
2628+ if (bpf_jit_supports_far_kfunc_call()) {
2629+ call_imm = func_id;
2630+ } else {
2631+ call_imm = BPF_CALL_IMM(addr);
2632+ /* Check whether the relative offset overflows desc->imm */
2633+ if ((unsigned long)(s32)call_imm != call_imm) {
2634+ verbose(env, "address of kernel function %s is out of range\n",
2635+ func_name);
2636+ return -EINVAL;
2637+ }
26122638 }
26132639
26142640 if (bpf_dev_bound_kfunc_id(func_id)) {
@@ -2621,6 +2647,7 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
26212647 desc->func_id = func_id;
26222648 desc->imm = call_imm;
26232649 desc->offset = offset;
2650+ desc->addr = addr;
26242651 err = btf_distill_func_proto(&env->log, desc_btf,
26252652 func_proto, func_name,
26262653 &desc->func_model);
@@ -2630,19 +2657,19 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
26302657 return err;
26312658}
26322659
2633- static int kfunc_desc_cmp_by_imm (const void *a, const void *b)
2660+ static int kfunc_desc_cmp_by_imm_off (const void *a, const void *b)
26342661{
26352662 const struct bpf_kfunc_desc *d0 = a;
26362663 const struct bpf_kfunc_desc *d1 = b;
26372664
2638- if (d0->imm > d1->imm)
2639- return 1;
2640- else if (d0->imm < d1->imm )
2641- return - 1;
2665+ if (d0->imm != d1->imm)
2666+ return d0->imm < d1->imm ? -1 : 1;
2667+ if (d0->offset != d1->offset )
2668+ return d0->offset < d1->offset ? -1 : 1;
26422669 return 0;
26432670}
26442671
2645- static void sort_kfunc_descs_by_imm (struct bpf_prog *prog)
2672+ static void sort_kfunc_descs_by_imm_off (struct bpf_prog *prog)
26462673{
26472674 struct bpf_kfunc_desc_tab *tab;
26482675
@@ -2651,7 +2678,7 @@ static void sort_kfunc_descs_by_imm(struct bpf_prog *prog)
26512678 return;
26522679
26532680 sort(tab->descs, tab->nr_descs, sizeof(tab->descs[0]),
2654- kfunc_desc_cmp_by_imm , NULL);
2681+ kfunc_desc_cmp_by_imm_off , NULL);
26552682}
26562683
26572684bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
@@ -2665,13 +2692,14 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
26652692{
26662693 const struct bpf_kfunc_desc desc = {
26672694 .imm = insn->imm,
2695+ .offset = insn->off,
26682696 };
26692697 const struct bpf_kfunc_desc *res;
26702698 struct bpf_kfunc_desc_tab *tab;
26712699
26722700 tab = prog->aux->kfunc_tab;
26732701 res = bsearch(&desc, tab->descs, tab->nr_descs,
2674- sizeof(tab->descs[0]), kfunc_desc_cmp_by_imm );
2702+ sizeof(tab->descs[0]), kfunc_desc_cmp_by_imm_off );
26752703
26762704 return res ? &res->func_model : NULL;
26772705}
@@ -17293,11 +17321,45 @@ static int fixup_call_args(struct bpf_verifier_env *env)
1729317321 return err;
1729417322}
1729517323
17324+ /* replace a generic kfunc with a specialized version if necessary */
17325+ static void specialize_kfunc(struct bpf_verifier_env *env,
17326+ u32 func_id, u16 offset, unsigned long *addr)
17327+ {
17328+ struct bpf_prog *prog = env->prog;
17329+ bool seen_direct_write;
17330+ void *xdp_kfunc;
17331+ bool is_rdonly;
17332+
17333+ if (bpf_dev_bound_kfunc_id(func_id)) {
17334+ xdp_kfunc = bpf_dev_bound_resolve_kfunc(prog, func_id);
17335+ if (xdp_kfunc) {
17336+ *addr = (unsigned long)xdp_kfunc;
17337+ return;
17338+ }
17339+ /* fallback to default kfunc when not supported by netdev */
17340+ }
17341+
17342+ if (offset)
17343+ return;
17344+
17345+ if (func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
17346+ seen_direct_write = env->seen_direct_write;
17347+ is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE);
17348+
17349+ if (is_rdonly)
17350+ *addr = (unsigned long)bpf_dynptr_from_skb_rdonly;
17351+
17352+ /* restore env->seen_direct_write to its original value, since
17353+ * may_access_direct_pkt_data mutates it
17354+ */
17355+ env->seen_direct_write = seen_direct_write;
17356+ }
17357+ }
17358+
1729617359static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1729717360 struct bpf_insn *insn_buf, int insn_idx, int *cnt)
1729817361{
1729917362 const struct bpf_kfunc_desc *desc;
17300- void *xdp_kfunc;
1730117363
1730217364 if (!insn->imm) {
1730317365 verbose(env, "invalid kernel function call not eliminated in verifier pass\n");
@@ -17306,18 +17368,9 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1730617368
1730717369 *cnt = 0;
1730817370
17309- if (bpf_dev_bound_kfunc_id(insn->imm)) {
17310- xdp_kfunc = bpf_dev_bound_resolve_kfunc(env->prog, insn->imm);
17311- if (xdp_kfunc) {
17312- insn->imm = BPF_CALL_IMM(xdp_kfunc);
17313- return 0;
17314- }
17315-
17316- /* fallback to default kfunc when not supported by netdev */
17317- }
17318-
17319- /* insn->imm has the btf func_id. Replace it with
17320- * an address (relative to __bpf_call_base).
17371+ /* insn->imm has the btf func_id. Replace it with an offset relative to
17372+ * __bpf_call_base, unless the JIT needs to call functions that are
17373+ * further than 32 bits away (bpf_jit_supports_far_kfunc_call()).
1732117374 */
1732217375 desc = find_kfunc_desc(env->prog, insn->imm, insn->off);
1732317376 if (!desc) {
@@ -17326,7 +17379,8 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1732617379 return -EFAULT;
1732717380 }
1732817381
17329- insn->imm = desc->imm;
17382+ if (!bpf_jit_supports_far_kfunc_call())
17383+ insn->imm = BPF_CALL_IMM(desc->addr);
1733017384 if (insn->off)
1733117385 return 0;
1733217386 if (desc->func_id == special_kfunc_list[KF_bpf_obj_new_impl]) {
@@ -17351,17 +17405,6 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
1735117405 desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
1735217406 insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
1735317407 *cnt = 1;
17354- } else if (desc->func_id == special_kfunc_list[KF_bpf_dynptr_from_skb]) {
17355- bool seen_direct_write = env->seen_direct_write;
17356- bool is_rdonly = !may_access_direct_pkt_data(env, NULL, BPF_WRITE);
17357-
17358- if (is_rdonly)
17359- insn->imm = BPF_CALL_IMM(bpf_dynptr_from_skb_rdonly);
17360-
17361- /* restore env->seen_direct_write to its original value, since
17362- * may_access_direct_pkt_data mutates it
17363- */
17364- env->seen_direct_write = seen_direct_write;
1736517408 }
1736617409 return 0;
1736717410}
@@ -17891,7 +17934,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
1789117934 }
1789217935 }
1789317936
17894- sort_kfunc_descs_by_imm (env->prog);
17937+ sort_kfunc_descs_by_imm_off (env->prog);
1789517938
1789617939 return 0;
1789717940}
0 commit comments