> diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
> --- a/kernel/bpf/core.c
> +++ b/kernel/bpf/core.c

[ ... ]

> @@ -2418,6 +2419,9 @@ static bool __bpf_prog_map_compatible(struct bpf_map 
> *map,
>                     map->owner->sleepable == fp->sleepable;
>               if (ret && (!map->owner->kprobe_write_ctx && 
> aux->kprobe_write_ctx))
>                       ret = false;
> +             if (ret && (!map->owner->call_get_func_ip && 
> fp->call_get_func_ip &&
> +                         prog_type == BPF_PROG_TYPE_TRACING))
> +                     ret = false;

This check catches the case where owner->call_get_func_ip is 0 and
the new program has call_get_func_ip set. However, does the reverse
ordering also need to be handled?

Consider:

  1. Program H (call_get_func_ip=1) is added to the prog_array first
     and becomes the owner with owner->call_get_func_ip=1.

  2. Program M (call_get_func_ip=0) is loaded and references this
     prog_array for tail calls. bpf_check_tail_call() calls
     __bpf_prog_map_compatible(PA, M), and the check evaluates:

       (!owner->call_get_func_ip && fp->call_get_func_ip)
       (!1 && 0) = false

     so M passes the compatibility check.

  3. M is attached to a trampoline where no program needs func_ip,
     so ip_arg is false and func_ip is not pushed on the stack.

  4. M tail-calls H. H calls bpf_get_func_ip(), which reads from
     the expected stack offset, but that slot was never written by
     the trampoline, so it returns stale stack data.

Would it be safer to reject any mismatch on call_get_func_ip for
tracing programs, regardless of which program was added first?
Something like:

  if (ret && (map->owner->call_get_func_ip != fp->call_get_func_ip) &&
      prog_type == BPF_PROG_TYPE_TRACING)
          ret = false;

>               if (ret &&
>                   map->map_type == BPF_MAP_TYPE_PROG_ARRAY &&
>                   map->owner->expected_attach_type != 
> fp->expected_attach_type)
>                       ret = false;


---
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/22358832658

AI-authorship-score: medium
AI-authorship-explanation: Selftests in the series carry Assisted-by Codex 
tags, and the kernel code change is formulaic pattern replication across all 
commits, consistent with AI-assisted development.
issues-found: 1
issue-severity-score: medium
issue-severity-explanation: One-directional compatibility check allows a 
non-call_get_func_ip tail-caller to bypass the check when the call_get_func_ip 
program is added to the prog_array first, potentially causing bpf_get_func_ip 
to return stale stack data.

Reply via email to