selftests/bpf: Add reattach tests for uprobe syscall

Adding reattach tests for uprobe syscall tests to make sure
we can re-attach and optimize same uprobe multiple times.

Signed-off-by: Jiri Olsa <jolsa@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Link: https://patch.msgid.link/20260703114917.238144-12-jolsa@kernel.org
This commit is contained in:
Jiri Olsa 2026-07-03 13:49:15 +02:00 committed by Ingo Molnar
parent b2cf7c41e4
commit 28d57db3e8

View File

@ -404,6 +404,16 @@ static void *find_nop10(void *fn)
typedef void (__attribute__((nocf_check)) *trigger_t)(void);
static void check_attach_notrigger(struct uprobe_syscall_executed *skel,
void *addr, int executed)
{
unsigned char *op = addr;
/* Make sure bpf program was not executed. */
ASSERT_EQ(skel->bss->executed, executed, "executed");
ASSERT_EQ(*op, 0xcc, "int3");
}
static void *check_attach(struct uprobe_syscall_executed *skel, trigger_t trigger,
void *addr, int executed)
{
@ -430,23 +440,26 @@ static void *check_attach(struct uprobe_syscall_executed *skel, trigger_t trigge
return tramp;
}
static void check_detach(void *addr, void *tramp)
static bool check_detach(void *addr, void *tramp)
{
static const unsigned char nop10_prefix[] = { 0x66, 0x2e, 0x0f, 0x1f, 0x84 };
bool ok = true;
/* [uprobes_trampoline] stays after detach */
ASSERT_OK(find_uprobes_trampoline(tramp), "uprobes_trampoline");
ASSERT_OK(memcmp(addr, nop10_prefix, 5), "nop10_prefix");
ok &= ASSERT_OK(find_uprobes_trampoline(tramp), "uprobes_trampoline");
ok &= ASSERT_OK(memcmp(addr, nop10_prefix, 5), "nop10_prefix");
return ok;
}
static void check(struct uprobe_syscall_executed *skel, struct bpf_link *link,
trigger_t trigger, void *addr, int executed)
static void *check(struct uprobe_syscall_executed *skel, struct bpf_link *link,
trigger_t trigger, void *addr, int executed)
{
void *tramp;
tramp = check_attach(skel, trigger, addr, executed);
bpf_link__destroy(link);
check_detach(addr, tramp);
return tramp;
}
static void test_uprobe_legacy(void)
@ -457,6 +470,7 @@ static void test_uprobe_legacy(void)
);
struct bpf_link *link;
unsigned long offset;
void *tramp;
offset = get_uprobe_offset(&uprobe_test);
if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
@ -474,7 +488,30 @@ static void test_uprobe_legacy(void)
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts"))
goto cleanup;
check(skel, link, uprobe_test, uprobe_test, 2);
tramp = check(skel, link, uprobe_test, uprobe_test, 2);
/* reattach and detach without triggering optimization */
link = bpf_program__attach_uprobe_opts(skel->progs.test_uprobe,
0, "/proc/self/exe", offset, NULL);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts"))
goto cleanup;
check_attach_notrigger(skel, uprobe_test, 2);
bpf_link__destroy(link);
if (!check_detach(uprobe_test, tramp))
goto cleanup;
uprobe_test();
ASSERT_EQ(skel->bss->executed, 2, "executed_no_probe");
/* reattach with triggering optimization */
link = bpf_program__attach_uprobe_opts(skel->progs.test_uprobe,
0, "/proc/self/exe", offset, NULL);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_opts"))
goto cleanup;
check(skel, link, uprobe_test, uprobe_test, 4);
/* uretprobe */
skel->bss->executed = 0;
@ -496,6 +533,7 @@ static void test_uprobe_multi(void)
LIBBPF_OPTS(bpf_uprobe_multi_opts, opts);
struct bpf_link *link;
unsigned long offset;
void *tramp;
offset = get_uprobe_offset(&uprobe_test);
if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
@ -516,7 +554,30 @@ static void test_uprobe_multi(void)
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
goto cleanup;
check(skel, link, uprobe_test, uprobe_test, 2);
tramp = check(skel, link, uprobe_test, uprobe_test, 2);
/* reattach and detach without triggering optimization */
link = bpf_program__attach_uprobe_multi(skel->progs.test_uprobe_multi,
0, "/proc/self/exe", NULL, &opts);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
goto cleanup;
check_attach_notrigger(skel, uprobe_test, 2);
bpf_link__destroy(link);
if (!check_detach(uprobe_test, tramp))
goto cleanup;
uprobe_test();
ASSERT_EQ(skel->bss->executed, 2, "executed_no_probe");
/* reattach with triggering optimization */
link = bpf_program__attach_uprobe_multi(skel->progs.test_uprobe_multi,
0, "/proc/self/exe", NULL, &opts);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
goto cleanup;
check(skel, link, uprobe_test, uprobe_test, 4);
/* uretprobe.multi */
skel->bss->executed = 0;
@ -540,6 +601,7 @@ static void test_uprobe_session(void)
);
struct bpf_link *link;
unsigned long offset;
void *tramp;
offset = get_uprobe_offset(&uprobe_test);
if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
@ -559,7 +621,30 @@ static void test_uprobe_session(void)
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
goto cleanup;
check(skel, link, uprobe_test, uprobe_test, 4);
tramp = check(skel, link, uprobe_test, uprobe_test, 4);
/* reattach and detach without triggering optimization */
link = bpf_program__attach_uprobe_multi(skel->progs.test_uprobe_session,
0, "/proc/self/exe", NULL, &opts);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
goto cleanup;
check_attach_notrigger(skel, uprobe_test, 4);
bpf_link__destroy(link);
if (!check_detach(uprobe_test, tramp))
goto cleanup;
uprobe_test();
ASSERT_EQ(skel->bss->executed, 4, "executed_no_probe");
/* reattach with triggering optimization */
link = bpf_program__attach_uprobe_multi(skel->progs.test_uprobe_session,
0, "/proc/self/exe", NULL, &opts);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_uprobe_multi"))
goto cleanup;
check(skel, link, uprobe_test, uprobe_test, 8);
cleanup:
uprobe_syscall_executed__destroy(skel);
@ -569,7 +654,7 @@ static void test_uprobe_usdt(void)
{
struct uprobe_syscall_executed *skel;
struct bpf_link *link;
void *addr;
void *addr, *tramp;
errno = 0;
addr = find_nop10(usdt_test);
@ -588,7 +673,32 @@ static void test_uprobe_usdt(void)
if (!ASSERT_OK_PTR(link, "bpf_program__attach_usdt"))
goto cleanup;
check(skel, link, usdt_test, addr, 2);
tramp = check(skel, link, usdt_test, addr, 2);
/* reattach and detach without triggering optimization */
link = bpf_program__attach_usdt(skel->progs.test_usdt,
-1 /* all PIDs */, "/proc/self/exe",
"optimized_uprobe", "usdt", NULL);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_usdt"))
goto cleanup;
check_attach_notrigger(skel, addr, 2);
bpf_link__destroy(link);
if (!check_detach(addr, tramp))
goto cleanup;
usdt_test();
ASSERT_EQ(skel->bss->executed, 2, "executed_no_probe");
/* reattach with triggering optimization */
link = bpf_program__attach_usdt(skel->progs.test_usdt,
-1 /* all PIDs */, "/proc/self/exe",
"optimized_uprobe", "usdt", NULL);
if (!ASSERT_OK_PTR(link, "bpf_program__attach_usdt"))
goto cleanup;
check(skel, link, usdt_test, addr, 4);
cleanup:
uprobe_syscall_executed__destroy(skel);