Re: [PATCH bpf-next v3 08/18] bpf: Check fixed-size mem args of helpers and kfuncs the same way
[email protected] Sat, 01 Aug 2026 08:17:20 +0000
| Newsgroups | org.kernel.vger.bpf |
|---|---|
| Message-ID | <[email protected]> |
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: New issues: - [High] Kfuncs taking uninitialized memory arguments via the `__uninit` annotation are falsely rejected when passed uninitialized stack slots. Pre-existing issues: - [Critical] The verifier fails to check if the size argument for `KF_ARG_PTR_TO_MEM_SIZE` kfuncs is a scalar, allowing BPF programs to pass kernel pointers as size arguments, leading to an out-of-bounds access. -- --- Patch [8]: [PATCH bpf-next v3 08/18] bpf: Check fixed-size mem args of helpers and kfuncs the same way --- commit bcee13ba62b78a9328164e2486f3c31a7fddb8a0 Author: Amery Hung <[email protected]> bpf: Check fixed-size mem args of helpers and kfuncs the same way Fixed-size memory arguments went through two paths: helpers called check_helper_mem_access() directly, while kfuncs and global subprogs used check_mem_reg(). Route the helper MEM_FIXED_SIZE case through check_mem_reg() too so all three share the same check. > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index f61771e2a8b27..9e0c7f0a15c15 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c [ ... ] > @@ -12379,7 +12385,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_call_arg_me > ref_tname, PTR_ERR(resolve_ret)); > return -EINVAL; > } > - ret = check_mem_reg(env, reg, argno, type_size, meta); > + ret = check_mem_reg(env, reg, argno, type_size, BPF_READ | BPF_WRITE, meta); [Severity: High] Does this change break BPF programs that pass uninitialized stack slots to kfuncs using the __uninit annotation? Because check_mem_reg() is now unconditionally called with BPF_READ | BPF_WRITE here, it seems to mandate initialization for __uninit kfunc arguments as well, which should only require BPF_WRITE. > if (ret < 0) > return ret; > break; > case KF_ARG_PTR_TO_MEM_SIZE: > { > struct bpf_reg_state *buff_reg = reg; > const struct btf_param *buff_arg = &args[i]; > struct bpf_reg_state *size_reg = get_func_arg_reg(caller, regs, i + 1); > const struct btf_param *size_arg = &args[i + 1]; > argno_t next_argno = argno_from_arg(i + 2); > > if (!bpf_register_is_null(buff_reg) || !is_kfunc_arg_nullable(meta->btf, buff_arg)) { > ret = check_mem_size_reg(env, buff_reg, size_reg, argno, next_argno, > BPF_READ | BPF_WRITE, true, meta); > if (ret < 0) { [ ... ] > } > > /* Skip next '__sz' or '__szk' argument */ > i++; > break; [Severity: Critical] This isn't a bug introduced by this patch, but does the verifier fail to enforce that the size argument is a scalar for KF_ARG_PTR_TO_MEM_SIZE? The loop uses i++ to skip the next iteration, which completely bypasses the btf_type_is_scalar validation for the size argument. check_mem_size_reg() also assumes the register is a SCALAR_VALUE without verifying it. If a BPF program passes a pointer register (like PTR_TO_STACK with a zero offset) as the size argument, reg_umax evaluates to 0, which passes the verifier's size checks. At runtime, the full kernel pointer address could be used as the size, potentially allowing an out-of-bounds memory access. -- Sashiko AI review ยท https://sashiko.dev/#/patchset/[email protected]?part=8