Re: [PATCH bpf-next v6 06/10] bpf: Add verifier support for 16-byte returns in R0:R2

Yonghong Song <[email protected]>
Newsgroups dev.linux.lists.sashiko-reviews,org.kernel.vger.bpf
Message-ID <[email protected]>

On 8/16/26 9:42 PM, [email protected] wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [Medium] The newly added support for kfuncs returning structs by value is mathematically unreachable.
> --
>
> --- Patch [6]: [PATCH bpf-next v6 06/10] bpf: Add verifier support for 16-byte returns in R0:R2 ---
> commit 438f13b526c411cf77d7536a3436a0cc4625dbe4
> Author: Yonghong Song <[email protected]>
>
> bpf: Add verifier support for 16-byte returns in R0:R2
>
> This patch adds BPF verifier support for handling 16-byte returns in the
> R0:R2 register pair, utilizing LLVM 23 capabilities. It models this
> register pair at calls to global/static subprograms and kfuncs, allowing
> kfuncs to return structs composed of scalars.
>
> Link: https://github.com/llvm/llvm-project/pull/190894
> Link: https://github.com/llvm/llvm-project/pull/206876
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
> [ ... ]
>
>> @@ -13967,10 +13997,25 @@ static int check_kfunc_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
>>   	}
>>   
>>   	if (btf_type_is_scalar(t)) {
>> -		mark_reg_unknown(env, regs, BPF_REG_0);
>> +		mark_kfunc_ret_regs(env, regs, t->size);
>>   		if (meta.btf == btf_vmlinux && (meta.func_id == special_kfunc_list[KF_bpf_res_spin_lock] ||
>>   		    meta.func_id == special_kfunc_list[KF_bpf_res_spin_lock_irqsave]))
>>   			__mark_reg_const_zero(env, &regs[BPF_REG_0]);
>> +	} else if (btf_type_is_struct(t)) {
> [Severity: Medium]
> Is this newly added code for kfunc struct returns actually reachable
> during program load?
>
> Looking at how kfuncs are processed earlier in the verifier,
> bpf_add_kfunc_call() calls btf_distill_func_proto(), which appears to
> still explicitly reject struct return types:
>
> kernel/bpf/btf.c:btf_distill_func_proto() {
>      ...
>      if (ret < 0 || btf_type_is_struct(t)) {
>          bpf_log(log,
>              "The function %s return type %s is unsupported.\n",
>              tname, btf_type_str(t));
>          return -EINVAL;
>      }
>      ...
> }
>
> Since btf_distill_func_proto() is called during program load before
> check_kfunc_call() is ever reached, won't any BPF program calling a
> struct-returning kfunc be unconditionally rejected, making this new
> branch dead code?

The next patch "bpf: Enable aggregate return types up to 16 bytes"
will enable to have successful prog load.

>
>> +		/*
>> +		 * The returned struct comes back as raw register bits modeled
>> +		 * as an unknown scalar, so it must contain only scalars:
>> +		 * otherwise a pointer field would be laundered into a scalar
>> +		 * and escape provenance and reference tracking.
>> +		 */
>> +		if (!__btf_type_is_scalar_struct(env, desc_btf, t, 0)) {
>> +			verbose(env,
>> +				"kernel function %s returns %s %s that is not composed of scalars\n",
>> +				func_name, btf_type_str(t),
>> +				btf_name_by_offset(desc_btf, t->name_off));
>> +			return -EINVAL;
>> +		}
>> +		mark_kfunc_ret_regs(env, regs, t->size);
>>   	} else if (btf_type_is_ptr(t)) {
>>   		ptr_type = btf_type_skip_modifiers(desc_btf, t->type, &ptr_type_id);
> [ ... ]
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.