Skip to content

Commit 3a805ae

Browse files
committed
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. Signed-off-by: Jiri Olsa <[email protected]>
1 parent 7c33ddc commit 3a805ae

File tree

2 files changed

+137
-1
lines changed

2 files changed

+137
-1
lines changed

tools/testing/selftests/bpf/prog_tests/uprobe.c

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
/* Copyright (c) 2023 Hengqi Chen */
33

44
#include <test_progs.h>
5+
#include <asm/ptrace.h>
56
#include "test_uprobe.skel.h"
67

78
static FILE *urand_spawn(int *pid)
@@ -33,7 +34,7 @@ static int urand_trigger(FILE **urand_pipe)
3334
return exit_code;
3435
}
3536

36-
void test_uprobe(void)
37+
static void test_uprobe_attach(void)
3738
{
3839
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
3940
struct test_uprobe *skel;
@@ -93,3 +94,114 @@ void test_uprobe(void)
9394
pclose(urand_pipe);
9495
test_uprobe__destroy(skel);
9596
}
97+
98+
#ifdef __x86_64__
99+
__naked __maybe_unused unsigned long uprobe_regs_change_trigger(void)
100+
{
101+
asm volatile (
102+
"ret\n"
103+
);
104+
}
105+
106+
static __naked void uprobe_regs_change(struct pt_regs *before, struct pt_regs *after)
107+
{
108+
asm volatile (
109+
"movq %r11, 48(%rdi)\n"
110+
"movq %r10, 56(%rdi)\n"
111+
"movq %r9, 64(%rdi)\n"
112+
"movq %r8, 72(%rdi)\n"
113+
"movq %rax, 80(%rdi)\n"
114+
"movq %rcx, 88(%rdi)\n"
115+
"movq %rdx, 96(%rdi)\n"
116+
"movq %rsi, 104(%rdi)\n"
117+
"movq %rdi, 112(%rdi)\n"
118+
119+
/* save 2nd argument */
120+
"pushq %rsi\n"
121+
"call uprobe_regs_change_trigger\n"
122+
123+
/* save return value and load 2nd argument pointer to rax */
124+
"pushq %rax\n"
125+
"movq 8(%rsp), %rax\n"
126+
127+
"movq %r11, 48(%rax)\n"
128+
"movq %r10, 56(%rax)\n"
129+
"movq %r9, 64(%rax)\n"
130+
"movq %r8, 72(%rax)\n"
131+
"movq %rcx, 88(%rax)\n"
132+
"movq %rdx, 96(%rax)\n"
133+
"movq %rsi, 104(%rax)\n"
134+
"movq %rdi, 112(%rax)\n"
135+
136+
/* restore return value and 2nd argument */
137+
"pop %rax\n"
138+
"pop %rsi\n"
139+
140+
"movq %rax, 80(%rsi)\n"
141+
"ret\n"
142+
);
143+
}
144+
145+
static void regs_common(void)
146+
{
147+
struct pt_regs before = {}, after = {}, expected = {
148+
.rax = 0xc0ffe,
149+
.rcx = 0xbad,
150+
.rdx = 0xdead,
151+
.r8 = 0x8,
152+
.r9 = 0x9,
153+
.r10 = 0x10,
154+
.r11 = 0x11,
155+
.rdi = 0x12,
156+
.rsi = 0x13,
157+
};
158+
LIBBPF_OPTS(bpf_uprobe_opts, uprobe_opts);
159+
struct test_uprobe *skel;
160+
161+
skel = test_uprobe__open_and_load();
162+
if (!ASSERT_OK_PTR(skel, "skel_open"))
163+
return;
164+
165+
skel->bss->my_pid = getpid();
166+
skel->bss->regs = expected;
167+
168+
uprobe_opts.func_name = "uprobe_regs_change_trigger";
169+
skel->links.test_regs_change = bpf_program__attach_uprobe_opts(skel->progs.test_regs_change,
170+
-1,
171+
"/proc/self/exe",
172+
0 /* offset */,
173+
&uprobe_opts);
174+
if (!ASSERT_OK_PTR(skel->links.test_regs_change, "bpf_program__attach_uprobe_opts"))
175+
goto cleanup;
176+
177+
uprobe_regs_change(&before, &after);
178+
179+
ASSERT_EQ(after.rax, expected.rax, "ax");
180+
ASSERT_EQ(after.rcx, expected.rcx, "cx");
181+
ASSERT_EQ(after.rdx, expected.rdx, "dx");
182+
ASSERT_EQ(after.r8, expected.r8, "r8");
183+
ASSERT_EQ(after.r9, expected.r9, "r9");
184+
ASSERT_EQ(after.r10, expected.r10, "r10");
185+
ASSERT_EQ(after.r11, expected.r11, "r11");
186+
ASSERT_EQ(after.rdi, expected.rdi, "rdi");
187+
ASSERT_EQ(after.rsi, expected.rsi, "rsi");
188+
189+
cleanup:
190+
test_uprobe__destroy(skel);
191+
}
192+
193+
static void test_uprobe_regs_change(void)
194+
{
195+
if (test__start_subtest("regs_change_common"))
196+
regs_common();
197+
}
198+
#else
199+
static void test_uprobe_regs_change(void) { }
200+
#endif
201+
202+
void test_uprobe(void)
203+
{
204+
if (test__start_subtest("attach"))
205+
test_uprobe_attach();
206+
test_uprobe_regs_change();
207+
}

tools/testing/selftests/bpf/progs/test_uprobe.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,27 @@ int BPF_UPROBE(test4)
5959
test4_result = 1;
6060
return 0;
6161
}
62+
63+
#if defined(__TARGET_ARCH_x86)
64+
struct pt_regs regs;
65+
66+
SEC("uprobe")
67+
int BPF_UPROBE(test_regs_change)
68+
{
69+
pid_t pid = bpf_get_current_pid_tgid() >> 32;
70+
71+
if (pid != my_pid)
72+
return 0;
73+
74+
ctx->ax = regs.ax;
75+
ctx->cx = regs.cx;
76+
ctx->dx = regs.dx;
77+
ctx->r8 = regs.r8;
78+
ctx->r9 = regs.r9;
79+
ctx->r10 = regs.r10;
80+
ctx->r11 = regs.r11;
81+
ctx->di = regs.di;
82+
ctx->si = regs.si;
83+
return 0;
84+
}
85+
#endif

0 commit comments

Comments
 (0)