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 <[email protected]>
---
 .../selftests/bpf/prog_tests/uprobe_syscall.c | 88 +++++++++++++++++++
 1 file changed, 88 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c 
b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
index 739b0be13aa3..713b42d4f190 100644
--- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
+++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c
@@ -4,6 +4,8 @@
 
 #ifdef __x86_64__
 
+#define _GNU_SOURCE
+#include <sched.h>
 #include <unistd.h>
 #include <asm/ptrace.h>
 #include <linux/compiler.h>
@@ -936,6 +938,88 @@ 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, 0x66, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 
0x00\n" /* nop10 */
+               "ret\n"
+       );
+}
+
+static 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;
+       struct bpf_link *link = 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;
+
+       link = bpf_program__attach_uprobe_opts(skel->progs.test_uprobe,
+                               -1, "/proc/self/exe", offset, NULL);
+       if (!ASSERT_OK_PTR(link, "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"))
@@ -956,6 +1040,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"))
-- 
2.53.0


Reply via email to