On Thu, Jun 20, 2024 at 2:34 PM Daniel Borkmann <daniel@xxxxxxxxxxxxx> wrote: > > Add test coverage for reservations beyond the ring buffer size in order > to validate that bpf_ringbuf_reserve() rejects the request with NULL, all > other ring buffer tests keep passing as well: > > # ./vmtest.sh -- ./test_progs -t ringbuf > [...] > ./test_progs -t ringbuf > [ 1.165434] bpf_testmod: loading out-of-tree module taints kernel. > [ 1.165825] bpf_testmod: module verification failed: signature and/or required key missing - tainting kernel > [ 1.284001] tsc: Refined TSC clocksource calibration: 3407.982 MHz > [ 1.286871] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x311fc34e357, max_idle_ns: 440795379773 ns > [ 1.289555] clocksource: Switched to clocksource tsc > #274/1 ringbuf/ringbuf:OK > #274/2 ringbuf/ringbuf_n:OK > #274/3 ringbuf/ringbuf_map_key:OK > #274/4 ringbuf/ringbuf_write:OK > #274 ringbuf:OK > #275 ringbuf_multi:OK > [...] > > Signed-off-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx> > --- > tools/testing/selftests/bpf/Makefile | 2 +- > .../selftests/bpf/prog_tests/ringbuf.c | 46 +++++++++++++++++++ > .../selftests/bpf/progs/test_ringbuf_write.c | 42 +++++++++++++++++ > 3 files changed, 89 insertions(+), 1 deletion(-) > create mode 100644 tools/testing/selftests/bpf/progs/test_ringbuf_write.c > > diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile > index e0b3887b3d2d..dd49c1d23a60 100644 > --- a/tools/testing/selftests/bpf/Makefile > +++ b/tools/testing/selftests/bpf/Makefile > @@ -457,7 +457,7 @@ LINKED_SKELS := test_static_linked.skel.h linked_funcs.skel.h \ > LSKELS := fentry_test.c fexit_test.c fexit_sleep.c atomics.c \ > trace_printk.c trace_vprintk.c map_ptr_kern.c \ > core_kern.c core_kern_overflow.c test_ringbuf.c \ > - test_ringbuf_n.c test_ringbuf_map_key.c > + test_ringbuf_n.c test_ringbuf_map_key.c test_ringbuf_write.c > > # Generate both light skeleton and libbpf skeleton for these > LSKELS_EXTRA := test_ksyms_module.c test_ksyms_weak.c kfunc_call_test.c \ > diff --git a/tools/testing/selftests/bpf/prog_tests/ringbuf.c b/tools/testing/selftests/bpf/prog_tests/ringbuf.c > index 4c6f42dae409..3eddd5e9c10b 100644 > --- a/tools/testing/selftests/bpf/prog_tests/ringbuf.c > +++ b/tools/testing/selftests/bpf/prog_tests/ringbuf.c > @@ -12,9 +12,11 @@ > #include <sys/sysinfo.h> > #include <linux/perf_event.h> > #include <linux/ring_buffer.h> > + > #include "test_ringbuf.lskel.h" > #include "test_ringbuf_n.lskel.h" > #include "test_ringbuf_map_key.lskel.h" > +#include "test_ringbuf_write.lskel.h" > > #define EDONE 7777 > > @@ -84,6 +86,48 @@ static void *poll_thread(void *input) > return (void *)(long)ring_buffer__poll(ringbuf, timeout); > } > > +static void ringbuf_write_subtest(void) > +{ > + struct test_ringbuf_write_lskel *skel; > + int page_size = getpagesize(); > + size_t *mmap_ptr; > + int err, rb_fd; > + > + skel = test_ringbuf_write_lskel__open(); > + if (CHECK(!skel, "skel_open", "skeleton open failed\n")) > + return; > + > + skel->maps.ringbuf.max_entries = 0x4000; > + > + err = test_ringbuf_write_lskel__load(skel); > + if (CHECK(err != 0, "skel_load", "skeleton load failed\n")) here and above, let's not add CHECK(), let's stick to ASSERT_xxx() > + goto cleanup; > + > + rb_fd = skel->maps.ringbuf.map_fd; > + > + mmap_ptr = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, rb_fd, 0); > + ASSERT_OK_PTR(mmap_ptr, "rw_cons_pos"); > + *mmap_ptr = 0x3000; > + > + skel->bss->pid = getpid(); > + > + ringbuf = ring_buffer__new(skel->maps.ringbuf.map_fd, > + process_sample, NULL, NULL); > + if (CHECK(!ringbuf, "ringbuf_create", "failed to create ringbuf\n")) > + goto cleanup; > + > + err = test_ringbuf_write_lskel__attach(skel); > + if (CHECK(err, "skel_attach", "skeleton attachment failed: %d\n", err)) > + goto cleanup; > + > + trigger_samples(); > + ASSERT_GE(skel->bss->discarded, 1, "discarded"); > + ASSERT_EQ(skel->bss->passed, 0, "passed"); > +cleanup: > + ring_buffer__free(ringbuf); > + test_ringbuf_write_lskel__destroy(skel); > +} > + > static void ringbuf_subtest(void) > { > const size_t rec_sz = BPF_RINGBUF_HDR_SZ + sizeof(struct sample); > @@ -451,4 +495,6 @@ void test_ringbuf(void) > ringbuf_n_subtest(); > if (test__start_subtest("ringbuf_map_key")) > ringbuf_map_key_subtest(); > + if (test__start_subtest("ringbuf_write")) > + ringbuf_write_subtest(); > } > diff --git a/tools/testing/selftests/bpf/progs/test_ringbuf_write.c b/tools/testing/selftests/bpf/progs/test_ringbuf_write.c > new file mode 100644 > index 000000000000..c6c67238a7c8 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/test_ringbuf_write.c > @@ -0,0 +1,42 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/bpf.h> > +#include <bpf/bpf_helpers.h> > +#include "bpf_misc.h" > + > +char _license[] SEC("license") = "GPL"; > + > +struct { > + __uint(type, BPF_MAP_TYPE_RINGBUF); > +} ringbuf SEC(".maps"); > + > +long discarded, passed; > +int pid; > + > +SEC("fentry/" SYS_PREFIX "sys_getpgid") > +int test_ringbuf_write(void *ctx) > +{ > + int *foo, cur_pid = bpf_get_current_pid_tgid() >> 32; > + void *sample1, *sample2; > + > + if (cur_pid != pid) > + return 0; > + > + sample1 = bpf_ringbuf_reserve(&ringbuf, 0x3000, 0); > + if (!sample1) > + return 0; > + /* first one can pass */ > + sample2 = bpf_ringbuf_reserve(&ringbuf, 0x3000, 0); > + if (!sample2) { > + bpf_ringbuf_discard(sample1, 0); > + __sync_fetch_and_add(&discarded, 1); > + return 0; > + } > + /* second one must not */ > + __sync_fetch_and_add(&passed, 1); > + foo = sample2 + 4084; > + *foo = 256; > + bpf_ringbuf_discard(sample1, 0); > + bpf_ringbuf_discard(sample2, 0); > + return 0; > +} > -- > 2.43.0 > >