summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorAlexei Starovoitov <ast@kernel.org>2026-09-24 03:10:29 +0000
committerAlexei Starovoitov <ast@kernel.org>2026-09-24 05:39:49 +0000
commit373e3fd0bff0e276fd76c86c830cdb16a3457776 (patch)
tree54b9505104fd261ab3aa3075a4082730b63e8413 /include/linux
parentfb1f5ac185b76e8e27c1d857dd8b1edc8c9e5a3d (diff)
bpf: Prepare static analysis passes for callx instruction
BPF_JMP | BPF_CALL | BPF_X (callx) will be an indirect call of static subprog with address in dst_reg. The passes that run before the main verifier pass don't know which subprog callx calls. Teach them to treat callx as a call with unknown callee: - const_fold: callx clobbers R0-R5 like any other call. Otherwise bpf_prune_dead_branches() could rewrite a live conditional jump. - live regs: callx uses R1-R5 and dst_reg, defines R0-R5. - stack liveness: func instances are keyed by (callsite, depth) and cannot describe a callsite with multiple callees. Don't create instances for callees of callx. If any callx argument is derived from fp mark stack of all frames as read at callx insn and keep slots of outer frames alive 'before' the callsite while the callee is verified. Same as for callbacks that are not known statically. The callee is analyzed as standalone instance. - backtracking: treat callx as a call of static subprog, same as BPF_PSEUDO_CALL. callx is still rejected as unknown opcode. No functional change. Signed-off-by: Alexei Starovoitov <ast@kernel.org> Acked-by: Eduard Zingerman <eddyz87@gmail.com> Link: https://patch.msgid.link/20260924031042.1690890-5-alexei.starovoitov@gmail.com
Diffstat (limited to 'include/linux')
-rw-r--r--include/linux/bpf_verifier.h6
1 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index 92f528c45605..6380c851ed24 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -1089,6 +1089,12 @@ static inline bool bpf_pseudo_kfunc_call(const struct bpf_insn *insn)
insn->src_reg == BPF_PSEUDO_KFUNC_CALL;
}
+/* callx: indirect call of a bpf subprog whose address is in insn->dst_reg */
+static inline bool bpf_is_callx(const struct bpf_insn *insn)
+{
+ return insn->code == (BPF_JMP | BPF_CALL | BPF_X);
+}
+
__printf(2, 0) void bpf_verifier_vlog(struct bpf_verifier_log *log,
const char *fmt, va_list args);
__printf(2, 3) void bpf_verifier_log_write(struct bpf_verifier_env *env,