On Tue, Jul 21, 2026 at 09:30:34PM +0800, Leon Hwang wrote: > The trampoline could be corrupted by the blindly > 'tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX' in verifier. > > 1. A fexit attached to a tail_call_reachable prog. > 2. Another fexit loaded with the same tail_call_reachable prog target. > 3. Close the first fexit link.
had to ask ai for more details on how the warning was trigered ;-) would be nice to have that info in the changelog Acked-by: Jiri Olsa <[email protected]> jirka > > [ 3.410719] WARNING: kernel/bpf/syscall.c:3551 at > bpf_tracing_link_release+0x53/0x60, CPU#1: test_progs/98 > ... > [ 3.428793] bpf_link_free+0x58/0x130 > [ 3.429293] bpf_link_release+0x23/0x30 > > Fix the warning by updating 'tr->flags' with '|=' and lock. > > Fixes: 2b5dcb31a19a ("bpf, x64: Fix tailcall infinite loop") > Signed-off-by: Leon Hwang <[email protected]> > --- > include/linux/bpf.h | 2 ++ > kernel/bpf/trampoline.c | 7 +++++++ > kernel/bpf/verifier.c | 2 +- > 3 files changed, 10 insertions(+), 1 deletion(-) > > diff --git a/include/linux/bpf.h b/include/linux/bpf.h > index d9542127dfdf..fc84f39967ae 100644 > --- a/include/linux/bpf.h > +++ b/include/linux/bpf.h > @@ -1523,6 +1523,7 @@ int bpf_trampoline_multi_attach(struct bpf_prog *prog, > u32 *ids, > struct bpf_tracing_multi_link *link); > int bpf_trampoline_multi_detach(struct bpf_prog *prog, > struct bpf_tracing_multi_link *link); > +void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags); > > /* > * When the architecture supports STATIC_CALL replace the bpf_dispatcher_fn > @@ -1646,6 +1647,7 @@ static inline int bpf_trampoline_multi_detach(struct > bpf_prog *prog, > { > return -ENOTSUPP; > } > +static inline void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 > flags) {} > #endif > > struct bpf_func_info_aux { > diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c > index 6eadf64f7ec9..129d07db117e 100644 > --- a/kernel/bpf/trampoline.c > +++ b/kernel/bpf/trampoline.c > @@ -670,6 +670,13 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 > key, int size) > return ERR_PTR(err); > } > > +void bpf_trampoline_set_flags(struct bpf_trampoline *tr, u32 flags) > +{ > + trampoline_lock(tr); > + tr->flags |= flags; > + trampoline_unlock(tr); > +} > + > static int bpf_trampoline_update(struct bpf_trampoline *tr, bool > lock_direct_mutex, > const struct bpf_trampoline_ops *ops, void > *data) > { > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index 52be0a118cce..66d8d9eaec05 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -19523,7 +19523,7 @@ static int check_attach_btf_id(struct > bpf_verifier_env *env) > return -ENOMEM; > > if (tgt_prog && tgt_prog->aux->tail_call_reachable) > - tr->flags = BPF_TRAMP_F_TAIL_CALL_CTX; > + bpf_trampoline_set_flags(tr, BPF_TRAMP_F_TAIL_CALL_CTX); > > prog->aux->dst_trampoline = tr; > return 0; > -- > 2.55.0 >

