Commit 4bd11e08 authored by Andrii Nakryiko's avatar Andrii Nakryiko Committed by Daniel Borkmann

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: default avatarAndrii Nakryiko <andrii@kernel.org>
Signed-off-by: default avatarDaniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20210815070609.987780-17-andrii@kernel.org
parent 5e3b8356
...@@ -2,14 +2,18 @@ ...@@ -2,14 +2,18 @@
#include <test_progs.h> #include <test_progs.h>
#include "test_attach_probe.skel.h" #include "test_attach_probe.skel.h"
/* this is how USDT semaphore is actually defined, except volatile modifier */
volatile unsigned short uprobe_ref_ctr __attribute__((unused)) __attribute((section(".probes")));
void test_attach_probe(void) void test_attach_probe(void)
{ {
DECLARE_LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
int duration = 0; int duration = 0;
struct bpf_link *kprobe_link, *kretprobe_link; struct bpf_link *kprobe_link, *kretprobe_link;
struct bpf_link *uprobe_link, *uretprobe_link; struct bpf_link *uprobe_link, *uretprobe_link;
struct test_attach_probe* skel; struct test_attach_probe* skel;
size_t uprobe_offset; size_t uprobe_offset;
ssize_t base_addr; ssize_t base_addr, ref_ctr_offset;
base_addr = get_base_addr(); base_addr = get_base_addr();
if (CHECK(base_addr < 0, "get_base_addr", if (CHECK(base_addr < 0, "get_base_addr",
...@@ -17,6 +21,10 @@ void test_attach_probe(void) ...@@ -17,6 +21,10 @@ void test_attach_probe(void)
return; return;
uprobe_offset = get_uprobe_offset(&get_base_addr, base_addr); uprobe_offset = get_uprobe_offset(&get_base_addr, base_addr);
ref_ctr_offset = get_rel_offset((uintptr_t)&uprobe_ref_ctr);
if (!ASSERT_GE(ref_ctr_offset, 0, "ref_ctr_offset"))
return;
skel = test_attach_probe__open_and_load(); skel = test_attach_probe__open_and_load();
if (CHECK(!skel, "skel_open", "failed to open skeleton\n")) if (CHECK(!skel, "skel_open", "failed to open skeleton\n"))
return; return;
...@@ -37,20 +45,28 @@ void test_attach_probe(void) ...@@ -37,20 +45,28 @@ void test_attach_probe(void)
goto cleanup; goto cleanup;
skel->links.handle_kretprobe = kretprobe_link; skel->links.handle_kretprobe = kretprobe_link;
uprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uprobe, ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_before");
false /* retprobe */,
0 /* self pid */, uprobe_opts.retprobe = false;
"/proc/self/exe", uprobe_opts.ref_ctr_offset = ref_ctr_offset;
uprobe_offset); uprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uprobe,
0 /* self pid */,
"/proc/self/exe",
uprobe_offset,
&uprobe_opts);
if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe")) if (!ASSERT_OK_PTR(uprobe_link, "attach_uprobe"))
goto cleanup; goto cleanup;
skel->links.handle_uprobe = uprobe_link; skel->links.handle_uprobe = uprobe_link;
uretprobe_link = bpf_program__attach_uprobe(skel->progs.handle_uretprobe, ASSERT_GT(uprobe_ref_ctr, 0, "uprobe_ref_ctr_after");
true /* retprobe */,
-1 /* any pid */, /* if uprobe uses ref_ctr, uretprobe has to use ref_ctr as well */
"/proc/self/exe", uprobe_opts.retprobe = true;
uprobe_offset); uprobe_opts.ref_ctr_offset = ref_ctr_offset;
uretprobe_link = bpf_program__attach_uprobe_opts(skel->progs.handle_uretprobe,
-1 /* any pid */,
"/proc/self/exe",
uprobe_offset, &uprobe_opts);
if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe")) if (!ASSERT_OK_PTR(uretprobe_link, "attach_uretprobe"))
goto cleanup; goto cleanup;
skel->links.handle_uretprobe = uretprobe_link; skel->links.handle_uretprobe = uretprobe_link;
...@@ -77,4 +93,5 @@ void test_attach_probe(void) ...@@ -77,4 +93,5 @@ void test_attach_probe(void)
cleanup: cleanup:
test_attach_probe__destroy(skel); test_attach_probe__destroy(skel);
ASSERT_EQ(uprobe_ref_ctr, 0, "uprobe_ref_ctr_cleanup");
} }
...@@ -202,3 +202,24 @@ ssize_t get_base_addr(void) ...@@ -202,3 +202,24 @@ ssize_t get_base_addr(void)
fclose(f); fclose(f);
return -EINVAL; return -EINVAL;
} }
ssize_t get_rel_offset(uintptr_t addr)
{
size_t start, end, offset;
char buf[256];
FILE *f;
f = fopen("/proc/self/maps", "r");
if (!f)
return -errno;
while (fscanf(f, "%zx-%zx %s %zx %*[^\n]\n", &start, &end, buf, &offset) == 4) {
if (addr >= start && addr < end) {
fclose(f);
return (size_t)addr - start + offset;
}
}
fclose(f);
return -EINVAL;
}
...@@ -20,5 +20,6 @@ void read_trace_pipe(void); ...@@ -20,5 +20,6 @@ void read_trace_pipe(void);
ssize_t get_uprobe_offset(const void *addr, ssize_t base); ssize_t get_uprobe_offset(const void *addr, ssize_t base);
ssize_t get_base_addr(void); ssize_t get_base_addr(void);
ssize_t get_rel_offset(uintptr_t addr);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment