* [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback
@ 2026-07-08 2:57 David Windsor
2026-07-08 2:57 ` [PATCH bpf 2/2] selftests/bpf: Add XDP dispatcher FineIBT regression test David Windsor
2026-07-08 3:30 ` [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback Leon Hwang
0 siblings, 2 replies; 5+ messages in thread
From: David Windsor @ 2026-07-08 2:57 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David S . Miller, Jakub Kicinski,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Shuah Khan, Peter Zijlstra, netdev, linux-kernel, linux-kselftest,
David Windsor
commit 4f9087f16651 ("x86/cfi,bpf: Fix BPF JIT call") updated
emit_cfi() to emit FineIBT preambles for JIT-compiled BPF programs, but
did not update emit_bpf_dispatcher(). When prog->bpf_func is not in the
dispatcher table (e.g. an XDP_REDIRECT target program in a CPUMAP or
DEVMAP, or BPF_PROG_TEST_RUN of an unattached prog), the dispatcher
still jumps directly to prog->bpf_func. Without a FineIBT caller
sequence, under FineIBT this raises #CP:
Missing ENDBR: __cfi_bpf_prog_..._xdp_dispatcher_unattached+0x10/0x10
------------[ cut here ]------------
kernel BUG at arch/x86/kernel/cet.c:133!
Oops: invalid opcode: 0000 [#1] SMP NOPTI
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
RIP: 0010:do_kernel_cp_fault+0x126/0x130
Call Trace:
<TASK>
exc_control_protection+0x46/0x80
asm_exc_control_protection+0x2b/0x30
RIP: 0010:__cfi_bpf_prog_..._xdp_dispatcher_unattached+0x10/0x10
bpf_prog_test_run+0xda/0x1b0
__sys_bpf+0x70b/0x990
__x64_sys_bpf+0x2d/0x50
x64_sys_call+0x1079/0x2d40
do_syscall_64+0x12a/0x3c0
entry_SYSCALL_64_after_hwframe+0x76/0x7e
</TASK>
To fix this, we precede the indirect jump in emit_bpf_dispatcher() with
the FineIBT caller sequence: load cfi_bpf_hash into %eax and subtract
cfi_get_offset() from the target so it enters the preamble's real ENDBR.
Only needed for CFI_FINEIBT.
Fixes: 4f9087f16651 ("x86/cfi,bpf: Fix BPF JIT call")
Cc: stable@vger.kernel.org
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
arch/x86/net/bpf_jit_comp.c | 9 +++++++++
1 file changed, 9 insertions(+)
diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index de7515ea1bea..1c8249d8ca3b 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -3740,6 +3740,15 @@ static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image,
if (err)
return err;
+ /* If running under FineIBT, enter the preamble so the following
+ * indirect jump lands on a real ENDBR instead of the poison.
+ */
+ if (cfi_mode == CFI_FINEIBT) {
+ EMIT1_off32(0xb8, cfi_bpf_hash); /* mov $cfi_bpf_hash, %eax */
+ EMIT1(add_1mod(0x48, BPF_REG_3)); /* sub rdx, cfi_get_offset() */
+ EMIT2_off32(0x81, add_1reg(0xE8, BPF_REG_3), cfi_get_offset());
+ }
+
emit_indirect_jump(&prog, BPF_REG_3 /* R3 -> rdx */, image + (prog - buf));
*pprog = prog;
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* [PATCH bpf 2/2] selftests/bpf: Add XDP dispatcher FineIBT regression test
2026-07-08 2:57 [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback David Windsor
@ 2026-07-08 2:57 ` David Windsor
2026-07-08 3:22 ` Leon Hwang
2026-07-08 3:30 ` [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback Leon Hwang
1 sibling, 1 reply; 5+ messages in thread
From: David Windsor @ 2026-07-08 2:57 UTC (permalink / raw)
To: bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David S . Miller, Jakub Kicinski,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Shuah Khan, Peter Zijlstra, netdev, linux-kernel, linux-kselftest,
David Windsor
Add a regression test for the x86 BPF dispatcher's indirect-jump fallback
under FineIBT.
This test can crash the kernel on an unfixed FineIBT build and so should
be run in a VM.
Signed-off-by: David Windsor <dwindsor@gmail.com>
---
.../bpf/prog_tests/xdp_dispatcher_fineibt.c | 47 +++++++++++++++++++
.../bpf/progs/xdp_dispatcher_fineibt.c | 18 +++++++
2 files changed, 65 insertions(+)
create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c
create mode 100644 tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c b/tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c
new file mode 100644
index 000000000000..2d3fc4034eb9
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c
@@ -0,0 +1,47 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 David Windsor */
+
+/*
+ * Regression test for the x86 BPF dispatcher's indirect-jump fallback
+ * under FineIBT.
+ *
+ * WARNING
+ * -------
+ * This test can crash the kernel, thus should be run in a VM.
+ */
+#include <uapi/linux/if_link.h>
+#include <test_progs.h>
+#include <network_helpers.h>
+#include "xdp_dispatcher_fineibt.skel.h"
+
+#define IFINDEX_LO 1
+
+void test_xdp_dispatcher_fineibt(void)
+{
+ struct xdp_dispatcher_fineibt *skel;
+ int err, attached_fd, unattached_fd;
+
+ LIBBPF_OPTS(bpf_test_run_opts, topts,
+ .data_in = &pkt_v4,
+ .data_size_in = sizeof(pkt_v4),
+ );
+
+ skel = xdp_dispatcher_fineibt__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
+ return;
+
+ attached_fd = bpf_program__fd(skel->progs.xdp_dispatcher_attached);
+ unattached_fd = bpf_program__fd(skel->progs.xdp_dispatcher_unattached);
+
+ err = bpf_xdp_attach(IFINDEX_LO, attached_fd, XDP_FLAGS_SKB_MODE, NULL);
+ if (!ASSERT_OK(err, "attach_prog"))
+ goto out;
+
+ err = bpf_prog_test_run_opts(unattached_fd, &topts);
+ ASSERT_OK(err, "unattached_test_run");
+ ASSERT_EQ(topts.retval, XDP_PASS, "unattached_retval");
+
+ bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
+out:
+ xdp_dispatcher_fineibt__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c b/tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c
new file mode 100644
index 000000000000..b49b84f01c8e
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2026 David Windsor */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+SEC("xdp")
+int xdp_dispatcher_attached(struct xdp_md *ctx)
+{
+ return XDP_PASS;
+}
+
+SEC("xdp")
+int xdp_dispatcher_unattached(struct xdp_md *ctx)
+{
+ return XDP_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
--
2.53.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH bpf 2/2] selftests/bpf: Add XDP dispatcher FineIBT regression test
2026-07-08 2:57 ` [PATCH bpf 2/2] selftests/bpf: Add XDP dispatcher FineIBT regression test David Windsor
@ 2026-07-08 3:22 ` Leon Hwang
0 siblings, 0 replies; 5+ messages in thread
From: Leon Hwang @ 2026-07-08 3:22 UTC (permalink / raw)
To: David Windsor, bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David S . Miller, Jakub Kicinski,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Shuah Khan, Peter Zijlstra, netdev, linux-kernel, linux-kselftest
On 8/7/26 10:57, David Windsor wrote:
> Add a regression test for the x86 BPF dispatcher's indirect-jump fallback
> under FineIBT.
>
> This test can crash the kernel on an unfixed FineIBT build and so should
> be run in a VM.
>
> Signed-off-by: David Windsor <dwindsor@gmail.com>
> ---
> .../bpf/prog_tests/xdp_dispatcher_fineibt.c | 47 +++++++++++++++++++
> .../bpf/progs/xdp_dispatcher_fineibt.c | 18 +++++++
> 2 files changed, 65 insertions(+)
> create mode 100644 tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c
> create mode 100644 tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c b/tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c
> new file mode 100644
> index 000000000000..2d3fc4034eb9
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/prog_tests/xdp_dispatcher_fineibt.c
> @@ -0,0 +1,47 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2026 David Windsor */
> +
> +/*
> + * Regression test for the x86 BPF dispatcher's indirect-jump fallback
> + * under FineIBT.
> + *
> + * WARNING
> + * -------
> + * This test can crash the kernel, thus should be run in a VM.
> + */
> +#include <uapi/linux/if_link.h>
> +#include <test_progs.h>
> +#include <network_helpers.h>
> +#include "xdp_dispatcher_fineibt.skel.h"
> +
> +#define IFINDEX_LO 1
> +
> +void test_xdp_dispatcher_fineibt(void)
> +{
> + struct xdp_dispatcher_fineibt *skel;
> + int err, attached_fd, unattached_fd;
> +
> + LIBBPF_OPTS(bpf_test_run_opts, topts,
> + .data_in = &pkt_v4,
> + .data_size_in = sizeof(pkt_v4),
> + );
> +
> + skel = xdp_dispatcher_fineibt__open_and_load();
> + if (!ASSERT_OK_PTR(skel, "skel_open_and_load"))
> + return;
> +
> + attached_fd = bpf_program__fd(skel->progs.xdp_dispatcher_attached);
> + unattached_fd = bpf_program__fd(skel->progs.xdp_dispatcher_unattached);
> +
> + err = bpf_xdp_attach(IFINDEX_LO, attached_fd, XDP_FLAGS_SKB_MODE, NULL);
> + if (!ASSERT_OK(err, "attach_prog"))
> + goto out;
> +
> + err = bpf_prog_test_run_opts(unattached_fd, &topts);
> + ASSERT_OK(err, "unattached_test_run");
> + ASSERT_EQ(topts.retval, XDP_PASS, "unattached_retval");
> +
> + bpf_xdp_detach(IFINDEX_LO, XDP_FLAGS_SKB_MODE, NULL);
> +out:
> + xdp_dispatcher_fineibt__destroy(skel);
> +}
> diff --git a/tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c b/tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c
> new file mode 100644
> index 000000000000..b49b84f01c8e
> --- /dev/null
> +++ b/tools/testing/selftests/bpf/progs/xdp_dispatcher_fineibt.c
> @@ -0,0 +1,18 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright (c) 2026 David Windsor */
> +#include <linux/bpf.h>
> +#include <bpf/bpf_helpers.h>
> +
> +SEC("xdp")
> +int xdp_dispatcher_attached(struct xdp_md *ctx)
> +{
> + return XDP_PASS;
> +}
> +
> +SEC("xdp")
> +int xdp_dispatcher_unattached(struct xdp_md *ctx)
> +{
> + return XDP_PASS;
> +}
> +
> +char _license[] SEC("license") = "GPL";
Instead of creating xdp_dispatcher_fineibt.c, better to reuse
xdp_dummy.c. Then, in xdp_dispatcher_fineibt.c, you can create two
xdp_dummy skels, one for attaching, one for running.
And, add the test to xdp_attach.c instead of new file
prog_tests/xdp_dispatcher_fineibt.c?
Thanks,
Leon
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback
2026-07-08 2:57 [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback David Windsor
2026-07-08 2:57 ` [PATCH bpf 2/2] selftests/bpf: Add XDP dispatcher FineIBT regression test David Windsor
@ 2026-07-08 3:30 ` Leon Hwang
2026-07-08 3:40 ` David Windsor
1 sibling, 1 reply; 5+ messages in thread
From: Leon Hwang @ 2026-07-08 3:30 UTC (permalink / raw)
To: David Windsor, bpf
Cc: Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David S . Miller, Jakub Kicinski,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Shuah Khan, Peter Zijlstra, netdev, linux-kernel, linux-kselftest
On 8/7/26 10:57, David Windsor wrote:
> commit 4f9087f16651 ("x86/cfi,bpf: Fix BPF JIT call") updated
> emit_cfi() to emit FineIBT preambles for JIT-compiled BPF programs, but
> did not update emit_bpf_dispatcher(). When prog->bpf_func is not in the
> dispatcher table (e.g. an XDP_REDIRECT target program in a CPUMAP or
> DEVMAP, or BPF_PROG_TEST_RUN of an unattached prog), the dispatcher
> still jumps directly to prog->bpf_func. Without a FineIBT caller
> sequence, under FineIBT this raises #CP:
>
> Missing ENDBR: __cfi_bpf_prog_..._xdp_dispatcher_unattached+0x10/0x10
> ------------[ cut here ]------------
> kernel BUG at arch/x86/kernel/cet.c:133!
> Oops: invalid opcode: 0000 [#1] SMP NOPTI
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.17.0-0-gb52ca86e094d-prebuilt.qemu.org 04/01/2014
> RIP: 0010:do_kernel_cp_fault+0x126/0x130
> Call Trace:
> <TASK>
> exc_control_protection+0x46/0x80
> asm_exc_control_protection+0x2b/0x30
> RIP: 0010:__cfi_bpf_prog_..._xdp_dispatcher_unattached+0x10/0x10
> bpf_prog_test_run+0xda/0x1b0
> __sys_bpf+0x70b/0x990
> __x64_sys_bpf+0x2d/0x50
> x64_sys_call+0x1079/0x2d40
> do_syscall_64+0x12a/0x3c0
> entry_SYSCALL_64_after_hwframe+0x76/0x7e
> </TASK>
>
> To fix this, we precede the indirect jump in emit_bpf_dispatcher() with
> the FineIBT caller sequence: load cfi_bpf_hash into %eax and subtract
> cfi_get_offset() from the target so it enters the preamble's real ENDBR.
> Only needed for CFI_FINEIBT.
>
> Fixes: 4f9087f16651 ("x86/cfi,bpf: Fix BPF JIT call")
> Cc: stable@vger.kernel.org
> Signed-off-by: David Windsor <dwindsor@gmail.com>
> ---
> arch/x86/net/bpf_jit_comp.c | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
> index de7515ea1bea..1c8249d8ca3b 100644
> --- a/arch/x86/net/bpf_jit_comp.c
> +++ b/arch/x86/net/bpf_jit_comp.c
> @@ -3740,6 +3740,15 @@ static int emit_bpf_dispatcher(u8 **pprog, int a, int b, s64 *progs, u8 *image,
> if (err)
> return err;
>
> + /* If running under FineIBT, enter the preamble so the following
> + * indirect jump lands on a real ENDBR instead of the poison.
> + */
Comment style: /* should stay at its own line.
> + if (cfi_mode == CFI_FINEIBT) {
> + EMIT1_off32(0xb8, cfi_bpf_hash); /* mov $cfi_bpf_hash, %eax */
> + EMIT1(add_1mod(0x48, BPF_REG_3)); /* sub rdx, cfi_get_offset() */
> + EMIT2_off32(0x81, add_1reg(0xE8, BPF_REG_3), cfi_get_offset());
> + }
Better to emit_cfi()?
Thanks,
Leon
> +
> emit_indirect_jump(&prog, BPF_REG_3 /* R3 -> rdx */, image + (prog - buf));
>
> *pprog = prog;
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback
2026-07-08 3:30 ` [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback Leon Hwang
@ 2026-07-08 3:40 ` David Windsor
0 siblings, 0 replies; 5+ messages in thread
From: David Windsor @ 2026-07-08 3:40 UTC (permalink / raw)
To: Leon Hwang
Cc: bpf, Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen, x86,
H . Peter Anvin, David S . Miller, Jakub Kicinski,
Jesper Dangaard Brouer, John Fastabend, Stanislav Fomichev,
Shuah Khan, Peter Zijlstra, netdev, linux-kernel, linux-kselftest
On Tue, Jul 7, 2026 at 11:30 PM Leon Hwang <leon.hwang@linux.dev> wrote:
>
> Comment style: /* should stay at its own line.
>
> > + if (cfi_mode == CFI_FINEIBT) {
> > + EMIT1_off32(0xb8, cfi_bpf_hash); /* mov $cfi_bpf_hash, %eax */
> > + EMIT1(add_1mod(0x48, BPF_REG_3)); /* sub rdx, cfi_get_offset() */
> > + EMIT2_off32(0x81, add_1reg(0xE8, BPF_REG_3), cfi_get_offset());
> > + }
>
>
> Better to emit_cfi()?
>
Yes, thanks. Will do this for v2.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-08 3:40 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-08 2:57 [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback David Windsor
2026-07-08 2:57 ` [PATCH bpf 2/2] selftests/bpf: Add XDP dispatcher FineIBT regression test David Windsor
2026-07-08 3:22 ` Leon Hwang
2026-07-08 3:30 ` [PATCH bpf 1/2] bpf, x86: Fix FineIBT #CP in BPF dispatcher's indirect-jump fallback Leon Hwang
2026-07-08 3:40 ` David Windsor
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox