Re: [PATCH bpf-next 2/3] bpf: Reject attaching fexit to functions annotated with __noreturn

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux