From nobody Tue Dec 16 09:30:02 2025 Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91B0621E0BE; Mon, 21 Apr 2025 21:48:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=10.30.226.201 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745272089; cv=none; b=ofEWriG0EEx2pTUEm5Emu6/oVMyxGGXeTey6npNXlnZM/sLeYZhnbklwcpFQcV+DM3oM/QqtcD3rn0ENQKuWwazZ/UhloZujwygWftTwVnxkbLaBxktv3OXQIDjhWzB5/2hr6/cK6yXAnoTJ/jQgyDr9qWFVWiFkia2Vh8jkW3c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1745272089; c=relaxed/simple; bh=w7qqIh17fSwCFSWXvO2PicQUXbzrbsGmg5JeXxLIKAY=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rmkfC0cG5+XoGbVnOA9KycRPvmSsCoeudWo/wESXucyI1qUts9I+ufmmIXFZwu1uGlm8ZZO4RkrjHAtj7CKehY1arrDYKzZkRl67FxmKVs0x9Fm9rlLNYU0dQdGDgkWwxiija+VV8FyQNHXvS9aVZhZKiYmMRZq9HsHl2VHLY3Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b=s7VECdYj; arc=none smtp.client-ip=10.30.226.201 Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=kernel.org header.i=@kernel.org header.b="s7VECdYj" Received: by smtp.kernel.org (Postfix) with ESMTPSA id 6B528C4CEE4; Mon, 21 Apr 2025 21:48:04 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1745272089; bh=w7qqIh17fSwCFSWXvO2PicQUXbzrbsGmg5JeXxLIKAY=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=s7VECdYj7kWyp3cAmNmvoXHdL+inrEdfGlNpyvwkzirgrLje6ufeILvXRok4+b24p hi7EmaEtFfQMuZBjEJvb9VwxvmLliYjo0epa0HbIUmvXtxJFSNIGEnqPRDWyxtvvX6 iZ15hlQX7ZkBvYzr1WcofbLuKKiL2vAI8uRhqC0kMIq4m9GYqp8nhH+Bys5F54WAx4 0AdEobcpPaUpTbLdC94+UmMUQIhLt8Xmc8FdHoaVTcOP72ngcl5rBos3mFM8Rys8nw 3WoWCOAT0NViSCSoeC2VLt6cS/JNb4dYHN18CqGW/lzJTEeNeYPoIq1qLCNLQHWNl4 OeLF7IBa07W5A== From: Jiri Olsa To: Oleg Nesterov , Peter Zijlstra , Andrii Nakryiko Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org, x86@kernel.org, Song Liu , Yonghong Song , John Fastabend , Hao Luo , Steven Rostedt , Masami Hiramatsu , Alan Maguire , David Laight , =?UTF-8?q?Thomas=20Wei=C3=9Fschuh?= , Ingo Molnar Subject: [PATCH perf/core 18/22] selftests/bpf: Add uprobe_regs_equal test Date: Mon, 21 Apr 2025 23:44:18 +0200 Message-ID: <20250421214423.393661-19-jolsa@kernel.org> X-Mailer: git-send-email 2.49.0 In-Reply-To: <20250421214423.393661-1-jolsa@kernel.org> References: <20250421214423.393661-1-jolsa@kernel.org> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Changing uretprobe_regs_trigger to allow the test for both uprobe and uretprobe and renaming it to uprobe_regs_equal. We check that both uprobe and uretprobe probes (bpf programs) see expected registers with few exceptions. Signed-off-by: Jiri Olsa --- .../selftests/bpf/prog_tests/uprobe_syscall.c | 58 ++++++++++++++----- .../selftests/bpf/progs/uprobe_syscall.c | 4 +- 2 files changed, 45 insertions(+), 17 deletions(-) diff --git a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c b/tool= s/testing/selftests/bpf/prog_tests/uprobe_syscall.c index f001986981ab..6d88c5b0f6aa 100644 --- a/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/prog_tests/uprobe_syscall.c @@ -18,15 +18,17 @@ =20 #pragma GCC diagnostic ignored "-Wattributes" =20 -__naked unsigned long uretprobe_regs_trigger(void) +__attribute__((aligned(16))) +__nocf_check __weak __naked unsigned long uprobe_regs_trigger(void) { asm volatile ( - "movq $0xdeadbeef, %rax\n" + ".byte 0x0f, 0x1f, 0x44, 0x00, 0x00 \n" + "movq $0xdeadbeef, %rax \n" "ret\n" ); } =20 -__naked void uretprobe_regs(struct pt_regs *before, struct pt_regs *after) +__naked void uprobe_regs(struct pt_regs *before, struct pt_regs *after) { asm volatile ( "movq %r15, 0(%rdi)\n" @@ -47,15 +49,17 @@ __naked void uretprobe_regs(struct pt_regs *before, str= uct pt_regs *after) "movq $0, 120(%rdi)\n" /* orig_rax */ "movq $0, 128(%rdi)\n" /* rip */ "movq $0, 136(%rdi)\n" /* cs */ + "pushq %rax\n" "pushf\n" "pop %rax\n" "movq %rax, 144(%rdi)\n" /* eflags */ + "pop %rax\n" "movq %rsp, 152(%rdi)\n" /* rsp */ "movq $0, 160(%rdi)\n" /* ss */ =20 /* save 2nd argument */ "pushq %rsi\n" - "call uretprobe_regs_trigger\n" + "call uprobe_regs_trigger\n" =20 /* save return value and load 2nd argument pointer to rax */ "pushq %rax\n" @@ -95,25 +99,37 @@ __naked void uretprobe_regs(struct pt_regs *before, str= uct pt_regs *after) ); } =20 -static void test_uretprobe_regs_equal(void) +static void test_uprobe_regs_equal(bool retprobe) { + LIBBPF_OPTS(bpf_uprobe_opts, opts, + .retprobe =3D retprobe, + ); struct uprobe_syscall *skel =3D NULL; struct pt_regs before =3D {}, after =3D {}; unsigned long *pb =3D (unsigned long *) &before; unsigned long *pa =3D (unsigned long *) &after; unsigned long *pp; + unsigned long offset; unsigned int i, cnt; - int err; + + offset =3D get_uprobe_offset(&uprobe_regs_trigger); + if (!ASSERT_GE(offset, 0, "get_uprobe_offset")) + return; =20 skel =3D uprobe_syscall__open_and_load(); if (!ASSERT_OK_PTR(skel, "uprobe_syscall__open_and_load")) goto cleanup; =20 - err =3D uprobe_syscall__attach(skel); - if (!ASSERT_OK(err, "uprobe_syscall__attach")) + skel->links.probe =3D bpf_program__attach_uprobe_opts(skel->progs.probe, + 0, "/proc/self/exe", offset, &opts); + if (!ASSERT_OK_PTR(skel->links.probe, "bpf_program__attach_uprobe_opts")) goto cleanup; =20 - uretprobe_regs(&before, &after); + /* make sure uprobe gets optimized */ + if (!retprobe) + uprobe_regs_trigger(); + + uprobe_regs(&before, &after); =20 pp =3D (unsigned long *) &skel->bss->regs; cnt =3D sizeof(before)/sizeof(*pb); @@ -122,7 +138,7 @@ static void test_uretprobe_regs_equal(void) unsigned int offset =3D i * sizeof(unsigned long); =20 /* - * Check register before and after uretprobe_regs_trigger call + * Check register before and after uprobe_regs_trigger call * that triggers the uretprobe. */ switch (offset) { @@ -136,7 +152,7 @@ static void test_uretprobe_regs_equal(void) =20 /* * Check register seen from bpf program and register after - * uretprobe_regs_trigger call + * uprobe_regs_trigger call (with rax exception, check below). */ switch (offset) { /* @@ -149,6 +165,15 @@ static void test_uretprobe_regs_equal(void) case offsetof(struct pt_regs, rsp): case offsetof(struct pt_regs, ss): break; + /* + * uprobe does not see return value in rax, it needs to see the + * original (before) rax value + */ + case offsetof(struct pt_regs, rax): + if (!retprobe) { + ASSERT_EQ(pp[i], pb[i], "uprobe rax prog-before value check"); + break; + } default: if (!ASSERT_EQ(pp[i], pa[i], "register prog-after value check")) fprintf(stdout, "failed register offset %u\n", offset); @@ -186,13 +211,13 @@ static void test_uretprobe_regs_change(void) unsigned long cnt =3D sizeof(before)/sizeof(*pb); unsigned int i, err, offset; =20 - offset =3D get_uprobe_offset(uretprobe_regs_trigger); + offset =3D get_uprobe_offset(uprobe_regs_trigger); =20 err =3D write_bpf_testmod_uprobe(offset); if (!ASSERT_OK(err, "register_uprobe")) return; =20 - uretprobe_regs(&before, &after); + uprobe_regs(&before, &after); =20 err =3D write_bpf_testmod_uprobe(0); if (!ASSERT_OK(err, "unregister_uprobe")) @@ -605,7 +630,8 @@ static void test_uretprobe_shadow_stack(void) /* Run all the tests with shadow stack in place. */ shstk_is_enabled =3D true; =20 - test_uretprobe_regs_equal(); + test_uprobe_regs_equal(false); + test_uprobe_regs_equal(true); test_uretprobe_regs_change(); test_uretprobe_syscall_call(); =20 @@ -728,7 +754,7 @@ static void test_uprobe_sigill(void) static void __test_uprobe_syscall(void) { if (test__start_subtest("uretprobe_regs_equal")) - test_uretprobe_regs_equal(); + test_uprobe_regs_equal(true); if (test__start_subtest("uretprobe_regs_change")) test_uretprobe_regs_change(); if (test__start_subtest("uretprobe_syscall_call")) @@ -747,6 +773,8 @@ static void __test_uprobe_syscall(void) test_uprobe_race(); if (test__start_subtest("uprobe_sigill")) test_uprobe_sigill(); + if (test__start_subtest("uprobe_regs_equal")) + test_uprobe_regs_equal(false); } #else static void __test_uprobe_syscall(void) diff --git a/tools/testing/selftests/bpf/progs/uprobe_syscall.c b/tools/tes= ting/selftests/bpf/progs/uprobe_syscall.c index 8a4fa6c7ef59..e08c31669e5a 100644 --- a/tools/testing/selftests/bpf/progs/uprobe_syscall.c +++ b/tools/testing/selftests/bpf/progs/uprobe_syscall.c @@ -7,8 +7,8 @@ struct pt_regs regs; =20 char _license[] SEC("license") =3D "GPL"; =20 -SEC("uretprobe//proc/self/exe:uretprobe_regs_trigger") -int uretprobe(struct pt_regs *ctx) +SEC("uprobe") +int probe(struct pt_regs *ctx) { __builtin_memcpy(®s, ctx, sizeof(regs)); return 0; --=20 2.49.0