Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add ref_ctr_offset selftests

Extend attach_probe selftests to specify ref_ctr_offset for uprobe/uretprobe
and validate that its value is incremented from zero.

Turns out that once uprobe is attached with ref_ctr_offset, uretprobe for the
same location/function *has* to use ref_ctr_offset as well, otherwise
perf_event_open() fails with -EINVAL. So this test uses ref_ctr_offset for
both uprobe and uretprobe, even though for the purpose of test uprobe would be
enough.

Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20210815070609.987780-17-andrii@kernel.org

authored by

Andrii Nakryiko and committed by
Daniel Borkmann
4bd11e08 5e3b8356

+50 -11
+28 -11
tools/testing/selftests/bpf/prog_tests/attach_probe.c
··· 2 2 #include <test_progs.h> 3 3 #include "test_attach_probe.skel.h" 4 4 5 + /* this is how USDT semaphore is actually defined, except volatile modifier */ 6 + volatile unsigned short uprobe_ref_ctr __attribute__((unused)) __attribute((section(".probes"))); 7 + 5 8 void test_attach_probe(void) 6 9 { 10 + DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts); 7 11 int duration = 0; 8 12 struct bpf_link *kprobe_link, *kretprobe_link; 9 13 struct bpf_link *uprobe_link, *uretprobe_link; 10 14 struct test_attach_probe* skel; 11 15 size_t uprobe_offset; 12 - ssize_t base_addr; 16 + ssize_t base_addr, ref_ctr_offset; 13 17 14 18 base_addr = get_base_addr(); 15 19 if (CHECK(base_addr < 0, "get_base_addr", 16 20 "failed to find base addr: %zd", base_addr)) 17 21 return; 18 22 uprobe_offset = get_uprobe_offset(&get_base_addr, base_addr); 23 + 24 + ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr); 25 + if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset")) 26 + return; 19 27 20 28 skel = test_attach_probe__open_and_load(); 21 29 if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) ··· 45 37 goto cleanup; 46 38 skel->links.handle_kretprobe = kretprobe_link; 47 39 48 - uprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uprobe, 49 - false /* retprobe */, 50 - 0 /* self pid */, 51 - "/proc/self/exe", 52 - uprobe_offset); 40 + ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before"); 41 + 42 + uprobe_opts.retprobe = false; 43 + uprobe_opts.ref_ctr_offset = ref_ctr_offset; 44 + uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe, 45 + 0 /* self pid */, 46 + "/proc/self/exe", 47 + uprobe_offset, 48 + &uprobe_opts); 53 49 if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe")) 54 50 goto cleanup; 55 51 skel->links.handle_uprobe = uprobe_link; 56 52 57 - uretprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uretprobe, 58 - true /* retprobe */, 59 - -1 /* any pid */, 60 - "/proc/self/exe", 61 - uprobe_offset); 53 + ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after"); 54 + 55 + /* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */ 56 + uprobe_opts.retprobe = true; 57 + uprobe_opts.ref_ctr_offset = ref_ctr_offset; 58 + uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe, 59 + -1 /* any pid */, 60 + "/proc/self/exe", 61 + uprobe_offset, &uprobe_opts); 62 62 if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe")) 63 63 goto cleanup; 64 64 skel->links.handle_uretprobe = uretprobe_link; ··· 93 77 94 78 cleanup: 95 79 test_attach_probe__destroy(skel); 80 + ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_cleanup"); 96 81 }
+21
tools/testing/selftests/bpf/trace_helpers.c
··· 202 202 fclose(f); 203 203 return -EINVAL; 204 204 } 205 + 206 + ssize_t get_rel_offset(uintptr_t addr) 207 + { 208 + size_t start, end, offset; 209 + char buf[256]; 210 + FILE *f; 211 + 212 + f = fopen("/proc/self/maps", "r"); 213 + if (!f) 214 + return -errno; 215 + 216 + while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &offset) == 4) { 217 + if (addr >= start && addr < end) { 218 + fclose(f); 219 + return (size_t)addr - start + offset; 220 + } 221 + } 222 + 223 + fclose(f); 224 + return -EINVAL; 225 + }
+1
tools/testing/selftests/bpf/trace_helpers.h
··· 20 20 21 21 ssize_t get_uprobe_offset(const void *addr, ssize_t base); 22 22 ssize_t get_base_addr(void); 23 + ssize_t get_rel_offset(uintptr_t addr); 23 24 24 25 #endif