@@ -195,6 +195,8 @@ static void invalidate_non_owning_refs(struct bpf_verifier_env *env);
195
195
static bool in_rbtree_lock_required_cb(struct bpf_verifier_env *env);
196
196
static int ref_set_non_owning(struct bpf_verifier_env *env,
197
197
struct bpf_reg_state *reg);
198
+ static void specialize_kfunc(struct bpf_verifier_env *env,
199
+ u32 func_id, u16 offset, unsigned long *addr);
198
200
199
201
static bool bpf_map_ptr_poisoned(const struct bpf_insn_aux_data *aux)
200
202
{
@@ -2374,6 +2376,7 @@ struct bpf_kfunc_desc {
2374
2376
u32 func_id;
2375
2377
s32 imm;
2376
2378
u16 offset;
2379
+ unsigned long addr;
2377
2380
};
2378
2381
2379
2382
struct bpf_kfunc_btf {
@@ -2383,6 +2386,11 @@ struct bpf_kfunc_btf {
2383
2386
};
2384
2387
2385
2388
struct 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
+ */
2386
2394
struct bpf_kfunc_desc descs[MAX_KFUNC_DESCS];
2387
2395
u32 nr_descs;
2388
2396
};
@@ -2423,6 +2431,19 @@ find_kfunc_desc(const struct bpf_prog *prog, u32 func_id, u16 offset)
2423
2431
sizeof(tab->descs[0]), kfunc_desc_cmp_by_id_off);
2424
2432
}
2425
2433
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
+
2426
2447
static struct btf *__find_kfunc_desc_btf(struct bpf_verifier_env *env,
2427
2448
s16 offset)
2428
2449
{
@@ -2602,13 +2623,18 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
2602
2623
func_name);
2603
2624
return -EINVAL;
2604
2625
}
2626
+ specialize_kfunc(env, func_id, offset, &addr);
2605
2627
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
+ }
2612
2638
}
2613
2639
2614
2640
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)
2621
2647
desc->func_id = func_id;
2622
2648
desc->imm = call_imm;
2623
2649
desc->offset = offset;
2650
+ desc->addr = addr;
2624
2651
err = btf_distill_func_proto(&env->log, desc_btf,
2625
2652
func_proto, func_name,
2626
2653
&desc->func_model);
@@ -2630,19 +2657,19 @@ static int add_kfunc_call(struct bpf_verifier_env *env, u32 func_id, s16 offset)
2630
2657
return err;
2631
2658
}
2632
2659
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)
2634
2661
{
2635
2662
const struct bpf_kfunc_desc *d0 = a;
2636
2663
const struct bpf_kfunc_desc *d1 = b;
2637
2664
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;
2642
2669
return 0;
2643
2670
}
2644
2671
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)
2646
2673
{
2647
2674
struct bpf_kfunc_desc_tab *tab;
2648
2675
@@ -2651,7 +2678,7 @@ static void sort_kfunc_descs_by_imm(struct bpf_prog *prog)
2651
2678
return;
2652
2679
2653
2680
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);
2655
2682
}
2656
2683
2657
2684
bool bpf_prog_has_kfunc_call(const struct bpf_prog *prog)
@@ -2665,13 +2692,14 @@ bpf_jit_find_kfunc_model(const struct bpf_prog *prog,
2665
2692
{
2666
2693
const struct bpf_kfunc_desc desc = {
2667
2694
.imm = insn->imm,
2695
+ .offset = insn->off,
2668
2696
};
2669
2697
const struct bpf_kfunc_desc *res;
2670
2698
struct bpf_kfunc_desc_tab *tab;
2671
2699
2672
2700
tab = prog->aux->kfunc_tab;
2673
2701
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 );
2675
2703
2676
2704
return res ? &res->func_model : NULL;
2677
2705
}
@@ -17293,11 +17321,45 @@ static int fixup_call_args(struct bpf_verifier_env *env)
17293
17321
return err;
17294
17322
}
17295
17323
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
+
17296
17359
static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
17297
17360
struct bpf_insn *insn_buf, int insn_idx, int *cnt)
17298
17361
{
17299
17362
const struct bpf_kfunc_desc *desc;
17300
- void *xdp_kfunc;
17301
17363
17302
17364
if (!insn->imm) {
17303
17365
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,
17306
17368
17307
17369
*cnt = 0;
17308
17370
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()).
17321
17374
*/
17322
17375
desc = find_kfunc_desc(env->prog, insn->imm, insn->off);
17323
17376
if (!desc) {
@@ -17326,7 +17379,8 @@ static int fixup_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
17326
17379
return -EFAULT;
17327
17380
}
17328
17381
17329
- insn->imm = desc->imm;
17382
+ if (!bpf_jit_supports_far_kfunc_call())
17383
+ insn->imm = BPF_CALL_IMM(desc->addr);
17330
17384
if (insn->off)
17331
17385
return 0;
17332
17386
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,
17351
17405
desc->func_id == special_kfunc_list[KF_bpf_rdonly_cast]) {
17352
17406
insn_buf[0] = BPF_MOV64_REG(BPF_REG_0, BPF_REG_1);
17353
17407
*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;
17365
17408
}
17366
17409
return 0;
17367
17410
}
@@ -17891,7 +17934,7 @@ static int do_misc_fixups(struct bpf_verifier_env *env)
17891
17934
}
17892
17935
}
17893
17936
17894
- sort_kfunc_descs_by_imm (env->prog);
17937
+ sort_kfunc_descs_by_imm_off (env->prog);
17895
17938
17896
17939
return 0;
17897
17940
}
0 commit comments