[PATCH bpf-next v6 6/7] riscv, bpf: Mixing bpf2bpf and tailcalls
Pu Lehui
pulehui at huaweicloud.com
Fri Jul 17 00:37:43 PDT 2026
On 2026/7/10 17:43, Daniel Borkmann wrote:
> On 7/10/26 2:53 AM, Pu Lehui wrote:
>> On 2026/7/10 3:51, Björn Töpel wrote:
>>> On Thu, 9 Jul 2026 at 17:09, Pu Lehui <pulehui at huaweicloud.com> wrote:
>>>> 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 at huaweicloud.com> 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.
>>>
>>> Thanks for trying it out!
>>>
>>> Ok, so seems like we need a verifier fix pre-landing?
Hi Björn,
Just a quick note that the verifier fix we discussed has now landed in
bpf-next [0]. Looking forward to your feedback on v6 whenever you get a
chance. :)
[0]
https://lore.kernel.org/bpf/178424941139.1475787.18080893330670192934.git-patchwork-notify@kernel.org/
>>
>> make sense to me, will try it.
>
> Thanks, yes, please take a stab at crafting a verifier fix + BPF selftest
> and let us know if you are stuck somewhere.
More information about the linux-riscv
mailing list