Commit 9f1e16fb authored by Pu Lehui's avatar Pu Lehui Committed by Daniel Borkmann

riscv, bpf: Fix out-of-bounds issue when preparing trampoline image

We get the size of the trampoline image during the dry run phase and
allocate memory based on that size. The allocated image will then be
populated with instructions during the real patch phase. But after
commit 26ef208c ("bpf: Use arch_bpf_trampoline_size"), the `im`
argument is inconsistent in the dry run and real patch phase. This may
cause emit_imm in RV64 to generate a different number of instructions
when generating the 'im' address, potentially causing out-of-bounds
issues. Let's emit the maximum number of instructions for the "im"
address during dry run to fix this problem.

Fixes: 26ef208c ("bpf: Use arch_bpf_trampoline_size")
Signed-off-by: default avatarPu Lehui <pulehui@huawei.com>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20240622030437.3973492-3-pulehui@huaweicloud.com
parent d1a42617
...@@ -16,6 +16,8 @@ ...@@ -16,6 +16,8 @@
#include "bpf_jit.h" #include "bpf_jit.h"
#define RV_FENTRY_NINSNS 2 #define RV_FENTRY_NINSNS 2
/* imm that allows emit_imm to emit max count insns */
#define RV_MAX_COUNT_IMM 0x7FFF7FF7FF7FF7FF
#define RV_REG_TCC RV_REG_A6 #define RV_REG_TCC RV_REG_A6
#define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */ #define RV_REG_TCC_SAVED RV_REG_S6 /* Store A6 in S6 if program do calls */
...@@ -916,7 +918,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -916,7 +918,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
orig_call += RV_FENTRY_NINSNS * 4; orig_call += RV_FENTRY_NINSNS * 4;
if (flags & BPF_TRAMP_F_CALL_ORIG) { if (flags & BPF_TRAMP_F_CALL_ORIG) {
emit_imm(RV_REG_A0, (const s64)im, ctx); emit_imm(RV_REG_A0, ctx->insns ? (const s64)im : RV_MAX_COUNT_IMM, ctx);
ret = emit_call((const u64)__bpf_tramp_enter, true, ctx); ret = emit_call((const u64)__bpf_tramp_enter, true, ctx);
if (ret) if (ret)
return ret; return ret;
...@@ -977,7 +979,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, ...@@ -977,7 +979,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
if (flags & BPF_TRAMP_F_CALL_ORIG) { if (flags & BPF_TRAMP_F_CALL_ORIG) {
im->ip_epilogue = ctx->insns + ctx->ninsns; im->ip_epilogue = ctx->insns + ctx->ninsns;
emit_imm(RV_REG_A0, (const s64)im, ctx); emit_imm(RV_REG_A0, ctx->insns ? (const s64)im : RV_MAX_COUNT_IMM, ctx);
ret = emit_call((const u64)__bpf_tramp_exit, true, ctx); ret = emit_call((const u64)__bpf_tramp_exit, true, ctx);
if (ret) if (ret)
goto out; goto out;
...@@ -1046,6 +1048,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, ...@@ -1046,6 +1048,7 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
{ {
int ret; int ret;
struct rv_jit_context ctx; struct rv_jit_context ctx;
u32 size = image_end - image;
ctx.ninsns = 0; ctx.ninsns = 0;
/* /*
...@@ -1059,11 +1062,16 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, ...@@ -1059,11 +1062,16 @@ int arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image,
ctx.ro_insns = image; ctx.ro_insns = image;
ret = __arch_prepare_bpf_trampoline(im, m, tlinks, func_addr, flags, &ctx); ret = __arch_prepare_bpf_trampoline(im, m, tlinks, func_addr, flags, &ctx);
if (ret < 0) if (ret < 0)
return ret; goto out;
bpf_flush_icache(ctx.insns, ctx.insns + ctx.ninsns); if (WARN_ON(size < ninsns_rvoff(ctx.ninsns))) {
ret = -E2BIG;
goto out;
}
return ninsns_rvoff(ret); bpf_flush_icache(image, image_end);
out:
return ret < 0 ? ret : size;
} }
int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx, int bpf_jit_emit_insn(const struct bpf_insn *insn, struct rv_jit_context *ctx,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment