summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorDaniel Borkmann <daniel@iogearbox.net>2026-09-25 19:52:34 +0200
committerAlexei Starovoitov <ast@kernel.org>2026-09-25 21:02:31 +0000
commitc48a91c049fd98fcde54880a24c51b9a05f7e185 (patch)
tree6447cb28fd35172a44d4e6d45c5cd4a3642f228a /kernel
parent19581372dd81f3337bb672a437e56050a3ea41cb (diff)
downloadlinux-c48a91c049fd98fcde54880a24c51b9a05f7e185.tar.gz
linux-c48a91c049fd98fcde54880a24c51b9a05f7e185.zip
bpf: Don't remove indirect jump targets in the nop removal pass
bpf_opt_remove_nops() drops every ja +0 and may_goto +0 unconditionally. A gotox target may itself be such a transparent nop: it is a verified entry of an insn array jump table that is reachable at run time through the indirect jump. bpf_insn_array_adjust_after_remove() marks it as INSN_DELETED instead, and bpf_insn_array_ready() skips INSN_DELETED entries, so the program loads with a hole in its jump table. The x86 JIT, for example, lowers gotox to a raw indirect jump, so executing that index jumps to the zeroed ips[] slot, that is, to address 0. Fix by keeping an indirect jump target in place. Fixes: 493d9e0d6083 ("bpf, x86: add support for indirect jumps") Reported-by: Sandipan Roy <saroy@redhat.com> Reported-by: James Burton <jamesburton@meta.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Anton Protopopov <a.s.protopopov@gmail.com> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://patch.msgid.link/20260925175244.1136329-8-daniel@iogearbox.net
Diffstat (limited to 'kernel')
-rw-r--r--kernel/bpf/fixups.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c
index adc254b1a646..d4e54fa42dae 100644
--- a/kernel/bpf/fixups.c
+++ b/kernel/bpf/fixups.c
@@ -727,6 +727,7 @@ int bpf_opt_remove_dead_code(struct bpf_verifier_env *env)
int bpf_opt_remove_nops(struct bpf_verifier_env *env)
{
+ struct bpf_insn_aux_data *aux = env->insn_aux_data;
struct bpf_insn *insn = env->prog->insnsi;
int insn_cnt = env->prog->len;
bool is_may_goto_0, is_ja;
@@ -738,6 +739,8 @@ int bpf_opt_remove_nops(struct bpf_verifier_env *env)
if (!is_may_goto_0 && !is_ja)
continue;
+ if (aux[i].indirect_target)
+ continue;
err = verifier_remove_insns(env, i, 1);
if (err)