Subject: Re: [PATCH bpf-next 04/16] net: Add BPF_XDP_EGRESS as a bpf_attach_type

From: Toke Høiland-Jørgensen <[email-masked]>
Date: Fri, 24 Apr 2020 10:55:42 +0200

Alexei Starovoitov <[email-masked]> writes:

> On Fri, Apr 24, 2020 at 01:49:03AM +0200, Toke Høiland-Jørgensen wrote:
>> Alexei Starovoitov <[email-masked]> writes:
>> 
>> > On Thu, Apr 23, 2020 at 07:05:42PM +0200, Toke Høiland-Jørgensen wrote:
>> >> >> >
>> >> >> > Looks like there is indeed a bug in prog_type_ext handling code that
>> >> >> > is doing
>> >> >> > env->ops = bpf_verifier_ops[tgt_prog->type];
>> >> >> > I'm not sure whether the verifier can simply add:
>> >> >> > prog->expected_attach_type = tgt_prog->expected_attach_type;
>> >> >> > and be done with it.
>> >> >> > Likely yes, since expected_attach_type must be zero at that point
>> >> >> > that is enforced by bpf_prog_load_check_attach().
>> >> >> > So I suspect it's a single line fix.
>> >> >>
>> >> >> Not quite: the check in bpf_tracing_prog_attach() that enforces
>> >> >> prog->expected_attach_type==0 also needs to go. So 5 lines :)
>> >> >
>> >> > prog_ext's expected_attach_type needs to stay zero.
>> >> > It needs to be inherited from tgt prog. Hence one line:
>> >> > prog->expected_attach_type = tgt_prog->expected_attach_type;
>> >> 
>> >> Not sure I follow you here? I ended up with the patch below - without
>> >> the first hunk I can't attach freplace funcs to an xdp egress prog
>> >> (since the expected_attach_type will have been propagated from
>> >> verification time), and so that check will fail. Or am I missing
>> >> something?
>> >> 
>> >> -Toke
>> >> 
>> >> 
>> >> 
>> >> diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
>> >> index d85f37239540..40c3103c7233 100644
>> >> --- a/kernel/bpf/syscall.c
>> >> +++ b/kernel/bpf/syscall.c
>> >> @@ -2381,10 +2381,6 @@ static int bpf_tracing_prog_attach(struct bpf_prog *prog)
>> >>                 }
>> >>                 break;
>> >>         case BPF_PROG_TYPE_EXT:
>> >> -               if (prog->expected_attach_type != 0) {
>> >> -                       err = -EINVAL;
>> >> -                       goto out_put_prog;
>> >> -               }
>> >>                 break;
>> >
>> > ahh. that extra check.
>> > I think it's better to keep it for extra safety.
>> > Here all expected_attach_type have clear checks depending on prog_type.
>> > There is no other place where it's that obvious.
>> > The verifier does similar thing earlier, but it's not that clear.
>> > I think the better fix would to set expected_attach_type = 0 for PROG_TYPE_EXT
>> > at the end of do_check, since we're overriding this field temporarily
>> > during verification.
>> 
>> OK, sure, can do. I do agree it's better to keep the check. I'll send a
>> proper patch tomorrow, then.
>> 
>> As far as a adding a selftest for this, I think the most natural thing
>> would be to add it on top of David's tests for xdp_egress, since that's
>> what hit this - would you be OK with that? And if so, should I send the
>> main patch straight away and hold off on the selftest, or should I split
>> them, or hold off on the whole thing?
>
> I think the issue is not related to xdp egress.
> Hence I'd like to push the fix along with selftest into bpf tree.
> The selftest can be:
> void noinline do_bind((struct bpf_sock_addr *ctx)
> {
>   struct sockaddr_in sa = {};
>
>   bpf_bind(ctx, (struct sockaddr *)&sa, sizeof(sa));
>   return 0;
> }
> SEC("cgroup/connect4")
> int connect_v4_prog(struct bpf_sock_addr *ctx)
> {
>   return do_bind(ctx);
> }
>
> and freplace would replace do_bind() with do_new_bind()
> that also calls bpf_bind().
> I think without the fix freplace will fail to load, because
> availability of bpf_bind() depends on correct
> prog->expected_attach_type.

Right, I'll give this a shot, thanks :)

> I haven't looked at the crash you mentioned in the other email related
> to xdp egress set. That could be different issue. I hope it's the same
> thing :)

Yeah, it is.

-Toke