Re: [PATCH v3 bpf-next 6/6] selftests/bpf: Test BPF_F_REPLACE in cgroup_attach_multi

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

 



Andrii Nakryiko <andrii.nakryiko@xxxxxxxxx> [Wed, 2019-12-18 21:59 -0800]:
> On Wed, Dec 18, 2019 at 6:17 PM Andrey Ignatov <rdna@xxxxxx> wrote:
> >
> > Test replacing a cgroup-bpf program attached with BPF_F_ALLOW_MULTI and
> > possible failure modes: invalid combination of flags, invalid
> > replace_bpf_fd, replacing a non-attachd to specified cgroup program.
> >
> > Example of program replacing:
> >
> >   # gdb -q --args ./test_progs --name=cgroup_attach_multi
> >   ...
> >   Breakpoint 1, test_cgroup_attach_multi () at cgroup_attach_multi.c:227
> >   (gdb)
> >   [1]+  Stopped                 gdb -q --args ./test_progs --name=cgroup_attach_multi
> >   # bpftool c s /mnt/cgroup2/cgroup-test-work-dir/cg1
> >   ID       AttachType      AttachFlags     Name
> >   2133     egress          multi
> >   2134     egress          multi
> >   # fg
> >   gdb -q --args ./test_progs --name=cgroup_attach_multi
> >   (gdb) c
> >   Continuing.
> >
> >   Breakpoint 2, test_cgroup_attach_multi () at cgroup_attach_multi.c:233
> >   (gdb)
> >   [1]+  Stopped                 gdb -q --args ./test_progs --name=cgroup_attach_multi
> >   # bpftool c s /mnt/cgroup2/cgroup-test-work-dir/cg1
> >   ID       AttachType      AttachFlags     Name
> >   2139     egress          multi
> >   2134     egress          multi
> >
> > Signed-off-by: Andrey Ignatov <rdna@xxxxxx>
> > ---
> >  .../bpf/prog_tests/cgroup_attach_multi.c      | 53 +++++++++++++++++--
> >  1 file changed, 50 insertions(+), 3 deletions(-)
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c b/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c
> > index 4eaab7435044..2ff21dbce179 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/cgroup_attach_multi.c
> > @@ -78,7 +78,8 @@ void test_cgroup_attach_multi(void)
> >  {
> >         __u32 prog_ids[4], prog_cnt = 0, attach_flags, saved_prog_id;
> >         int cg1 = 0, cg2 = 0, cg3 = 0, cg4 = 0, cg5 = 0, key = 0;
> > -       int allow_prog[6] = {-1};
> > +       DECLARE_LIBBPF_OPTS(bpf_prog_attach_opts, attach_opts);
> > +       int allow_prog[7] = {-1};
> >         unsigned long long value;
> >         __u32 duration = 0;
> >         int i = 0;
> > @@ -189,6 +190,52 @@ void test_cgroup_attach_multi(void)
> >         CHECK_FAIL(bpf_map_lookup_elem(map_fd, &key, &value));
> >         CHECK_FAIL(value != 1 + 2 + 8 + 16);
> >
> > +       /* test replace */
> > +
> > +       attach_opts.flags = BPF_F_ALLOW_OVERRIDE | BPF_F_REPLACE;
> > +       attach_opts.replace_prog_fd = allow_prog[0];
> > +       if (CHECK(!bpf_prog_attach_xattr(allow_prog[6], cg1,
> > +                                        BPF_CGROUP_INET_EGRESS, &attach_opts),
> > +                 "fail_prog_replace_override", "unexpected success\n"))
> > +               goto err;
> > +       CHECK_FAIL(errno != EINVAL);
> 
> CHECK macro above can prints both in success and failure scenarios,
> which means that errno of bpf_prog_attach_xattr can be overriden by a
> bunch of other functions. So if this check is critical, you'd have to
> remember errno before calling CHECK. Same for all the check below.

If bpf_prog_attach_xattr finishes successfully (what is unexpected
here), `goto err` will be taken and `CHECK_FAIL(errno != EINVAL)` won't
be run at all so "success" case is not a problem.

If bpf_prog_attach_xattr fails (what is expected) it has to set errno
and this is the errno that will be checked by CHECK_FAIL, i.e. failure
case is not a problem at all.

If you mean printf() that is called from "PASS" branch of CHECK then I
don't actually see a way to distinguish errno from failed
bpf_prog_attach_xattr (what would mean "PASS" for the CHECK) and
printf() from the CHECK() w/o changing CHECK() itself.

I think CHECK() can be improved wrt errno so that it saves errno before
calling anything that can affect it and restore it afterwards. But this
is not specific to this patch so IMO it should be done separately with,
ideally, checking that it doesn't break some other tests.

> > +
> > +       attach_opts.flags = BPF_F_REPLACE;
> > +       if (CHECK(!bpf_prog_attach_xattr(allow_prog[6], cg1,
> > +                                        BPF_CGROUP_INET_EGRESS, &attach_opts),
> > +                 "fail_prog_replace_no_multi", "unexpected success\n"))
> > +               goto err;
> > +       CHECK_FAIL(errno != EINVAL);
> > +
> > +       attach_opts.flags = BPF_F_ALLOW_MULTI | BPF_F_REPLACE;
> > +       attach_opts.replace_prog_fd = -1;
> > +       if (CHECK(!bpf_prog_attach_xattr(allow_prog[6], cg1,
> > +                                        BPF_CGROUP_INET_EGRESS, &attach_opts),
> > +                 "fail_prog_replace_bad_fd", "unexpected success\n"))
> > +               goto err;
> > +       CHECK_FAIL(errno != EBADF);
> > +
> > +       /* replacing a program that is not attached to cgroup should fail  */
> > +       attach_opts.replace_prog_fd = allow_prog[3];
> > +       if (CHECK(!bpf_prog_attach_xattr(allow_prog[6], cg1,
> > +                                        BPF_CGROUP_INET_EGRESS, &attach_opts),
> > +                 "fail_prog_replace_no_ent", "unexpected success\n"))
> > +               goto err;
> > +       CHECK_FAIL(errno != ENOENT);
> > +
> > +       /* replace 1st from the top program */
> > +       attach_opts.replace_prog_fd = allow_prog[0];
> > +       if (CHECK(bpf_prog_attach_xattr(allow_prog[6], cg1,
> > +                                       BPF_CGROUP_INET_EGRESS, &attach_opts),
> > +                 "prog_replace", "errno=%d\n", errno))
> > +               goto err;
> > +
> > +       value = 0;
> > +       CHECK_FAIL(bpf_map_update_elem(map_fd, &key, &value, 0));
> > +       CHECK_FAIL(system(PING_CMD));
> > +       CHECK_FAIL(bpf_map_lookup_elem(map_fd, &key, &value));
> > +       CHECK_FAIL(value != 64 + 2 + 8 + 16);
> > +
> >         /* detach 3rd from bottom program and ping again */
> >         if (CHECK(!bpf_prog_detach2(0, cg3, BPF_CGROUP_INET_EGRESS),
> >                   "fail_prog_detach_from_cg3", "unexpected success\n"))
> > @@ -202,7 +249,7 @@ void test_cgroup_attach_multi(void)
> >         CHECK_FAIL(bpf_map_update_elem(map_fd, &key, &value, 0));
> >         CHECK_FAIL(system(PING_CMD));
> >         CHECK_FAIL(bpf_map_lookup_elem(map_fd, &key, &value));
> > -       CHECK_FAIL(value != 1 + 2 + 16);
> > +       CHECK_FAIL(value != 64 + 2 + 16);
> >
> >         /* detach 2nd from bottom program and ping again */
> >         if (CHECK(bpf_prog_detach2(-1, cg4, BPF_CGROUP_INET_EGRESS),
> > @@ -213,7 +260,7 @@ void test_cgroup_attach_multi(void)
> >         CHECK_FAIL(bpf_map_update_elem(map_fd, &key, &value, 0));
> >         CHECK_FAIL(system(PING_CMD));
> >         CHECK_FAIL(bpf_map_lookup_elem(map_fd, &key, &value));
> > -       CHECK_FAIL(value != 1 + 2 + 4);
> > +       CHECK_FAIL(value != 64 + 2 + 4);
> >
> >         prog_cnt = 4;
> >         CHECK_FAIL(bpf_prog_query(cg5, BPF_CGROUP_INET_EGRESS,
> > --
> > 2.17.1
> >

-- 
Andrey Ignatov




[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