mirror of
https://github.com/torvalds/linux.git
synced 2026-09-27 11:02:03 +02:00
selftests/bpf: Add tests for forked/cloned optimized uprobes
Adding tests for forked/cloned optimized uprobes and make sure the child can properly execute optimized probe for both fork (dups mm) and clone with CLONE_VM. 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> Reviewed-by: Jakub Sitnicki <jakub@cloudflare.com> Link: https://patch.msgid.link/20260703114917.238144-14-jolsa@kernel.org
This commit is contained in:
parent
eccf368562
commit
d7ebbae57d
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
#ifdef __x86_64__
|
||||
|
||||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
#include <unistd.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <linux/compiler.h>
|
||||
|
|
@ -13,6 +15,7 @@
|
|||
#include <sys/syscall.h>
|
||||
#include <sys/prctl.h>
|
||||
#include <asm/prctl.h>
|
||||
#include <stdnoreturn.h>
|
||||
#include "uprobe_syscall.skel.h"
|
||||
#include "uprobe_syscall_executed.skel.h"
|
||||
#include "bpf/libbpf_internal.h"
|
||||
|
|
@ -954,6 +957,87 @@ static void test_uprobe_error(void)
|
|||
ASSERT_EQ(errno, EPROTO, "errno");
|
||||
}
|
||||
|
||||
__attribute__((aligned(16)))
|
||||
__nocf_check __weak __naked void uprobe_fork_test(void)
|
||||
{
|
||||
asm volatile (
|
||||
".byte 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00\n" /* nop10 */
|
||||
"ret\n"
|
||||
);
|
||||
}
|
||||
|
||||
static noreturn int child_func(void *arg)
|
||||
{
|
||||
struct uprobe_syscall_executed *skel = arg;
|
||||
|
||||
/* Make sure the child's probe is still there and optimized.. */
|
||||
if (memcmp(uprobe_fork_test, lea_rsp, sizeof(lea_rsp)))
|
||||
_exit(1);
|
||||
|
||||
skel->bss->pid = getpid();
|
||||
|
||||
/* .. and it executes properly. */
|
||||
uprobe_fork_test();
|
||||
|
||||
if (skel->bss->executed != 3)
|
||||
_exit(2);
|
||||
|
||||
_exit(0);
|
||||
}
|
||||
|
||||
static void test_uprobe_fork_optimized(bool clone_vm)
|
||||
{
|
||||
struct uprobe_syscall_executed *skel = NULL;
|
||||
unsigned long offset;
|
||||
int pid, status, err;
|
||||
char stack[65535];
|
||||
|
||||
offset = get_uprobe_offset(&uprobe_fork_test);
|
||||
if (!ASSERT_GE(offset, 0, "get_uprobe_offset"))
|
||||
return;
|
||||
|
||||
skel = uprobe_syscall_executed__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "open_and_load"))
|
||||
goto cleanup;
|
||||
|
||||
skel->links.test_uprobe = bpf_program__attach_uprobe_opts(skel->progs.test_uprobe,
|
||||
-1, "/proc/self/exe", offset, NULL);
|
||||
if (!ASSERT_OK_PTR(skel->links.test_uprobe, "attach_uprobe"))
|
||||
goto cleanup;
|
||||
|
||||
skel->bss->pid = getpid();
|
||||
|
||||
/* Trigger optimization of uprobe in uprobe_fork_test. */
|
||||
uprobe_fork_test();
|
||||
uprobe_fork_test();
|
||||
|
||||
/* Make sure it got optimied. */
|
||||
if (!ASSERT_OK(memcmp(uprobe_fork_test, lea_rsp, sizeof(lea_rsp)), "optimized"))
|
||||
goto cleanup;
|
||||
|
||||
if (clone_vm) {
|
||||
pid = clone(child_func, stack + sizeof(stack), CLONE_VM|SIGCHLD, skel);
|
||||
if (!ASSERT_GT(pid, 0, "clone"))
|
||||
goto cleanup;
|
||||
} else {
|
||||
pid = fork();
|
||||
if (!ASSERT_GE(pid, 0, "fork"))
|
||||
goto cleanup;
|
||||
if (pid == 0)
|
||||
child_func(skel);
|
||||
}
|
||||
|
||||
/* Wait for the child and verify it exited properly with 0. */
|
||||
err = waitpid(pid, &status, 0);
|
||||
if (ASSERT_EQ(err, pid, "waitpid")) {
|
||||
ASSERT_EQ(WIFEXITED(status), 1, "child_exited");
|
||||
ASSERT_EQ(WEXITSTATUS(status), 0, "child_exit_code");
|
||||
}
|
||||
|
||||
cleanup:
|
||||
uprobe_syscall_executed__destroy(skel);
|
||||
}
|
||||
|
||||
static void __test_uprobe_syscall(void)
|
||||
{
|
||||
if (test__start_subtest("uretprobe_regs_equal"))
|
||||
|
|
@ -974,6 +1058,10 @@ static void __test_uprobe_syscall(void)
|
|||
test_uprobe_race();
|
||||
if (test__start_subtest("uprobe_red_zone"))
|
||||
test_uprobe_red_zone();
|
||||
if (test__start_subtest("uprobe_optimized_fork"))
|
||||
test_uprobe_fork_optimized(false);
|
||||
if (test__start_subtest("uprobe_optimized_clone_vm"))
|
||||
test_uprobe_fork_optimized(true);
|
||||
if (test__start_subtest("uprobe_error"))
|
||||
test_uprobe_error();
|
||||
if (test__start_subtest("uprobe_regs_equal"))
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user