diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2026-09-24 03:10:29 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-09-24 05:39:49 +0000 |
| commit | 373e3fd0bff0e276fd76c86c830cdb16a3457776 (patch) | |
| tree | 54b9505104fd261ab3aa3075a4082730b63e8413 /include/linux | |
| parent | fb1f5ac185b76e8e27c1d857dd8b1edc8c9e5a3d (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.h | 6 |
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, |
