summaryrefslogtreecommitdiffstats
path: root/arch/riscv
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2026-10-02 12:59:32 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2026-10-02 12:59:32 -0700
commit8f150ccedfbd610aa25509ff42365d70fb20478f (patch)
tree1b22e147a9f8464940fcfa0483c96b8842c953c5 /arch/riscv
parentd2dbe503fd806082acb0ca79a9d6641822988c2c (diff)
parentde020dc8049bfb2b22e3b6d99c031feb2e22d112 (diff)
downloadlinux-stable-8f150ccedfbd610aa25509ff42365d70fb20478f.tar.gz
linux-stable-8f150ccedfbd610aa25509ff42365d70fb20478f.zip
Merge tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf
Pull bpf fixes from Alexei Starovoitov: - Fix overflow of backward jump offset in constant blinding (Alexei Starovoitov) - Fix packet range of packet pointers sharing an id when var_off tightens umax of one pointer and not the other (Alexei Starovoitov) - Fix objects stuck in free_by_rcu_ttrace list of bpf memalloc (Alexei Starovoitov) - Fix use-after-free of progs detached from busy trampolines: wait for an RCU tasks grace period before freeing trampoline progs, and patch detached progs out of trampoline images that are still in use (Florent Revest) - Hold map BTF for the memory allocator destructor record to fix UAF in deferred bpf_mem_alloc destruction (Kumar Kartikeya Dwivedi) - Fix missing migration protection in resizable hashtab lookup_and_delete batch operation (Ă–mer Mete Kaya) * tag 'bpf-fixes' of git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf: bpf: Fix missing migration protection in __rhtab_map_lookup_and_delete_batch() selftests/bpf: Add a test for objects stuck in free_by_rcu_ttrace bpf: Fix objects stuck in free_by_rcu_ttrace bpf: Factor out __do_call_rcu_ttrace() selftests/bpf: Test packet range of pointers sharing an id bpf: Fix packet range of pointers sharing an id selftests/bpf: Detach a trampoline prog while a task sleeps before it bpf: Skip detached progs in trampoline images that are still in use bpf: Wait for an RCU tasks grace period before freeing trampoline progs bpf: Hold map BTF for the memory allocator destructor record bpf: Fix overflow of jump offset in constant blinding
Diffstat (limited to 'arch/riscv')
-rw-r--r--arch/riscv/net/bpf_jit_comp64.c56
1 files changed, 39 insertions, 17 deletions
diff --git a/arch/riscv/net/bpf_jit_comp64.c b/arch/riscv/net/bpf_jit_comp64.c
index 151031e97..01fe66774 100644
--- a/arch/riscv/net/bpf_jit_comp64.c
+++ b/arch/riscv/net/bpf_jit_comp64.c
@@ -822,6 +822,24 @@ static int gen_jump_or_nops(void *target, void *ip, u32 *insns, bool is_call)
return emit_jump_and_link(is_call ? RV_REG_T0 : RV_REG_ZERO, rvoff, false, &ctx);
}
+int arch_bpf_trampoline_skip(void *nop, void *target)
+{
+ u32 old_insn = rv_nop();
+ u32 new_insn = rv_jal(RV_REG_ZERO, (target - nop) >> 1);
+ int ret;
+
+ if (memcmp(nop, &old_insn, sizeof(old_insn)))
+ return -EFAULT;
+
+ cpus_read_lock();
+ mutex_lock(&text_mutex);
+ ret = patch_text(nop, &new_insn, sizeof(new_insn));
+ mutex_unlock(&text_mutex);
+ cpus_read_unlock();
+
+ return ret;
+}
+
int bpf_arch_text_poke(void *ip, enum bpf_text_poke_type old_t,
enum bpf_text_poke_type new_t, void *old_addr,
void *new_addr)
@@ -904,12 +922,17 @@ static void emit_store_stack_imm64(u8 reg, int stack_off, u64 imm64,
emit_sd(RV_REG_FP, stack_off, reg, ctx);
}
-static int invoke_bpf_prog(struct bpf_tramp_node *node, int args_off, int retval_off,
- int run_ctx_off, bool save_ret, struct rv_jit_context *ctx)
+static int invoke_bpf_prog(struct bpf_tramp_image *im, struct bpf_tramp_node *node,
+ int args_off, int retval_off, int run_ctx_off, bool save_ret,
+ struct rv_jit_context *ctx)
{
int ret, branch_off;
struct bpf_prog *p = node->link->prog;
int cookie_off = offsetof(struct bpf_tramp_run_ctx, bpf_cookie);
+ void *skip = ctx->ro_insns + ctx->ninsns;
+
+ /* nop, patched to a jal over this prog when it is detached */
+ emit(rv_nop(), ctx);
if (node->cookie)
emit_store_stack_imm64(RV_REG_T1, -run_ctx_off + cookie_off, node->cookie, ctx);
@@ -962,13 +985,17 @@ static int invoke_bpf_prog(struct bpf_tramp_node *node, int args_off, int retval
/* arg3: &run_ctx */
emit_addi(RV_REG_A2, RV_REG_FP, -run_ctx_off, ctx);
ret = emit_call((const u64)bpf_trampoline_exit(p), true, ctx);
+ if (ret)
+ return ret;
- return ret;
+ bpf_tramp_image_add_skip(im, p, skip, ctx->ro_insns + ctx->ninsns);
+ return 0;
}
-static int invoke_bpf(struct bpf_tramp_nodes *tn, int args_off, int retval_off,
- int run_ctx_off, int func_meta_off, bool save_ret, u64 func_meta,
- int cookie_off, struct rv_jit_context *ctx)
+static int invoke_bpf(struct bpf_tramp_image *im, struct bpf_tramp_nodes *tn,
+ int args_off, int retval_off, int run_ctx_off, int func_meta_off,
+ bool save_ret, u64 func_meta, int cookie_off,
+ struct rv_jit_context *ctx)
{
int i, cur_cookie = (cookie_off - args_off) / 8;
@@ -981,8 +1008,8 @@ static int invoke_bpf(struct bpf_tramp_nodes *tn, int args_off, int retval_off,
emit_store_stack_imm64(RV_REG_T1, -func_meta_off, meta, ctx);
cur_cookie--;
}
- err = invoke_bpf_prog(tn->nodes[i], args_off, retval_off, run_ctx_off,
- save_ret, ctx);
+ err = invoke_bpf_prog(im, tn->nodes[i], args_off, retval_off,
+ run_ctx_off, save_ret, ctx);
if (err)
return err;
}
@@ -1170,7 +1197,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
}
if (fentry->nr_nodes) {
- ret = invoke_bpf(fentry, args_off, retval_off, run_ctx_off, func_meta_off,
+ ret = invoke_bpf(im, fentry, args_off, retval_off, run_ctx_off, func_meta_off,
flags & BPF_TRAMP_F_RET_FENTRY_RET, func_meta, cookie_off, ctx);
if (ret)
return ret;
@@ -1184,7 +1211,7 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
/* cleanup to avoid garbage return value confusion */
emit_sd(RV_REG_FP, -retval_off, RV_REG_ZERO, ctx);
for (i = 0; i < fmod_ret->nr_nodes; i++) {
- ret = invoke_bpf_prog(fmod_ret->nodes[i], args_off, retval_off,
+ ret = invoke_bpf_prog(im, fmod_ret->nodes[i], args_off, retval_off,
run_ctx_off, true, ctx);
if (ret)
goto out;
@@ -1211,10 +1238,6 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
emit_sd(RV_REG_FP, -tcc_off, RV_REG_TCC, ctx);
emit_sd(RV_REG_FP, -retval_off, RV_REG_A0, ctx);
emit_sd(RV_REG_FP, -(retval_off - 8), regmap[BPF_REG_0], ctx);
- im->ip_after_call = ctx->ro_insns + ctx->ninsns;
- /* 2 nops reserved for auipc+jalr pair */
- emit(rv_nop(), ctx);
- emit(rv_nop(), ctx);
}
/* update branches saved in invoke_bpf_mod_ret with bnez */
@@ -1230,14 +1253,13 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im,
emit_store_stack_imm64(RV_REG_T1, -func_meta_off, func_meta, ctx);
if (fexit->nr_nodes) {
- ret = invoke_bpf(fexit, args_off, retval_off, run_ctx_off, func_meta_off,
+ ret = invoke_bpf(im, fexit, args_off, retval_off, run_ctx_off, func_meta_off,
false, func_meta, cookie_off, ctx);
if (ret)
goto out;
}
if (flags & BPF_TRAMP_F_CALL_ORIG) {
- im->ip_epilogue = ctx->ro_insns + ctx->ninsns;
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);
if (ret)
@@ -1299,7 +1321,7 @@ out:
int arch_bpf_trampoline_size(const struct btf_func_model *m, u32 flags,
struct bpf_tramp_nodes *tnodes, void *func_addr)
{
- struct bpf_tramp_image im;
+ struct bpf_tramp_image im = {};
struct rv_jit_context ctx;
int ret;