Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branch 'bpf-verifier-correct-tail_call_reachable-for-bpf-prog'

Leon Hwang says:

====================
bpf, verifier: Correct tail_call_reachable for bpf prog

It's confusing to inspect 'prog->aux->tail_call_reachable' with drgn[0],
when bpf prog has tail call but 'tail_call_reachable' is false.

This patch corrects 'tail_call_reachable' when bpf prog has tail call.

Therefore, it's unnecessary to detect tail call in x86 jit. Let's remove
it.

Changes:
v1 -> v2:
* Address comment from Yonghong:
* Remove unnecessary tail call detection in x86 jit.
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
---

Links:
[0] https://github.com/osandov/drgn
====================

Link: https://lore.kernel.org/r/20240610124224.34673-1-hffilwlqm@gmail.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

+5 -10
+2 -9
arch/x86/net/bpf_jit_comp.c
··· 1234 1234 } 1235 1235 1236 1236 static void detect_reg_usage(struct bpf_insn *insn, int insn_cnt, 1237 - bool *regs_used, bool *tail_call_seen) 1237 + bool *regs_used) 1238 1238 { 1239 1239 int i; 1240 1240 1241 1241 for (i = 1; i <= insn_cnt; i++, insn++) { 1242 - if (insn->code == (BPF_JMP | BPF_TAIL_CALL)) 1243 - *tail_call_seen = true; 1244 1242 if (insn->dst_reg == BPF_REG_6 || insn->src_reg == BPF_REG_6) 1245 1243 regs_used[0] = true; 1246 1244 if (insn->dst_reg == BPF_REG_7 || insn->src_reg == BPF_REG_7) ··· 1322 1324 struct bpf_insn *insn = bpf_prog->insnsi; 1323 1325 bool callee_regs_used[4] = {}; 1324 1326 int insn_cnt = bpf_prog->len; 1325 - bool tail_call_seen = false; 1326 1327 bool seen_exit = false; 1327 1328 u8 temp[BPF_MAX_INSN_SIZE + BPF_INSN_SAFETY]; 1328 1329 u64 arena_vm_start, user_vm_start; ··· 1333 1336 arena_vm_start = bpf_arena_get_kern_vm_start(bpf_prog->aux->arena); 1334 1337 user_vm_start = bpf_arena_get_user_vm_start(bpf_prog->aux->arena); 1335 1338 1336 - detect_reg_usage(insn, insn_cnt, callee_regs_used, 1337 - &tail_call_seen); 1338 - 1339 - /* tail call's presence in current prog implies it is reachable */ 1340 - tail_call_reachable |= tail_call_seen; 1339 + detect_reg_usage(insn, insn_cnt, callee_regs_used); 1341 1340 1342 1341 emit_prologue(&prog, bpf_prog->aux->stack_depth, 1343 1342 bpf_prog_was_classic(bpf_prog), tail_call_reachable,
+3 -1
kernel/bpf/verifier.c
··· 2982 2982 2983 2983 if (code == (BPF_JMP | BPF_CALL) && 2984 2984 insn[i].src_reg == 0 && 2985 - insn[i].imm == BPF_FUNC_tail_call) 2985 + insn[i].imm == BPF_FUNC_tail_call) { 2986 2986 subprog[cur_subprog].has_tail_call = true; 2987 + subprog[cur_subprog].tail_call_reachable = true; 2988 + } 2987 2989 if (BPF_CLASS(code) == BPF_LD && 2988 2990 (BPF_MODE(code) == BPF_ABS || BPF_MODE(code) == BPF_IND)) 2989 2991 subprog[cur_subprog].has_ld_abs = true;