From: Yonghong Song <yonghong.song@linux.dev>
To: bot+bpf-ci@kernel.org, bpf@vger.kernel.org
Cc: ast@kernel.org, andrii@kernel.org, daniel@iogearbox.net,
eddyz87@gmail.com, kernel-team@fb.com, martin.lau@kernel.org,
clm@meta.com, ihor.solodrai@linux.dev
Subject: Re: [PATCH bpf-next v7 07/10] bpf: Enable aggregate return types up to 16 bytes
Date: Wed, 19 Aug 2026 09:12:32 -0700 [thread overview]
Message-ID: <e39f49b4-6e5c-490d-a629-c13d95e33c6c@linux.dev> (raw)
In-Reply-To: <96066402806a298adc4f6c068695e3d79b3157cf141fd243a54413de855f1d16@mail.kernel.org>
On 8/18/26 11:50 PM, bot+bpf-ci@kernel.org wrote:
>> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
>> index 953d8191563a..004b06785521 100644
>> --- a/include/linux/bpf_verifier.h
>> +++ b/include/linux/bpf_verifier.h
>> @@ -1488,6 +1488,8 @@ int bpf_jmp_offset(struct bpf_insn *insn);
>> struct bpf_iarray *bpf_insn_successors(struct bpf_verifier_env *env, u32 idx);
>> void bpf_fmt_stack_mask(char *buf, ssize_t buf_sz, u64 stack_mask);
>> bool bpf_subprog_is_global(const struct bpf_verifier_env *env, int subprog);
>> +bool btf_type_is_scalar_struct(struct bpf_verifier_env *env, const struct btf *btf,
>> + const struct btf_type *t, int rec);
>>
>> int bpf_find_subprog(struct bpf_verifier_env *env, int off);
>> bool bpf_is_throw_kfunc(struct bpf_insn *insn);
> [ ... ]
>
>> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
>> index 5e9f6a487524..58b81c6f5288 100644
>> --- a/kernel/bpf/btf.c
>> +++ b/kernel/bpf/btf.c
> [ ... ]
>
>> @@ -7970,7 +7970,7 @@ static int btf_scan_type_tags(struct bpf_verifier_env *env,
>>
>> /* Check whether the type is a valid return type. */
>> static int btf_validate_return_type(struct bpf_verifier_env *env, struct btf *btf,
>> - const struct btf_type *t, int subprog)
>> + const struct btf_type *t, int subprog, bool is_global)
>> {
>> u32 tags = 0;
>> int err;
>> @@ -7993,6 +7993,19 @@ static int btf_validate_return_type(struct bpf_verifier_env *env, struct btf *bt
>> if (btf_type_is_void(t) || btf_type_is_int(t) || btf_is_any_enum(t))
>> return 0;
>>
>> + if (btf_type_is_struct(t) && t->size <= 16) {
>> + /*
>> + * A global function's caller models the return as an opaque
>> + * scalar pair, so it may only return scalars by value. A local
>> + * function is verified inline, so a pointer field stays tracked
>> + * and needs no such restriction.
>> + */
>> + bool local_func = subprog && !is_global;
>> +
>> + if (local_func || btf_type_is_scalar_struct(env, btf, t, 0))
>> + return 0;
>> + }
>> +
>> return -EOPNOTSUPP;
>> }
> Does this code reject enum64-valued fields in scalar structs?
>
> Nine lines above, btf_is_any_enum(t) accepts a bare BTF_KIND_ENUM64
> return value as a scalar. However, btf_type_is_scalar_struct() calls
> btf_type_is_scalar() (include/linux/btf.h:361), which only matches
> btf_type_is_int() or btf_type_is_enum(). The latter
> (include/linux/btf.h:286) covers BTF_KIND_ENUM only, while
> BTF_KIND_ENUM64 requires btf_is_any_enum() (include/linux/btf.h:291).
>
> This means a bare 'return enum64_t' passes the bare-scalar branch above,
> but 'return struct { enum64_t e; }' - a struct of one scalar - fails the
> scalar-struct test and gets rejected with -EOPNOTSUPP.
>
> The commit message describes 'a struct or union up to 8 bytes, returned
> in R0 alone', and the series documentation (7ba16e29a69f) says the
> aggregate 'must be composed only of scalars (recursively), where a scalar
> is an integer or an enum', so enum64 members appear to be intended.
>
> The same gap affects kfuncs: check_kfunc_call() gates struct returns
> on btf_type_is_scalar_struct() as well and logs 'returns %s %s that
> is not composed of scalars'.
>
> Could btf_type_is_scalar() be updated to include btf_is_any_enum(), or
> should these two call sites use a different helper?
It is rare that we have enum64 in a struct, so I would like keep this way.
>
>> @@ -8080,12 +8093,12 @@ int btf_prepare_func_args(struct bpf_verifier_env *env, int subprog)
>> return -EINVAL;
>> }
>>
>> - err = btf_validate_return_type(env, btf, t, subprog);
>> + err = btf_validate_return_type(env, btf, t, subprog, is_global);
>> if (err) {
>> if (is_global) {
>> bpf_log(log,
>> - "Global function %s() return value not void or scalar. "
>> - "Only those are supported.\n",
>> + "Global function %s() has unsupported return type. "
>> + "Only void, scalar, or a scalar-only struct/union up to 16 bytes is supported.\n",
>> tname);
>> }
>> return err;
> [ ... ]
>
>> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
>> index d79f0c069795..7a939dfa3797 100644
>> --- a/kernel/bpf/verifier.c
>> +++ b/kernel/bpf/verifier.c
> [ ... ]
>
>> diff --git a/tools/testing/selftests/bpf/progs/exceptions_fail.c b/tools/testing/selftests/bpf/progs/exceptions_fail.c
>> index ac44d60e5066..9708efb93683 100644
>> --- a/tools/testing/selftests/bpf/progs/exceptions_fail.c
>> +++ b/tools/testing/selftests/bpf/progs/exceptions_fail.c
>> @@ -60,7 +60,7 @@ __noinline int exception_cb_ok_arg_small(int a)
>>
>> SEC("?tc")
>> __exception_cb(exception_cb_bad_ret_type1)
>> -__failure __msg("Global function exception_cb_bad_ret_type1() return value not void or scalar.")
>> +__failure __msg("Only void, scalar, or a scalar-only struct/union up to 16 bytes is supported.")
>> int reject_exception_cb_type_1(struct __sk_buff *ctx)
>> {
>> bpf_throw(0);
> Does this updated expectation still pin the function being tested?
>
> The old assertion string included both the function name and the specific
> reason: 'Global function exception_cb_bad_ret_type1() return value not
> void or scalar.' The replacement now matches only the generic second
> sentence of the message, which contains no function name.
>
> This means the test now passes if the verifier logs an unsupported return
> type error for any global function in the object, not specifically
> exception_cb_bad_ret_type1().
>
> The new bpf_log() message at btf.c:8099-8102 still interpolates the name
> ('Global function %s() has unsupported return type'), so a more specific
> assertion form was available:
>
> __msg("Global function exception_cb_bad_ret_type1() has unsupported return type")
>
> The later selftest commit in this series (8b8a84ddcc3e, selftests/bpf: Add
> tests for aggregate return values) does keep the function name in its
> equivalent expectations.
>
> Could this test retain the function name in the assertion to avoid
> matching unrelated failures?
I think it is okay.
>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32221968339
next prev parent reply other threads:[~2026-08-19 16:12 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-19 5:52 [PATCH bpf-next v7 00/10] bpf: Support aggregate return values up to 16 bytes Yonghong Song
2026-08-19 5:52 ` [PATCH bpf-next v7 01/10] bpf: Factor check_global_ret_scalar_reg() out of the global return check Yonghong Song
2026-08-19 5:52 ` [PATCH bpf-next v7 02/10] bpf: Add helpers to describe the R0:R2 return register pair Yonghong Song
2026-08-19 6:17 ` sashiko-bot
2026-08-19 15:41 ` Yonghong Song
2026-08-19 15:50 ` Yonghong Song
2026-08-19 5:52 ` [PATCH bpf-next v7 03/10] bpf: Wire up JIT support for 16-byte kfunc returns Yonghong Song
2026-08-19 6:49 ` bot+bpf-ci
2026-08-19 15:52 ` Yonghong Song
2026-08-19 5:52 ` [PATCH bpf-next v7 04/10] bpf: Handle R2 as a return register in precision backtracking Yonghong Song
2026-08-19 6:03 ` sashiko-bot
2026-08-19 15:54 ` Yonghong Song
2026-08-19 5:53 ` [PATCH bpf-next v7 05/10] bpf: Account R2 of register-pair returns in live register analysis Yonghong Song
2026-08-19 6:20 ` sashiko-bot
2026-08-19 15:57 ` Yonghong Song
2026-08-19 6:32 ` bot+bpf-ci
2026-08-19 15:58 ` Yonghong Song
2026-08-19 5:53 ` [PATCH bpf-next v7 06/10] bpf: Add verifier support for 16-byte returns in R0:R2 Yonghong Song
2026-08-19 6:14 ` sashiko-bot
2026-08-19 16:01 ` Yonghong Song
2026-08-19 5:53 ` [PATCH bpf-next v7 07/10] bpf: Enable aggregate return types up to 16 bytes Yonghong Song
2026-08-19 6:13 ` sashiko-bot
2026-08-19 16:04 ` Yonghong Song
2026-08-19 6:50 ` bot+bpf-ci
2026-08-19 16:12 ` Yonghong Song [this message]
2026-08-19 5:53 ` [PATCH bpf-next v7 08/10] selftests/bpf: Add C tests for 16-byte returns in R0:R2 Yonghong Song
2026-08-19 6:49 ` bot+bpf-ci
2026-08-19 16:15 ` Yonghong Song
2026-08-19 5:53 ` [PATCH bpf-next v7 09/10] selftests/bpf: Add inline-asm and subprog tests for R0:R2 returns Yonghong Song
2026-08-19 5:53 ` [PATCH bpf-next v7 10/10] Documentation/bpf: Document up to 16-byte kfunc return values in R0:R2 Yonghong Song
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=e39f49b4-6e5c-490d-a629-c13d95e33c6c@linux.dev \
--to=yonghong.song@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bot+bpf-ci@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=clm@meta.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=ihor.solodrai@linux.dev \
--cc=kernel-team@fb.com \
--cc=martin.lau@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.