Subject: Re: bpf: ability to attach freplace to multiple parents

From: Alan Maguire <[email-masked]>
Date: Tue, 12 May 2020 10:53:38 +0100 (BST)

On Tue, 12 May 2020, Toke Høiland-Jørgensen wrote:

> Alexei Starovoitov <[email-masked]> writes:
> 
> >> > Currently fentry/fexit/freplace progs have single prog->aux->linked_prog pointer.
> >> > It just needs to become a linked list.
> >> > The api extension could be like this:
> >> > bpf_raw_tp_open(prog_fd, attach_prog_fd, attach_btf_id);
> >> > (currently it's just bpf_raw_tp_open(prog_fd))
> >> > The same pair of (attach_prog_fd, attach_btf_id) is already passed into prog_load
> >> > to hold the linked_prog and its corresponding btf_id.
> >> > I'm proposing to extend raw_tp_open with this pair as well to
> >> > attach existing fentry/fexit/freplace prog to another target.
> >> > Internally the kernel verify that btf of current linked_prog
> >> > exactly matches to btf of another requested linked_prog and
> >> > if they match it will attach the same prog to two target programs (in case of freplace)
> >> > or two kernel functions (in case of fentry/fexit).
> >> 
> >> API-wise this was exactly what I had in mind as well.
> >
> > perfect!
>

Apologies in advance if I've missed a way to do this, but
for fentry/fexit, if we could attach the same program to
multiple kernel functions, it would be great it we could
programmatically access the BTF func proto id for the
attached function (prog->aux->attach_btf_id I think?).
Then perhaps we could support access to that and associated
ids via a helper, roughly like:

s32 btf_attach_info(enum btf_info_wanted wanted,
		    struct __btf_ptr *ptr,__u64 flags);

The info_wanted would be BTF_INFO_FUNC_PROTO, BTF_INFO_RET_TYPE,
BTF_INFO_NARGS, BTF_INFO_ARG1, etc.

With that and the BTF-based printk support in hand, we could
potentially use bpf_trace_printk() to print function arguments
in an attach-point agnostic way.  The BTF printk v2 patchset has
support for BTF id-based display (it's not currently used in that
patchset though). We'd have to teach it to print BTF func protos
but that's not too tricky I think. An ftrace-like program that
would print out function prototypes for the attached function
would look something like this:

	struct __btf_ptr func = { 0 };
	btf_attach_info(BTF_INFO_FUNC_PROTO, &func, 0); 
	btf_printk("%pT", &func);

Printing args would be slightly more complicated because we'd have
to determine from the BTF func proto whether the function argument
was a pointer or not. The BTF printk code assumes the _pointee_ BTF
type ("struct sk_buff") is specified along with the pointer
(a struct sk_buff *).

So

- if an arg is not a pointer, we'd need to set the pointer value
  in struct __btf_ptr to &arg while using the BTF id from the
  func proto
- if an arg is a pointer we'd want to get the pointee BTF type
  from the func proto while using the argument as the pointer arg.

Perhaps the best way to achieve that would be to pass in
a value/result struct __btf_ptr * as arg and have the
helper do the right thing.  Alternately we could use flags to
specify that for args which are pointers we want the pointee
BTF type.

With all that in place, we'd have all the pieces to write a
generic ftrace-like BPF program that supported function argument
display for any function attach point. 

I've had trouble keeping up with everything going on so
perhaps there's a way to do some of this already, but my understanding
of most of the referencing of attach BTF id is done at
verifier time. Tweaking the BPF program itself isn't an option
if it is to be shared with multiple attach points.

All of which is to say that if the aux info contains a linked
list, having the attach BTF id for each attached program accessible
such that a helper could retrieve the BTF id of the function it
is attached to would be great!

Thanks!

Alan

> Hi Alexei
> 
> I don't suppose you've had a chance to whip up a patch for this, have
> you? :)
> 
> -Toke
> 
>