[PATCH v4 bpf-next 0/2] bpf: properly verify tail call behavior

Martin Teichmann
2025-11-06T10:52:57Z

Hi Eduard,

you are right, backtrack_insn() did not properly deal with tail calls.
I fixed that, and added your test, which now passes properly.

What my code does is to effectively treat (following your example):

foo(int *a):
tail call;
*a = 0;
return;

as

foo(int *a);
if (prog_map_has_entry) {
tail call;
return;
}
*a = 0;
return;

In bpf_insn_successors(), a BPF_EXIT is declared as can_jump=false and
can_fallthrough=false. This is how the return after tail call should be
treated. Let's go through the three lines: the if statement has two
successors, the jump and the fallthrough. The fallthrough is the tail call,
which has the return as its only successor, which in turn has no successor
as BPF_EXIT has no successor. So we are left with the jump successor of
the if statement, which is nothing else than the fallthrough of the entire
three lines. So if we go back to the original code, we have an effective
can_jump=false, can_fallthrough=true. This is the default for BPF_CALL in
bpf_insn_successors(), so no code change is needed.

Martin Teichmann (2):
bpf: properly verify tail call behavior
bpf: test the proper verification of tail calls

kernel/bpf/verifier.c | 31 +++++++++-
.../selftests/bpf/progs/verifier_live_stack.c | 60 +++++++++++++++++++
.../selftests/bpf/progs/verifier_sock.c | 39 +++++++++++-
.../bpf/progs/verifier_subprog_precision.c | 47 +++++++++++++++
4 files changed, 172 insertions(+), 5 deletions(-)

--
2.43.0