Skip to content

Commit 9e7f74e

Browse files
olsajirimhiramat
authored andcommitted
selftests/bpf: Add uretprobe syscall call from user space test
Adding test to verify that when called from outside of the trampoline provided by kernel, the uretprobe syscall will cause calling process to receive SIGILL signal and the attached bpf program is not executed. Link: https://lore.kernel.org/all/[email protected]/ Acked-by: Andrii Nakryiko <[email protected]> Reviewed-by: Masami Hiramatsu (Google) <[email protected]> Signed-off-by: Jiri Olsa <[email protected]> Signed-off-by: Masami Hiramatsu (Google) <[email protected]>
1 parent f42a58f commit 9e7f74e

File tree

2 files changed

+112
-0
lines changed

2 files changed

+112
-0
lines changed

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

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,10 @@
77
#include <unistd.h>
88
#include <asm/ptrace.h>
99
#include <linux/compiler.h>
10+
#include <linux/stringify.h>
11+
#include <sys/wait.h>
1012
#include "uprobe_syscall.skel.h"
13+
#include "uprobe_syscall_executed.skel.h"
1114

1215
__naked unsigned long uretprobe_regs_trigger(void)
1316
{
@@ -209,6 +212,91 @@ static void test_uretprobe_regs_change(void)
209212
}
210213
}
211214

215+
#ifndef __NR_uretprobe
216+
#define __NR_uretprobe 463
217+
#endif
218+
219+
__naked unsigned long uretprobe_syscall_call_1(void)
220+
{
221+
/*
222+
* Pretend we are uretprobe trampoline to trigger the return
223+
* probe invocation in order to verify we get SIGILL.
224+
*/
225+
asm volatile (
226+
"pushq %rax\n"
227+
"pushq %rcx\n"
228+
"pushq %r11\n"
229+
"movq $" __stringify(__NR_uretprobe) ", %rax\n"
230+
"syscall\n"
231+
"popq %r11\n"
232+
"popq %rcx\n"
233+
"retq\n"
234+
);
235+
}
236+
237+
__naked unsigned long uretprobe_syscall_call(void)
238+
{
239+
asm volatile (
240+
"call uretprobe_syscall_call_1\n"
241+
"retq\n"
242+
);
243+
}
244+
245+
static void test_uretprobe_syscall_call(void)
246+
{
247+
LIBBPF_OPTS(bpf_uprobe_multi_opts, opts,
248+
.retprobe = true,
249+
);
250+
struct uprobe_syscall_executed *skel;
251+
int pid, status, err, go[2], c;
252+
253+
if (ASSERT_OK(pipe(go), "pipe"))
254+
return;
255+
256+
skel = uprobe_syscall_executed__open_and_load();
257+
if (!ASSERT_OK_PTR(skel, "uprobe_syscall_executed__open_and_load"))
258+
goto cleanup;
259+
260+
pid = fork();
261+
if (!ASSERT_GE(pid, 0, "fork"))
262+
goto cleanup;
263+
264+
/* child */
265+
if (pid == 0) {
266+
close(go[1]);
267+
268+
/* wait for parent's kick */
269+
err = read(go[0], &c, 1);
270+
if (err != 1)
271+
exit(-1);
272+
273+
uretprobe_syscall_call();
274+
_exit(0);
275+
}
276+
277+
skel->links.test = bpf_program__attach_uprobe_multi(skel->progs.test, pid,
278+
"/proc/self/exe",
279+
"uretprobe_syscall_call", &opts);
280+
if (!ASSERT_OK_PTR(skel->links.test, "bpf_program__attach_uprobe_multi"))
281+
goto cleanup;
282+
283+
/* kick the child */
284+
write(go[1], &c, 1);
285+
err = waitpid(pid, &status, 0);
286+
ASSERT_EQ(err, pid, "waitpid");
287+
288+
/* verify the child got killed with SIGILL */
289+
ASSERT_EQ(WIFSIGNALED(status), 1, "WIFSIGNALED");
290+
ASSERT_EQ(WTERMSIG(status), SIGILL, "WTERMSIG");
291+
292+
/* verify the uretprobe program wasn't called */
293+
ASSERT_EQ(skel->bss->executed, 0, "executed");
294+
295+
cleanup:
296+
uprobe_syscall_executed__destroy(skel);
297+
close(go[1]);
298+
close(go[0]);
299+
}
212300
#else
213301
static void test_uretprobe_regs_equal(void)
214302
{
@@ -219,6 +307,11 @@ static void test_uretprobe_regs_change(void)
219307
{
220308
test__skip();
221309
}
310+
311+
static void test_uretprobe_syscall_call(void)
312+
{
313+
test__skip();
314+
}
222315
#endif
223316

224317
void test_uprobe_syscall(void)
@@ -227,4 +320,6 @@ void test_uprobe_syscall(void)
227320
test_uretprobe_regs_equal();
228321
if (test__start_subtest("uretprobe_regs_change"))
229322
test_uretprobe_regs_change();
323+
if (test__start_subtest("uretprobe_syscall_call"))
324+
test_uretprobe_syscall_call();
230325
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include "vmlinux.h"
3+
#include <bpf/bpf_helpers.h>
4+
#include <string.h>
5+
6+
struct pt_regs regs;
7+
8+
char _license[] SEC("license") = "GPL";
9+
10+
int executed = 0;
11+
12+
SEC("uretprobe.multi")
13+
int test(struct pt_regs *regs)
14+
{
15+
executed = 1;
16+
return 0;
17+
}

0 commit comments

Comments
 (0)