On Wed, Feb 12, 2025 at 1:19 AM Song Liu <song@xxxxxxxxxx> wrote: > > On Mon, Feb 10, 2025 at 6:34 PM Yafang Shao <laoar.shao@xxxxxxxxx> wrote: > > > > If we attach fexit to a function annotated with __noreturn, it will > > cause an issue that the bpf trampoline image will be left over even if > > the bpf link has been destroyed. Take attaching do_exit() for example. The > > fexit works as follows, > > > > bpf_trampoline > > + __bpf_tramp_enter > > + percpu_ref_get(&tr->pcref); > > > > + call do_exit() > > > > + __bpf_tramp_exit > > + percpu_ref_put(&tr->pcref); > > > > Since do_exit() never returns, the refcnt of the trampoline image is > > never decremented, preventing it from being freed. This can be verified > > with as follows, > > > > $ bpftool link show <<<< nothing output > > $ grep "bpf_trampoline_[0-9]" /proc/kallsyms > > ffffffffc04cb000 t bpf_trampoline_6442526459 [bpf] <<<< leftover > > > > With this change, attaching fexit probes to functions like do_exit() will > > be rejected. > > > > $ ./fexit > > libbpf: prog 'fexit': BPF program load failed: -EINVAL > > libbpf: prog 'fexit': -- BEGIN PROG LOAD LOG -- > > processed 0 insns (limit 1000000) max_states_per_insn 0 total_states 0 peak_states 0 mark_read 0 > > -- END PROG LOAD LOG -- > > libbpf: prog 'fexit': failed to load: -EINVAL > > libbpf: failed to load object 'fexit_bpf' > > libbpf: failed to load BPF skeleton 'fexit_bpf': -EINVAL > > failed to load BPF object -22 > > > > Signed-off-by: Yafang Shao <laoar.shao@xxxxxxxxx> > > --- > > kernel/bpf/verifier.c | 10 ++++++++++ > > 1 file changed, 10 insertions(+) > > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > > index 9971c03adfd5..f7224fc61e0c 100644 > > --- a/kernel/bpf/verifier.c > > +++ b/kernel/bpf/verifier.c > > @@ -22841,6 +22841,13 @@ BTF_ID(func, __rcu_read_unlock) > > #endif > > BTF_SET_END(btf_id_deny) > > > > +/* The functions annotated with __noreturn are denied. */ > > +BTF_SET_START(fexit_deny) > > +#define NORETURN(fn) BTF_ID(func, fn) > > +#include <linux/noreturns.h> > > +#undef NORETURN > > +BTF_SET_END(fexit_deny) > > + > > static bool can_be_sleepable(struct bpf_prog *prog) > > { > > if (prog->type == BPF_PROG_TYPE_TRACING) { > > @@ -22929,6 +22936,9 @@ static int check_attach_btf_id(struct bpf_verifier_env *env) > > } else if (prog->type == BPF_PROG_TYPE_TRACING && > > btf_id_set_contains(&btf_id_deny, btf_id)) { > > return -EINVAL; > > + } else if (prog->expected_attach_type == BPF_TRACE_FEXIT && > > + btf_id_set_contains(&fexit_deny, btf_id)) { > > Please add a verifier log (with verbose()) here, so that the user knows > why the program failed to attach. Good suggestion. I will add it. -- Regards Yafang