[RFC PATCH bpf-next 3/7] bpf: Enable BPF_LINK_UPDATE for fentry/fexit/fmod_ret links
Jordan Rife
jordan at jrife.io
Thu Nov 20 11:23:27 PST 2025
On Tue, Nov 18, 2025 at 01:19:33AM +0000, bot+bpf-ci at kernel.org wrote:
> > diff --git a/include/linux/bpf.h b/include/linux/bpf.h
> > index 23fcbcd26..7daf40cbd 100644
> > --- a/include/linux/bpf.h
> > +++ b/include/linux/bpf.h
> > @@ -1215,6 +1215,8 @@ enum {
> >
> > struct bpf_tramp_links {
> > struct bpf_tramp_link *links[BPF_MAX_TRAMP_LINKS];
> > + struct bpf_tramp_link *update_link;
> > + struct bpf_prog *update_prog;
> > int nr_links;
> > };
>
> [ ... ]
>
> > @@ -1840,6 +1843,13 @@ struct bpf_tramp_link {
> > u64 cookie;
> > };
> >
> > +static inline struct bpf_prog *
> > +bpf_tramp_links_prog(struct bpf_tramp_links *tl, int i)
> > +{
> > + return tl->links[i] == tl->update_link ? tl->update_prog :
> > + tl->links[i]->link.prog;
> > +}
>
> This helper is added but the architecture-specific code in
> arch/x86/net/bpf_jit_comp.c, arch/arm64/net/bpf_jit_comp.c, and
> arch/s390/net/bpf_jit_comp.c continues to access tl->links[i]->link.prog
> directly. When __bpf_trampoline_update() passes tlinks with update_link
> and update_prog set, won't arch_prepare_bpf_trampoline() and
> arch_bpf_trampoline_size() use the old program instead of the new one?
>
> For example, in arch/x86/net/bpf_jit_comp.c around line 2966:
> struct bpf_prog *p = l->link.prog;
>
> This should probably use bpf_tramp_links_prog() to get the correct
> program during updates. The same pattern appears in the other arch
> implementations.
This is done in follow up patches in this series.
> > diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c
> > index 171440f37..486f945f6 100644
> > --- a/kernel/bpf/trampoline.c
> > +++ b/kernel/bpf/trampoline.c
> > @@ -232,7 +232,10 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr)
> > }
> >
> > static struct bpf_tramp_links *
> > -bpf_trampoline_get_progs(const struct bpf_trampoline *tr, int *total, bool *ip_arg)
> > +bpf_trampoline_get_progs(const struct bpf_trampoline *tr,
> > + struct bpf_tramp_link *update_link,
> > + struct bpf_prog *update_prog,
> > + int *total, bool *ip_arg)
> > {
> > struct bpf_tramp_link *link;
> > struct bpf_tramp_links *tlinks;
> > @@ -252,6 +255,11 @@ bpf_trampoline_get_progs(const struct bpf_trampoline *tr, int *total, bool *ip_a
> > hlist_for_each_entry(link, &tr->progs_hlist[kind], tramp_hlist) {
> > *ip_arg |= link->link.prog->call_get_func_ip;
> > *links++ = link;
> > + if (link == update_link) {
> > + *ip_arg |= update_prog->call_get_func_ip;
> > + tlinks[kind].update_link = update_link;
> > + tlinks[kind].update_prog = update_prog;
> > + }
> > }
> > }
> > return tlinks;
>
> [ ... ]
>
> > @@ -397,7 +405,10 @@ static struct bpf_tramp_image *bpf_tramp_image_alloc(u64 key, int size)
> > return ERR_PTR(err);
> > }
> >
> > -static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex)
> > +static int __bpf_trampoline_update(struct bpf_trampoline *tr,
> > + struct bpf_tramp_link *update_link,
> > + struct bpf_prog *update_prog,
> > + bool lock_direct_mutex)
> > {
> > struct bpf_tramp_image *im;
> > struct bpf_tramp_links *tlinks;
> > @@ -405,7 +416,11 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
> > bool ip_arg = false;
> > int err, total, size;
> >
> > - tlinks = bpf_trampoline_get_progs(tr, &total, &ip_arg);
> > + if (update_link && !bpf_trampoline_supports_update_prog())
> > + return -ENOTSUPP;
> > +
> > + tlinks = bpf_trampoline_get_progs(tr, update_link, update_prog,
> > + &total, &ip_arg);
>
> [ ... ]
>
> > @@ -503,6 +518,11 @@ static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mut
> > goto out;
> > }
> >
> > +static int bpf_trampoline_update(struct bpf_trampoline *tr, bool lock_direct_mutex)
> > +{
> > + return __bpf_trampoline_update(tr, NULL, NULL, lock_direct_mutex);
> > +}
> > +
> > static enum bpf_tramp_prog_type bpf_attach_type_to_tramp(struct bpf_prog *prog)
> > {
> > switch (prog->expected_attach_type) {
> > @@ -626,7 +646,7 @@ static int __bpf_trampoline_update_prog(struct bpf_tramp_link *link,
> > return 0;
> > }
> >
> > - return -ENOTSUPP;
> > + return __bpf_trampoline_update(tr, link, new_prog, true);
> > }
>
> [ ... ]
>
> > @@ -1136,6 +1156,11 @@ arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, void *image, void *image
> > return -ENOTSUPP;
> > }
> >
> > +bool __weak bpf_trampoline_supports_update_prog(void)
> > +{
> > + return false;
> > +}
>
> The commit message says "For now, only x86, arm64, and s390 are
> implemented" but none of these architectures appear to be updated in
> this patch or in the visible preceding commits (627b0f207, b0184022d).
> Without overriding bpf_trampoline_supports_update_prog() to return true
> and updating the arch code to use bpf_tramp_links_prog(), the feature
> will always return -ENOTSUPP on all architectures. Was this patch meant
> to include the arch-specific implementations, or are they in a separate
> series?
The architecture-specific implementations for x86, arm64, and s390 are
in follow up patches in this series.
> ---
> 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/19450205468
More information about the linux-arm-kernel
mailing list