Re: [PATCH v3 bpf-next 7/9] libbpf: implement __arg_ctx fallback logic

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

 



On Thu, Jan 4, 2024 at 10:37 AM Andrii Nakryiko
<andrii.nakryiko@xxxxxxxxx> wrote:
>
> On Wed, Jan 3, 2024 at 9:39 PM Alexei Starovoitov
> <alexei.starovoitov@xxxxxxxxx> wrote:
> >
> > On Wed, Jan 3, 2024 at 5:39 PM Andrii Nakryiko <andrii@xxxxxxxxxx> wrote:
> > >
> > > This limitation was the reason to add btf_decl_tag("arg:ctx"), making
> > > the actual argument type not important, so that user can just define
> > > "generic" signature:
> > >
> > >   __noinline int global_subprog(void *ctx __arg_ctx) { ... }
> >
> > I still think that this __arg_ctx only makes sense with 'void *'.
> > Blind rewrite of ctx is a foot gun.
> >
> > I've tried the following:
> >
> > diff --git a/tools/testing/selftests/bpf/progs/test_global_func_ctx_args.c
> > b/tools/testing/selftests/bpf/progs/test_global_func_ctx_args.c
> > index 9a06e5eb1fbe..0e5f5205d4a8 100644
> > --- a/tools/testing/selftests/bpf/progs/test_global_func_ctx_args.c
> > +++ b/tools/testing/selftests/bpf/progs/test_global_func_ctx_args.c
> > @@ -106,9 +106,9 @@ int perf_event_ctx(void *ctx)
> >  /* this global subprog can be now called from many types of entry progs, each
> >   * with different context type
> >   */
> > -__weak int subprog_ctx_tag(void *ctx __arg_ctx)
> > +__weak int subprog_ctx_tag(long ctx __arg_ctx)
> >  {
> > -       return bpf_get_stack(ctx, stack, sizeof(stack), 0);
> > +       return bpf_get_stack((void *)ctx, stack, sizeof(stack), 0);
> >  }
> >
> >  struct my_struct { int x; };
> > @@ -131,7 +131,7 @@ int arg_tag_ctx_raw_tp(void *ctx)
> >  {
> >         struct my_struct x = { .x = 123 };
> >
> > -       return subprog_ctx_tag(ctx) + subprog_multi_ctx_tags(ctx, &x, ctx);
> > +       return subprog_ctx_tag((long)ctx) +
> > subprog_multi_ctx_tags(ctx, &x, ctx);
> >  }
> >
> > and it "works".
>
> Yeah, but you had to actively force casting everywhere *and* you still
> had to consciously add __arg_ctx, right? If a user wants to subvert
> the type system, they will do it. It's C, after all. But if they just
> accidentally use sk_buff ctx and call it from the XDP program with
> xdp_buff/xdp_md, the compiler will call out type mismatch.

I could have used long everywhere and avoided casts.

> >
> > Both kernel and libbpf should really limit it to 'void *'.
> >
> > In the other email I suggested to allow types that match expected
> > based on prog type, but even that is probably a danger zone as well.
> > The correct type would already be detected by the verifier,
> > so extra __arg_ctx is pointless.
> > It makes sense only for such polymorphic functions and those
> > better use 'void *' and don't dereference it.
> >
> > I think this can be a follow up.
>
> Not really just polymorphic functions. Think about subprog
> specifically for the fentry program, as one example. You *need*
> __arg_ctx just to make context passing work, but you also want
> non-`void *` type to access arguments.
>
> int subprog(u64 *args __arg_ctx) { ... }
>
> SEC("fentry")
> int BPF_PROG(main_prog, ...)
> {
>     return subprog(ctx);
> }
>
> Similarly, tracepoint programs, you'd have:
>
> int subprog(struct syscall_trace_enter* ctx __arg_ctx) { ... }
>
> SEC("tracepoint/syscalls/sys_enter_kill")
> int main_prog(struct syscall_trace_enter* ctx)
> {
>     return subprog(ctx);
> }
>
> So that's one group of cases.

But the above two are not supported by libbpf
since it doesn't handle "tracing" and "tracepoint" prog types
in global_ctx_map.
I suspect the kernel sort-of supports above, but in a dangerous
and broken way.

My point is that users must not use __arg_ctx in these two cases.
fentry (tracing prog type) wants 'void *' in the kernel to
match to ctx.
So the existing mechanism (prior to arg_ctx in the kernel)
should already work.

> Another special case are networking programs, where both "__sk_buff"
> and "sk_buff" are allowed, same for "xdp_buff" and "xdp_md".

what do you mean both?
networking bpf prog must only use __sk_buff and that is one and
only supported ctx.
Using 'struct sk_buff *ctx __arg_ctx' will be a bad bug.
Since offsets will be all wrong while ctx rewrite will apply garbage
and will likely fail.

> Also, kprobes are special, both "struct bpf_user_pt_regs_t" and
> *typedef* "bpf_user_pt_regs_t" are supported. But in practice users
> will often just use `struct pt_regs *ctx`, actually.

Same thing. The global bpf prog has to use bpf_user_pt_regs_t
to be properly recognized as ctx arg type.
Nothing special. Using 'struct pt_regs * ctx __arg_ctx' and blind
rewrite will cause similar hard to debug bugs when
bpf_user_pt_regs_t doesn't match pt_regs that bpf prog sees
at compile time.





[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