> 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?

> +
> +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

Reply via email to