* [PATCH bpf v2 2/2] selftests/bpf: Add test for usdt probe with page-crossing nop10
2026-08-25 15:04 [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary Jiayuan Chen
@ 2026-08-25 15:04 ` Jiayuan Chen
2026-08-25 18:39 ` [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary Andrii Nakryiko
2026-08-25 22:08 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 4+ messages in thread
From: Jiayuan Chen @ 2026-08-25 15:04 UTC (permalink / raw)
To: bpf, jolsa
Cc: Jiayuan Chen, Andrii Nakryiko, Eduard Zingerman, Ihor Solodrai,
Alexei Starovoitov, Daniel Borkmann, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Emil Tsalapatis,
Shuah Khan, Jakub Sitnicki, Peter Zijlstra (Intel), Jiawei Zhao,
Ingo Molnar, linux-kernel, linux-kselftest
Add a USDT probe laid out so that its nop10 crosses a page boundary
and check that attaching to it succeeds and the probe fires. Without
the previous fix libbpf shifts the uprobe onto the nop10 and the
attach fails with -ENOTSUPP.
Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
---
tools/testing/selftests/bpf/prog_tests/usdt.c | 54 +++++++++++++++++++
tools/testing/selftests/bpf/usdt_2.c | 16 ++++++
2 files changed, 70 insertions(+)
diff --git a/tools/testing/selftests/bpf/prog_tests/usdt.c b/tools/testing/selftests/bpf/prog_tests/usdt.c
index 8004c9568ffa..eff1e57ab13c 100644
--- a/tools/testing/selftests/bpf/prog_tests/usdt.c
+++ b/tools/testing/selftests/bpf/prog_tests/usdt.c
@@ -250,6 +250,7 @@ static void subtest_basic_usdt(bool optimized)
#ifdef __x86_64__
extern void usdt_1(void);
extern void usdt_2(void);
+extern void usdt_2_cross_page(void);
extern void usdt_red_zone_trigger(void);
static unsigned char nop1[1] = { 0x90 };
@@ -342,6 +343,57 @@ static void subtest_optimized_attach(void)
test_usdt__destroy(skel);
}
+/*
+ * Test attachment to a USDT probe whose nop10 crosses a page boundary.
+ * The kernel can't optimize such nop10, so libbpf keeps the uprobe on
+ * the preceding 1-byte nop. Do not assume any particular placement
+ * here, though: however the probe ends up attached, the attachment
+ * must succeed and the probe must fire.
+ */
+static void subtest_optimized_attach_cross_page(void)
+{
+ long page_sz = sysconf(_SC_PAGESIZE);
+ struct test_usdt *skel;
+ __u8 *addr = NULL;
+ long i;
+
+ /* combo is placed up to a page of padding after the function start */
+ for (i = 0; i < 2 * page_sz; i++) {
+ if (!memcmp((void *)usdt_2_cross_page + i, nop1_nop10_combo, 11)) {
+ addr = (void *)usdt_2_cross_page + i;
+ break;
+ }
+ }
+ if (!ASSERT_OK_PTR(addr, "find_nop1_nop10_combo"))
+ return;
+
+ /* layout sanity check: the nop10 must cross the page boundary */
+ if (!ASSERT_GT((unsigned long)(addr + 1) % page_sz + 10, page_sz,
+ "nop10_crosses_page"))
+ return;
+
+ skel = test_usdt__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "test_usdt__open_and_load"))
+ return;
+
+ skel->bss->my_pid = getpid();
+
+ skel->links.usdt0 = bpf_program__attach_usdt(skel->progs.usdt0,
+ 0 /*self*/, "/proc/self/exe",
+ "optimized_attach",
+ "usdt_2_cross_page", NULL);
+ if (!ASSERT_OK_PTR(skel->links.usdt0, "bpf_program__attach_usdt"))
+ goto cleanup;
+
+ usdt_2_cross_page();
+ usdt_2_cross_page();
+
+ ASSERT_EQ(skel->bss->usdt0_called, 2, "usdt0_called");
+
+cleanup:
+ test_usdt__destroy(skel);
+}
+
/*
* Test that USDT arguments survive nop10 optimization in a function where
* the compiler places operands in the red zone.
@@ -660,6 +712,8 @@ void test_usdt(void)
subtest_basic_usdt(true);
if (test__start_subtest("optimized_attach"))
subtest_optimized_attach();
+ if (test__start_subtest("optimized_attach_cross_page"))
+ subtest_optimized_attach_cross_page();
if (test__start_subtest("optimized_red_zone"))
subtest_optimized_red_zone();
#endif
diff --git a/tools/testing/selftests/bpf/usdt_2.c b/tools/testing/selftests/bpf/usdt_2.c
index 5e38f8605b02..3b7024b9b08b 100644
--- a/tools/testing/selftests/bpf/usdt_2.c
+++ b/tools/testing/selftests/bpf/usdt_2.c
@@ -13,6 +13,22 @@ void usdt_2(void)
USDT(optimized_attach, usdt_2);
}
+/*
+ * Force the nop1,nop10 combo of the USDT probe to a spot where the nop10
+ * crosses a page boundary: .balign starts the padding exactly at a page
+ * start regardless of the compiler-generated prologue size, and the 4086
+ * one-byte nops put the nop1 at page offset 4086, so the following nop10
+ * occupies the last 9 bytes of that page and 1 byte of the next one.
+ * The kernel can't optimize such nop10, so libbpf must keep the uprobe
+ * on the 1-byte nop.
+ */
+__attribute__((noinline))
+void usdt_2_cross_page(void)
+{
+ asm volatile (".balign 4096, 0x90\n\t.skip 4086, 0x90");
+ USDT(optimized_attach, usdt_2_cross_page);
+}
+
static volatile unsigned long usdt_red_zone_arg1 = 0xDEADBEEF;
static volatile unsigned long usdt_red_zone_arg2 = 0xCAFEBABE;
static volatile unsigned long usdt_red_zone_arg3 = 0xFEEDFACE;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary
2026-08-25 15:04 [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary Jiayuan Chen
2026-08-25 15:04 ` [PATCH bpf v2 2/2] selftests/bpf: Add test for usdt probe with page-crossing nop10 Jiayuan Chen
@ 2026-08-25 18:39 ` Andrii Nakryiko
2026-08-25 22:08 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 4+ messages in thread
From: Andrii Nakryiko @ 2026-08-25 18:39 UTC (permalink / raw)
To: Jiayuan Chen
Cc: bpf, jolsa, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Emil Tsalapatis, Ihor Solodrai,
Shuah Khan, Jakub Sitnicki, Ingo Molnar, Jiawei Zhao,
Peter Zijlstra (Intel), linux-kernel, linux-kselftest
On Tue, Aug 25, 2026 at 8:05 AM Jiayuan Chen <jiayuan.chen@linux.dev> wrote:
>
> The kernel refuses to attach to a nop10 that crosses a page boundary,
> since it can't be atomically rewritten:
>
> /* can_optimize(), arch/x86/kernel/uprobes.c */
> /* We can't do cross page atomic writes yet. */
> return PAGE_SIZE - (vaddr & ~PAGE_MASK) >= OPT_INSN_SIZE;
>
> Whether the nop10 crosses a page is purely up to the binary layout, so
> this does happen in practice. libbpf doesn't check for it and blindly
> shifts the uprobe onto the nop10, and the attach then fails with
> -ENOTSUPP. Just keep the uprobe on the preceding 1-byte nop in that
> case, it works everywhere as a regular int3 uprobe.
>
> Fixes: ee2862439e5c ("libbpf: Change has_nop_combo to work on top of nop10")
> Signed-off-by: Jiayuan Chen <jiayuan.chen@linux.dev>
>
> ---
> v1 -> v2: move check into has_nop_combo.
> v1: https://lore.kernel.org/bpf/20260824092847.361683-1-jiayuan.chen@linux.dev/
> ---
> tools/lib/bpf/usdt.c | 4 ++++
> 1 file changed, 4 insertions(+)
>
> diff --git a/tools/lib/bpf/usdt.c b/tools/lib/bpf/usdt.c
> index 2e56e3ab5b6c..ee9d1b614883 100644
> --- a/tools/lib/bpf/usdt.c
> +++ b/tools/lib/bpf/usdt.c
> @@ -608,8 +608,12 @@ static bool has_nop_combo(int fd, long off)
> unsigned char nop_combo[11] = {
> 0x90, 0x66, 0x2e, 0x0f, 0x1f, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
> };
> + long page_sz = getpagesize();
> unsigned char buf[11];
>
> + /* the kernel can't attach to a nop10 that crosses a page boundary */
> + if ((off + 1) % page_sz + 10 > page_sz)
> + return false;
yeah, this works ok, applied this version, disregard request to unify
has_nop_combo() with man->has_uprobe_syscall check
> if (pread(fd, buf, 11, off) != 11)
> return false;
> return memcmp(buf, nop_combo, 11) == 0;
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary
2026-08-25 15:04 [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary Jiayuan Chen
2026-08-25 15:04 ` [PATCH bpf v2 2/2] selftests/bpf: Add test for usdt probe with page-crossing nop10 Jiayuan Chen
2026-08-25 18:39 ` [PATCH bpf v2 1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary Andrii Nakryiko
@ 2026-08-25 22:08 ` patchwork-bot+netdevbpf
2 siblings, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-25 22:08 UTC (permalink / raw)
To: Jiayuan Chen
Cc: bpf, jolsa, ast, daniel, andrii, eddyz87, memxor, martin.lau,
song, yonghong.song, emil, ihor.solodrai, shuah, jakub, mingo,
phoenix500526, peterz, linux-kernel, linux-kselftest
Hello:
This series was applied to bpf/bpf-next.git (master)
by Andrii Nakryiko <andrii@kernel.org>:
On Tue, 25 Aug 2026 23:04:33 +0800 you wrote:
> The kernel refuses to attach to a nop10 that crosses a page boundary,
> since it can't be atomically rewritten:
>
> /* can_optimize(), arch/x86/kernel/uprobes.c */
> /* We can't do cross page atomic writes yet. */
> return PAGE_SIZE - (vaddr & ~PAGE_MASK) >= OPT_INSN_SIZE;
>
> [...]
Here is the summary with links:
- [bpf,v2,1/2] libbpf: Fix usdt attach failure when nop10 crosses page boundary
https://git.kernel.org/bpf/bpf-next/c/8b94878b2572
- [bpf,v2,2/2] selftests/bpf: Add test for usdt probe with page-crossing nop10
https://git.kernel.org/bpf/bpf-next/c/1555de33018f
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 4+ messages in thread