On Wed, May 27, 2026 at 12:59:43PM +0000, [email protected] wrote:
> > diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
> > index 435ae6efe961..27ad0c265c95 100644
> > --- a/kernel/bpf/syscall.c
> > +++ b/kernel/bpf/syscall.c
> > @@ -41,6 +41,7 @@
> > #include <linux/overflow.h>
> > #include <linux/cookie.h>
> > #include <linux/verification.h>
> > +#include <linux/btf_ids.h>
> >
> > #include <net/netfilter/nf_bpf_link.h>
> > #include <net/netkit.h>
>
> [ ... ]
>
> > @@ -2904,6 +2914,11 @@ static int bpf_prog_mark_insn_arrays_ready(struct
> > bpf_prog *prog)
> > return 0;
> > }
> >
> > +extern int bpf_multi_func(void);
> > +int __init __used bpf_multi_func(void) { return 0; }
>
> The signature change from v5 to v6 creates a potential issue. In v5,
> bpf_multi_func had 6 arguments (matching the initial verifier setup):
>
> int __init __used bpf_multi_func(u64 r1, u64 r2, u64 r3,
> u64 r4, u64 r5, u64 r6)
>
> Now it has no arguments. The Sashiko AI review in v5 identified that
> context array bounds checking could fail when bpf_multi_func's argument
> count doesn't match the attached function's argument count, and the
> author acknowledged the need to disable direct context access.
>
> Since the initial verification happens against bpf_multi_func (which now
> has 0 arguments), but the verifier previously allowed direct ctx[0-5]
> accesses based on the 6-argument version, is there still a path where
> direct context accesses could be allowed? If so, would accessing ctx[0]
> on a function with 0 arguments lead to out-of-bounds kernel stack reads?
>
> The earlier review suggested either:
> (a) explicitly disabling direct memory accesses to the ctx array for
> FENTRY_MULTI and FEXIT_MULTI, or
> (b) enforcing the use of bounds-checked helpers like bpf_get_func_arg()
>
> Was this implemented somewhere in the patch series?
it's implemented through bpf_multi_func without any arguments,
then verifier won't allow any access to any argument,
including ctx[0], which is 1st argument
jirka
>
> > +
> > +BTF_ID_LIST_GLOBAL_SINGLE(bpf_multi_func_btf_id, func, bpf_multi_func)
>
> [ ... ]
>
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index c8d980fdd709..58450cb88beb 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
>
> [ ... ]
>
> > @@ -18837,6 +18839,11 @@ static int check_attach_modify_return(unsigned
> > long addr, const char *func_name)
> >
> > #endif /* CONFIG_FUNCTION_ERROR_INJECTION */
> >
> > +static bool is_tracing_multi_id(const struct bpf_prog *prog, u32 btf_id)
> > +{
> > + return is_tracing_multi(prog->expected_attach_type) &&
> > bpf_multi_func_btf_id[0] == btf_id;
> > +}
> > +
> > int bpf_check_attach_target(struct bpf_verifier_log *log,
> > const struct bpf_prog *prog,
> > const struct bpf_prog *tgt_prog,
>
> [ ... ]
>
> > @@ -19094,7 +19105,18 @@ int bpf_check_attach_target(struct
> > bpf_verifier_log *log,
> > if (ret < 0)
> > return ret;
> >
> > - if (tgt_prog) {
> > + /*
> > + * *.multi programs don't need an address during program
> > + * verification, we just take the module ref if needed.
> > + */
> > + if (is_tracing_multi_id(prog, btf_id)) {
> > + if (btf_is_module(btf)) {
> > + mod = btf_try_get_module(btf);
> > + if (!mod)
> > + return -ENOENT;
> > + }
> > + addr = 0;
> > + } else if (tgt_prog) {
> > if (subprog == 0)
> > addr = (long) tgt_prog->bpf_func;
> > else
>
> [ ... ]
>
> > @@ -19122,6 +19144,12 @@ int bpf_check_attach_target(struct
> > bpf_verifier_log *log,
> > ret = -EINVAL;
> > switch (prog->type) {
> > case BPF_PROG_TYPE_TRACING:
> > + /* *.multi sleepable programs will pass initial
> > sleepable check,
> > + * the actual attached btf ids are checked
> > later during the link
> > + * attachment.
> > + */
> > + if (is_tracing_multi_id(prog, btf_id))
> > + ret = 0;
> > if (!check_attach_sleepable(btf_id, addr,
> > tname))
> > ret = 0;
>
> The multi types are not included in btf_validate_prog_ctx_type() in
> kernel/bpf/btf.c. That function validates which attach types allow u64*
> as their ctx parameter:
>
> kernel/bpf/btf.c:btf_validate_prog_ctx_type() {
> case BPF_TRACE_FENTRY:
> case BPF_TRACE_FEXIT:
> case BPF_MODIFY_RETURN:
> ...
> }
>
> Since BPF_TRACE_FENTRY_MULTI and BPF_TRACE_FEXIT_MULTI also use u64*
> context, do they need to be added to that validation list? Or if direct
> context access should be disabled for multi types (per the earlier
> review concern), should they be handled with special rejection logic?
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/26509800686