mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 02:24:24 +02:00
selftests/bpf: Add uprobe context registers changes test
Adding test to check we can change common register values through uprobe program. It's x86_64 specific test. Acked-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Jiri Olsa <jolsa@kernel.org> Link: https://lore.kernel.org/r/20250916215301.664963-4-jolsa@kernel.org Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
parent
4363264111
commit
7f8a05c5d3
|
|
@ -2,6 +2,7 @@
|
|||
/* Copyright (c) 2023 Hengqi Chen */
|
||||
|
||||
#include <test_progs.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include "test_uprobe.skel.h"
|
||||
|
||||
static FILE *urand_spawn(int *pid)
|
||||
|
|
@ -33,7 +34,7 @@ static int urand_trigger(FILE **urand_pipe)
|
|||
return exit_code;
|
||||
}
|
||||
|
||||
void test_uprobe(void)
|
||||
static void test_uprobe_attach(void)
|
||||
{
|
||||
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
|
||||
struct test_uprobe *skel;
|
||||
|
|
@ -93,3 +94,114 @@ void test_uprobe(void)
|
|||
pclose(urand_pipe);
|
||||
test_uprobe__destroy(skel);
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
__naked __maybe_unused unsigned long uprobe_regs_change_trigger(void)
|
||||
{
|
||||
asm volatile (
|
||||
"ret\n"
|
||||
);
|
||||
}
|
||||
|
||||
static __naked void uprobe_regs_change(struct pt_regs *before, struct pt_regs *after)
|
||||
{
|
||||
asm volatile (
|
||||
"movq %r11, 48(%rdi)\n"
|
||||
"movq %r10, 56(%rdi)\n"
|
||||
"movq %r9, 64(%rdi)\n"
|
||||
"movq %r8, 72(%rdi)\n"
|
||||
"movq %rax, 80(%rdi)\n"
|
||||
"movq %rcx, 88(%rdi)\n"
|
||||
"movq %rdx, 96(%rdi)\n"
|
||||
"movq %rsi, 104(%rdi)\n"
|
||||
"movq %rdi, 112(%rdi)\n"
|
||||
|
||||
/* save 2nd argument */
|
||||
"pushq %rsi\n"
|
||||
"call uprobe_regs_change_trigger\n"
|
||||
|
||||
/* save return value and load 2nd argument pointer to rax */
|
||||
"pushq %rax\n"
|
||||
"movq 8(%rsp), %rax\n"
|
||||
|
||||
"movq %r11, 48(%rax)\n"
|
||||
"movq %r10, 56(%rax)\n"
|
||||
"movq %r9, 64(%rax)\n"
|
||||
"movq %r8, 72(%rax)\n"
|
||||
"movq %rcx, 88(%rax)\n"
|
||||
"movq %rdx, 96(%rax)\n"
|
||||
"movq %rsi, 104(%rax)\n"
|
||||
"movq %rdi, 112(%rax)\n"
|
||||
|
||||
/* restore return value and 2nd argument */
|
||||
"pop %rax\n"
|
||||
"pop %rsi\n"
|
||||
|
||||
"movq %rax, 80(%rsi)\n"
|
||||
"ret\n"
|
||||
);
|
||||
}
|
||||
|
||||
static void regs_common(void)
|
||||
{
|
||||
struct pt_regs before = {}, after = {}, expected = {
|
||||
.rax = 0xc0ffe,
|
||||
.rcx = 0xbad,
|
||||
.rdx = 0xdead,
|
||||
.r8 = 0x8,
|
||||
.r9 = 0x9,
|
||||
.r10 = 0x10,
|
||||
.r11 = 0x11,
|
||||
.rdi = 0x12,
|
||||
.rsi = 0x13,
|
||||
};
|
||||
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
|
||||
struct test_uprobe *skel;
|
||||
|
||||
skel = test_uprobe__open_and_load();
|
||||
if (!ASSERT_OK_PTR(skel, "skel_open"))
|
||||
return;
|
||||
|
||||
skel->bss->my_pid = getpid();
|
||||
skel->bss->regs = expected;
|
||||
|
||||
uprobe_opts.func_name = "uprobe_regs_change_trigger";
|
||||
skel->links.test_regs_change = bpf_program__attach_uprobe_opts(skel->progs.test_regs_change,
|
||||
-1,
|
||||
"/proc/self/exe",
|
||||
0 /* offset */,
|
||||
&uprobe_opts);
|
||||
if (!ASSERT_OK_PTR(skel->links.test_regs_change, "bpf_program__attach_uprobe_opts"))
|
||||
goto cleanup;
|
||||
|
||||
uprobe_regs_change(&before, &after);
|
||||
|
||||
ASSERT_EQ(after.rax, expected.rax, "ax");
|
||||
ASSERT_EQ(after.rcx, expected.rcx, "cx");
|
||||
ASSERT_EQ(after.rdx, expected.rdx, "dx");
|
||||
ASSERT_EQ(after.r8, expected.r8, "r8");
|
||||
ASSERT_EQ(after.r9, expected.r9, "r9");
|
||||
ASSERT_EQ(after.r10, expected.r10, "r10");
|
||||
ASSERT_EQ(after.r11, expected.r11, "r11");
|
||||
ASSERT_EQ(after.rdi, expected.rdi, "rdi");
|
||||
ASSERT_EQ(after.rsi, expected.rsi, "rsi");
|
||||
|
||||
cleanup:
|
||||
test_uprobe__destroy(skel);
|
||||
}
|
||||
|
||||
static void test_uprobe_regs_change(void)
|
||||
{
|
||||
if (test__start_subtest("regs_change_common"))
|
||||
regs_common();
|
||||
}
|
||||
#else
|
||||
static void test_uprobe_regs_change(void) { }
|
||||
#endif
|
||||
|
||||
void test_uprobe(void)
|
||||
{
|
||||
if (test__start_subtest("attach"))
|
||||
test_uprobe_attach();
|
||||
test_uprobe_regs_change();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,3 +59,27 @@ int BPF_UPROBE(test4)
|
|||
test4_result = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(__TARGET_ARCH_x86)
|
||||
struct pt_regs regs;
|
||||
|
||||
SEC("uprobe")
|
||||
int BPF_UPROBE(test_regs_change)
|
||||
{
|
||||
pid_t pid = bpf_get_current_pid_tgid() >> 32;
|
||||
|
||||
if (pid != my_pid)
|
||||
return 0;
|
||||
|
||||
ctx->ax = regs.ax;
|
||||
ctx->cx = regs.cx;
|
||||
ctx->dx = regs.dx;
|
||||
ctx->r8 = regs.r8;
|
||||
ctx->r9 = regs.r9;
|
||||
ctx->r10 = regs.r10;
|
||||
ctx->r11 = regs.r11;
|
||||
ctx->di = regs.di;
|
||||
ctx->si = regs.si;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user