[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