Skip to content

Commit 96d1b7c

Browse files
liu-song-6Alexei Starovoitov
authored andcommitted
bpf: Add arch_bpf_trampoline_size()
This helper will be used to calculate the size of the trampoline before allocating the memory. arch_prepare_bpf_trampoline() for arm64 and riscv64 can use arch_bpf_trampoline_size() to check the trampoline fits in the image. OTOH, arch_prepare_bpf_trampoline() for s390 has to call the JIT process twice, so it cannot use arch_bpf_trampoline_size(). Signed-off-by: Song Liu <[email protected]> Acked-by: Ilya Leoshkevich <[email protected]> Tested-by: Ilya Leoshkevich <[email protected]> # on s390x Acked-by: Jiri Olsa <[email protected]> Acked-by: Björn Töpel <[email protected]> Tested-by: Björn Töpel <[email protected]> # on riscv Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Alexei Starovoitov <[email protected]>
1 parent 38b8b58 commit 96d1b7c

File tree

6 files changed

+136
-46
lines changed

6 files changed

+136
-46
lines changed

arch/arm64/net/bpf_jit_comp.c

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2026,18 +2026,10 @@ static int prepare_trampoline(struct jit_ctx *ctx, struct bpf_tramp_image *im,
20262026
return ctx->idx;
20272027
}
20282028

2029-
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
2030-
void *image_end, const struct btf_func_model *m,
2031-
u32 flags, struct bpf_tramp_links *tlinks,
2032-
void *func_addr)
2029+
static int btf_func_model_nregs(const struct btf_func_model *m)
20332030
{
2034-
int i, ret;
20352031
int nregs = m->nr_args;
2036-
int max_insns = ((long)image_end - (long)image) / AARCH64_INSN_SIZE;
2037-
struct jit_ctx ctx = {
2038-
.image = NULL,
2039-
.idx = 0,
2040-
};
2032+
int i;
20412033

20422034
/* extra registers needed for struct argument */
20432035
for (i = 0; i < MAX_BPF_FUNC_ARGS; i++) {
@@ -2046,19 +2038,53 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
20462038
nregs += (m->arg_size[i] + 7) / 8 - 1;
20472039
}
20482040

2041+
return nregs;
2042+
}
2043+
2044+
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
2045+
struct bpf_tramp_links *tlinks, void *func_addr)
2046+
{
2047+
struct jit_ctx ctx = {
2048+
.image = NULL,
2049+
.idx = 0,
2050+
};
2051+
struct bpf_tramp_image im;
2052+
int nregs, ret;
2053+
2054+
nregs = btf_func_model_nregs(m);
20492055
/* the first 8 registers are used for arguments */
20502056
if (nregs > 8)
20512057
return -ENOTSUPP;
20522058

2053-
ret = prepare_trampoline(&ctx, im, tlinks, func_addr, nregs, flags);
2059+
ret = prepare_trampoline(&ctx, &im, tlinks, func_addr, nregs, flags);
20542060
if (ret < 0)
20552061
return ret;
20562062

2057-
if (ret > max_insns)
2058-
return -EFBIG;
2063+
return ret < 0 ? ret : ret * AARCH64_INSN_SIZE;
2064+
}
20592065

2060-
ctx.image = image;
2061-
ctx.idx = 0;
2066+
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
2067+
void *image_end, const struct btf_func_model *m,
2068+
u32 flags, struct bpf_tramp_links *tlinks,
2069+
void *func_addr)
2070+
{
2071+
int ret, nregs;
2072+
struct jit_ctx ctx = {
2073+
.image = image,
2074+
.idx = 0,
2075+
};
2076+
2077+
nregs = btf_func_model_nregs(m);
2078+
/* the first 8 registers are used for arguments */
2079+
if (nregs > 8)
2080+
return -ENOTSUPP;
2081+
2082+
ret = arch_bpf_trampoline_size(m, flags, tlinks, func_addr);
2083+
if (ret < 0)
2084+
return ret;
2085+
2086+
if (ret > ((long)image_end - (long)image))
2087+
return -EFBIG;
20622088

20632089
jit_fill_hole(image, (unsigned int)(image_end - image));
20642090
ret = prepare_trampoline(&ctx, im, tlinks, func_addr, nregs, flags);

arch/riscv/net/bpf_jit_comp64.c

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,6 +1029,21 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
10291029
return ret;
10301030
}
10311031

1032+
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
1033+
struct bpf_tramp_links *tlinks, void *func_addr)
1034+
{
1035+
struct bpf_tramp_image im;
1036+
struct rv_jit_context ctx;
1037+
int ret;
1038+
1039+
ctx.ninsns = 0;
1040+
ctx.insns = NULL;
1041+
ctx.ro_insns = NULL;
1042+
ret = __arch_prepare_bpf_trampoline(&im, m, tlinks, func_addr, flags, &ctx);
1043+
1044+
return ret < 0 ? ret : ninsns_rvoff(ctx.ninsns);
1045+
}
1046+
10321047
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
10331048
void *image_end, const struct btf_func_model *m,
10341049
u32 flags, struct bpf_tramp_links *tlinks,
@@ -1037,14 +1052,11 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
10371052
int ret;
10381053
struct rv_jit_context ctx;
10391054

1040-
ctx.ninsns = 0;
1041-
ctx.insns = NULL;
1042-
ctx.ro_insns = NULL;
1043-
ret = __arch_prepare_bpf_trampoline(im, m, tlinks, func_addr, flags, &ctx);
1055+
ret = arch_bpf_trampoline_size(im, m, flags, tlinks, func_addr);
10441056
if (ret < 0)
10451057
return ret;
10461058

1047-
if (ninsns_rvoff(ret) > (long)image_end - (long)image)
1059+
if (ret > (long)image_end - (long)image)
10481060
return -EFBIG;
10491061

10501062
ctx.ninsns = 0;

arch/s390/net/bpf_jit_comp.c

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -2637,37 +2637,49 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
26372637
return 0;
26382638
}
26392639

2640+
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
2641+
struct bpf_tramp_links *tlinks, void *orig_call)
2642+
{
2643+
struct bpf_tramp_image im;
2644+
struct bpf_tramp_jit tjit;
2645+
int ret;
2646+
2647+
memset(&tjit, 0, sizeof(tjit));
2648+
2649+
ret = __arch_prepare_bpf_trampoline(&im, &tjit, m, flags,
2650+
tlinks, orig_call);
2651+
2652+
return ret < 0 ? ret : tjit.common.prg;
2653+
}
2654+
26402655
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
26412656
void *image_end, const struct btf_func_model *m,
26422657
u32 flags, struct bpf_tramp_links *tlinks,
26432658
void *func_addr)
26442659
{
26452660
struct bpf_tramp_jit tjit;
26462661
int ret;
2647-
int i;
26482662

2649-
for (i = 0; i < 2; i++) {
2650-
if (i == 0) {
2651-
/* Compute offsets, check whether the code fits. */
2652-
memset(&tjit, 0, sizeof(tjit));
2653-
} else {
2654-
/* Generate the code. */
2655-
tjit.common.prg = 0;
2656-
tjit.common.prg_buf = image;
2657-
}
2658-
ret = __arch_prepare_bpf_trampoline(im, &tjit, m, flags,
2659-
tlinks, func_addr);
2660-
if (ret < 0)
2661-
return ret;
2662-
if (tjit.common.prg > (char *)image_end - (char *)image)
2663-
/*
2664-
* Use the same error code as for exceeding
2665-
* BPF_MAX_TRAMP_LINKS.
2666-
*/
2667-
return -E2BIG;
2668-
}
2663+
/* Compute offsets, check whether the code fits. */
2664+
memset(&tjit, 0, sizeof(tjit));
2665+
ret = __arch_prepare_bpf_trampoline(im, &tjit, m, flags,
2666+
tlinks, func_addr);
2667+
2668+
if (ret < 0)
2669+
return ret;
2670+
if (tjit.common.prg > (char *)image_end - (char *)image)
2671+
/*
2672+
* Use the same error code as for exceeding
2673+
* BPF_MAX_TRAMP_LINKS.
2674+
*/
2675+
return -E2BIG;
2676+
2677+
tjit.common.prg = 0;
2678+
tjit.common.prg_buf = image;
2679+
ret = __arch_prepare_bpf_trampoline(im, &tjit, m, flags,
2680+
tlinks, func_addr);
26692681

2670-
return tjit.common.prg;
2682+
return ret < 0 ? ret : tjit.common.prg;
26712683
}
26722684

26732685
bool bpf_jit_supports_subprog_tailcalls(void)

arch/x86/net/bpf_jit_comp.c

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2422,10 +2422,10 @@ static int invoke_bpf_mod_ret(const struct btf_func_model *m, u8 **pprog,
24222422
* add rsp, 8 // skip eth_type_trans's frame
24232423
* ret // return to its caller
24242424
*/
2425-
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
2426-
const struct btf_func_model *m, u32 flags,
2427-
struct bpf_tramp_links *tlinks,
2428-
void *func_addr)
2425+
static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
2426+
const struct btf_func_model *m, u32 flags,
2427+
struct bpf_tramp_links *tlinks,
2428+
void *func_addr)
24292429
{
24302430
int i, ret, nr_regs = m->nr_args, stack_size = 0;
24312431
int regs_off, nregs_off, ip_off, run_ctx_off, arg_stack_off, rbx_off;
@@ -2678,6 +2678,38 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *i
26782678
return ret;
26792679
}
26802680

2681+
int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image_end,
2682+
const struct btf_func_model *m, u32 flags,
2683+
struct bpf_tramp_links *tlinks,
2684+
void *func_addr)
2685+
{
2686+
return __arch_prepare_bpf_trampoline(im, image, image_end, m, flags, tlinks, func_addr);
2687+
}
2688+
2689+
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
2690+
struct bpf_tramp_links *tlinks, void *func_addr)
2691+
{
2692+
struct bpf_tramp_image im;
2693+
void *image;
2694+
int ret;
2695+
2696+
/* Allocate a temporary buffer for __arch_prepare_bpf_trampoline().
2697+
* This will NOT cause fragmentation in direct map, as we do not
2698+
* call set_memory_*() on this buffer.
2699+
*
2700+
* We cannot use kvmalloc here, because we need image to be in
2701+
* module memory range.
2702+
*/
2703+
image = bpf_jit_alloc_exec(PAGE_SIZE);
2704+
if (!image)
2705+
return -ENOMEM;
2706+
2707+
ret = __arch_prepare_bpf_trampoline(&im, image, image + PAGE_SIZE, m, flags,
2708+
tlinks, func_addr);
2709+
bpf_jit_free_exec(image);
2710+
return ret;
2711+
}
2712+
26812713
static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image, u8 *buf)
26822714
{
26832715
u8 *jg_reloc, *prog = *pprog;

include/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1106,6 +1106,8 @@ void *arch_alloc_bpf_trampoline(unsigned int size);
11061106
void arch_free_bpf_trampoline(void *image, unsigned int size);
11071107
void arch_protect_bpf_trampoline(void *image, unsigned int size);
11081108
void arch_unprotect_bpf_trampoline(void *image, unsigned int size);
1109+
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
1110+
struct bpf_tramp_links *tlinks, void *func_addr);
11091111

11101112
u64 notrace __bpf_prog_enter_sleepable_recur(struct bpf_prog *prog,
11111113
struct bpf_tramp_run_ctx *run_ctx);

kernel/bpf/trampoline.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1072,6 +1072,12 @@ void __weak arch_unprotect_bpf_trampoline(void *image, unsigned int size)
10721072
set_memory_rw((long)image, 1);
10731073
}
10741074

1075+
int __weak arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
1076+
struct bpf_tramp_links *tlinks, void *func_addr)
1077+
{
1078+
return -ENOTSUPP;
1079+
}
1080+
10751081
static int __init init_trampolines(void)
10761082
{
10771083
int i;

0 commit comments

Comments
 (0)