* [PATCH bpf-next v4 1/2] bpf: Allow terminal gotox instructions
@ 2026-09-02 17:14 Siddharth Chintamaneni
2026-09-02 17:14 ` [PATCH bpf-next v4 2/2] selftests/bpf: Test " Siddharth Chintamaneni
0 siblings, 1 reply; 3+ messages in thread
From: Siddharth Chintamaneni @ 2026-09-02 17:14 UTC (permalink / raw)
To: bpf
Cc: Siddharth Chintamaneni, Anton Protopopov, Alexei Starovoitov,
Daniel Borkmann, John Fastabend, Andrii Nakryiko,
Eduard Zingerman, Kumar Kartikeya Dwivedi, Martin KaFai Lau,
Song Liu, Yonghong Song, Jiri Olsa, Emil Tsalapatis,
Ihor Solodrai, Puranjay Mohan, rlmenge, hargar, apais
check_subprogs() treats gotox as a direct jump and validates its reserved
zero offset. When gotox is the final instruction, this produces a
synthetic successor one instruction past the end of the subprogram and
rejects an otherwise valid program.
Skip direct-offset validation for gotox and accept it as a
non-fallthrough terminal instruction. Its actual targets remain validated
from the instruction-array jump table during CFG construction.
Fixes: 493d9e0d6083 ("bpf, x86: add support for indirect jumps")
Signed-off-by: Siddharth Chintamaneni <sidchintamaneni@gmail.com>
Reviewed-by: Anton Protopopov <a.s.protopopov@gmail.com>
---
kernel/bpf/verifier.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 8f585ceb2cd5..483473df7746 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -3088,6 +3088,8 @@ static int check_subprogs(struct bpf_verifier_env *env)
subprog[cur_subprog].exit_idx = i;
goto next;
}
+ if (insn_is_gotox(&insn[i]))
+ goto next;
off = i + bpf_jmp_offset(&insn[i]) + 1;
if (off < subprog_start || off >= subprog_end) {
verbose(env, "jump out of range from insn %d to %d\n", i, off);
@@ -3107,7 +3109,8 @@ static int check_subprogs(struct bpf_verifier_env *env)
*/
if (code != (BPF_JMP | BPF_EXIT) &&
code != (BPF_JMP32 | BPF_JA) &&
- code != (BPF_JMP | BPF_JA)) {
+ code != (BPF_JMP | BPF_JA) &&
+ !insn_is_gotox(&insn[i])) {
verbose(env, "last insn is not an exit or jmp\n");
bpf_diag_program_structure(
env, i, "subprogram can fall through",
base-commit: d761934c9483ecde93fe99d8705282f716dfee50
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH bpf-next v4 2/2] selftests/bpf: Test terminal gotox instructions
2026-09-02 17:14 [PATCH bpf-next v4 1/2] bpf: Allow terminal gotox instructions Siddharth Chintamaneni
@ 2026-09-02 17:14 ` Siddharth Chintamaneni
2026-09-02 17:54 ` Anton Protopopov
0 siblings, 1 reply; 3+ messages in thread
From: Siddharth Chintamaneni @ 2026-09-02 17:14 UTC (permalink / raw)
To: bpf
Cc: Siddharth Chintamaneni, Alexei Starovoitov, Daniel Borkmann,
John Fastabend, Andrii Nakryiko, Eduard Zingerman,
Kumar Kartikeya Dwivedi, Martin KaFai Lau, Song Liu,
Yonghong Song, Jiri Olsa, Emil Tsalapatis, Ihor Solodrai,
Anton Protopopov, Puranjay Mohan, rlmenge, hargar, apais
Add tests that place gotox at the end of the main program and a
subprogram, with each jump-table target preceding the gotox instruction.
This tests gotox as a valid non-fallthrough terminal instruction.
Signed-off-by: Siddharth Chintamaneni <sidchintamaneni@gmail.com>
---
.../selftests/bpf/progs/verifier_gotox.c | 48 +++++++++++++++++++
1 file changed, 48 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_gotox.c b/tools/testing/selftests/bpf/progs/verifier_gotox.c
index 5b18c9a27717..0e27c2c79c57 100644
--- a/tools/testing/selftests/bpf/progs/verifier_gotox.c
+++ b/tools/testing/selftests/bpf/progs/verifier_gotox.c
@@ -47,6 +47,54 @@ DEFINE_SIMPLE_JUMP_TABLE_PROG(reserved_field_src_reg, BPF_REG_1, 0, 0, __fa
DEFINE_SIMPLE_JUMP_TABLE_PROG(reserved_field_non_zero_off, BPF_REG_0, 1, 0, __failure __msg("BPF_JA|BPF_X uses reserved fields"))
DEFINE_SIMPLE_JUMP_TABLE_PROG(reserved_field_non_zero_imm, BPF_REG_0, 0, 1, __failure __msg("BPF_JA|BPF_X uses reserved fields"))
+#define DEFINE_TERMINAL_GOTOX_PROG(NAME, BASE) \
+ __naked void NAME(void) \
+ { \
+ asm volatile (" \
+ .pushsection .jumptables,\"\",@progbits; \
+jt0_%=: \
+ .quad ret0_%= - " BASE "; \
+ .size jt0_%=, 8; \
+ .global jt0_%=; \
+ .popsection; \
+ \
+ r0 = jt0_%= ll; \
+ r0 = *(u64 *)(r0 + 0); \
+ goto end_%=; \
+ret0_%=: \
+ r0 = 0; \
+ exit; \
+end_%=: \
+ .8byte %[gotox_r0]; \
+" : \
+ : __imm_insn(gotox_r0, BPF_RAW_INSN(BPF_JMP | BPF_JA | BPF_X, \
+ BPF_REG_0, 0, 0, 0)) \
+ : __clobber_all); \
+ }
+
+SEC("socket")
+__success __retval(0)
+DEFINE_TERMINAL_GOTOX_PROG(jump_table_terminal_gotox, "socket")
+
+static __noinline __used
+DEFINE_TERMINAL_GOTOX_PROG(terminal_gotox_subprog1, ".text")
+
+static __noinline __used int terminal_gotox_subprog2(void)
+{
+ return 0;
+}
+
+SEC("socket")
+__success __retval(0)
+__naked void jump_table_terminal_gotox_subprog(void)
+{
+ asm volatile (" \
+ call terminal_gotox_subprog1; \
+ call terminal_gotox_subprog2; \
+ exit; \
+" ::: __clobber_all);
+}
+
/*
* Gotox is forbidden when there is no jump table loaded
* which points to the sub-function where the gotox is used
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next v4 2/2] selftests/bpf: Test terminal gotox instructions
2026-09-02 17:14 ` [PATCH bpf-next v4 2/2] selftests/bpf: Test " Siddharth Chintamaneni
@ 2026-09-02 17:54 ` Anton Protopopov
0 siblings, 0 replies; 3+ messages in thread
From: Anton Protopopov @ 2026-09-02 17:54 UTC (permalink / raw)
To: Siddharth Chintamaneni
Cc: bpf, Alexei Starovoitov, Daniel Borkmann, John Fastabend,
Andrii Nakryiko, Eduard Zingerman, Kumar Kartikeya Dwivedi,
Martin KaFai Lau, Song Liu, Yonghong Song, Jiri Olsa,
Emil Tsalapatis, Ihor Solodrai, Puranjay Mohan, rlmenge, hargar,
apais
On 26/09/02 05:14PM, Siddharth Chintamaneni wrote:
> Add tests that place gotox at the end of the main program and a
> subprogram, with each jump-table target preceding the gotox instruction.
> This tests gotox as a valid non-fallthrough terminal instruction.
>
> Signed-off-by: Siddharth Chintamaneni <sidchintamaneni@gmail.com>
> ---
> .../selftests/bpf/progs/verifier_gotox.c | 48 +++++++++++++++++++
> 1 file changed, 48 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/progs/verifier_gotox.c b/tools/testing/selftests/bpf/progs/verifier_gotox.c
> index 5b18c9a27717..0e27c2c79c57 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_gotox.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_gotox.c
> @@ -47,6 +47,54 @@ DEFINE_SIMPLE_JUMP_TABLE_PROG(reserved_field_src_reg, BPF_REG_1, 0, 0, __fa
> DEFINE_SIMPLE_JUMP_TABLE_PROG(reserved_field_non_zero_off, BPF_REG_0, 1, 0, __failure __msg("BPF_JA|BPF_X uses reserved fields"))
> DEFINE_SIMPLE_JUMP_TABLE_PROG(reserved_field_non_zero_imm, BPF_REG_0, 0, 1, __failure __msg("BPF_JA|BPF_X uses reserved fields"))
>
> +#define DEFINE_TERMINAL_GOTOX_PROG(NAME, BASE) \
> + __naked void NAME(void) \
> + { \
> + asm volatile (" \
> + .pushsection .jumptables,\"\",@progbits; \
> +jt0_%=: \
> + .quad ret0_%= - " BASE "; \
> + .size jt0_%=, 8; \
> + .global jt0_%=; \
> + .popsection; \
> + \
> + r0 = jt0_%= ll; \
> + r0 = *(u64 *)(r0 + 0); \
> + goto end_%=; \
> +ret0_%=: \
> + r0 = 0; \
> + exit; \
> +end_%=: \
> + .8byte %[gotox_r0]; \
> +" : \
> + : __imm_insn(gotox_r0, BPF_RAW_INSN(BPF_JMP | BPF_JA | BPF_X, \
> + BPF_REG_0, 0, 0, 0)) \
> + : __clobber_all); \
> + }
> +
> +SEC("socket")
> +__success __retval(0)
> +DEFINE_TERMINAL_GOTOX_PROG(jump_table_terminal_gotox, "socket")
> +
> +static __noinline __used
> +DEFINE_TERMINAL_GOTOX_PROG(terminal_gotox_subprog1, ".text")
> +
> +static __noinline __used int terminal_gotox_subprog2(void)
> +{
> + return 0;
> +}
TBH, I was thinking about
DEFINE_TERMINAL_GOTOX_PROG(terminal_gotox_subprog1, ".text")
DEFINE_TERMINAL_GOTOX_PROG(terminal_gotox_subprog2, ".text")
such that one shouldn't think in which order subprogs are added.
But your variant should work.
Reviewed-by: Anton Protopopov <a.s.protopopov@gmail.com>
> +SEC("socket")
> +__success __retval(0)
> +__naked void jump_table_terminal_gotox_subprog(void)
> +{
> + asm volatile (" \
> + call terminal_gotox_subprog1; \
> + call terminal_gotox_subprog2; \
> + exit; \
> +" ::: __clobber_all);
> +}
> +
> /*
> * Gotox is forbidden when there is no jump table loaded
> * which points to the sub-function where the gotox is used
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-09-02 17:44 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-02 17:14 [PATCH bpf-next v4 1/2] bpf: Allow terminal gotox instructions Siddharth Chintamaneni
2026-09-02 17:14 ` [PATCH bpf-next v4 2/2] selftests/bpf: Test " Siddharth Chintamaneni
2026-09-02 17:54 ` Anton Protopopov
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox