Re: [PATCH bpf-next v6 6/7] riscv, bpf: Mixing bpf2bpf and tailcalls
From: Pu Lehui
Date: Thu Jul 09 2026 - 11:20:32 EST
On 2026/7/9 19:37, Björn Töpel wrote:
Sorry for the delay here -- the bot had me thinking a bit.
On Wed, 8 Jul 2026 at 10:54, Pu Lehui <pulehui@xxxxxxxxxxxxxxx> wrote:
...
This assumes a fixed number of instructions before the tailcall entry
point. When is_subprog is true, the rv_addi() instruction is not emitted,
which means the tailcall entry point moves forward by 4 bytes relative to
where RV_TAILCALL_OFFSET expects it to be.
The tailcall entry is used in emit_bpf_tail_call() when calculating the
jump target for the tail call. If RV_TAILCALL_OFFSET doesn't account for
the conditional emission, could this cause the wrong entry point to be
used when tail calling into subprograms?
This is not an issue, subprog can not be the tailcall callee.
Say, that we have an entry function that does bpf_for_each_map_array()
into a callback cb(). cb() is a subprogram, so no init of TCC. Now,
cb() calls another subprogram that does a tailcall.
The callback to cb() is coming from the kernel, so a6 could have been
clobbered, no? We're entering a subprogram coming from the C ABI. Now,
if the callback calls a subprog that's tail-call reachable, the TCC
can be garbage?
Sashiko reported the same issue yesterday. I verified that the verifier rejects cases where a tail call is invoked within a callback; specifically, while the callback's return value range is [0, 1], the simulation of the exit path in `check_helper_call` (handling the tail call helper) marks R0 as UNKNOWN, causing the verifier to reject it—so I didn't investigate further. However, I just verified that the verifier *does* accept the scenario where a callback calls a subprogram, and that subprogram subsequently calls a tail call. I believe this scenario ought to be rejected; perhaps some changes are needed in the verifier, otherwise tail calls on other architectures (like x86) would also be susceptible to infinite loop issues.
Björn