From: Eduard Zingerman <eddyz87@gmail.com>
To: Yonghong Song <yonghong.song@linux.dev>, bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Andrii Nakryiko <andrii@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
kernel-team@fb.com
Subject: Re: [PATCH bpf-next 04/12] bpf: Track R2 of register-pair returns in precision backtracking
Date: Thu, 09 Jul 2026 17:31:15 -0700 [thread overview]
Message-ID: <3f321b452fb19417ac317da7e8e55cb26b9488ef.camel@gmail.com> (raw)
In-Reply-To: <20260708201000.2157684-1-yonghong.song@linux.dev>
On Wed, 2026-07-08 at 13:10 -0700, Yonghong Song wrote:
> A function returning a value larger than 8 bytes (a struct/union, or an
> __int128) uses R2 as a second return register alongside R0. Previous
> precision backtracking only treated R0 as a return register at a
> call/return boundary, so marking the second half of such a return precise
> would trip the "unexpected regs" checks in backtrack_insn() and reject a
> valid program with -EFAULT.
>
> Handle R2 like R0 in the three boundaries where a call defines the return
> registers:
>
> - static subprog exit (BPF_EXIT): R2 is a return register, not a leftover
> argument; clear it before the args check and propagate its precision
> into the callee.
> - global subprog call: a global subprog returning >8 bytes also sets R2;
> clear it before the args check.
> - kfunc call (BPF_CALL): a kfunc returning >8 bytes (model ret_size > 8)
> also sets R2; clear it like R0.
>
> Signed-off-by: Yonghong Song <yonghong.song@linux.dev>
> ---
Acked-by: Eduard Zingerman <eddyz87@gmail.com>
> diff --git a/kernel/bpf/backtrack.c b/kernel/bpf/backtrack.c
> index 2e4ae0ef0860..c46c2778bf60 100644
> --- a/kernel/bpf/backtrack.c
> +++ b/kernel/bpf/backtrack.c
> @@ -424,6 +424,8 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
> */
> verifier_bug_if(idx + 1 != subseq_idx, env,
> "extra insn from subprog");
> + if (bpf_ret_reg_pair(env, subprog))
> + bt_clear_reg(bt, BPF_REG_2);
Nit: please move this a few lines below, so that r0 and r2 are handled nearby.
> /* r1-r5 are invalidated after subprog call,
> * so for global func call it shouldn't be set
> * anymore
> @@ -507,6 +509,12 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
> return -ENOTSUPP;
> /* regular helper call sets R0 */
> bt_clear_reg(bt, BPF_REG_0);
> + /* On error the return is negative, R2 stays set, and the
> + * check below catches it as an unexpected register.
> + */
Nit: I don't understand the above comment (the code is fine). Maybe drop it altogether?
> + if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL &&
> + bpf_get_kfunc_ret_size(env->prog, insn->imm, insn->off) > 8)
> + bt_clear_reg(bt, BPF_REG_2);
> if (bt_reg_mask(bt) & BPF_REGMASK_ARGS) {
> /* if backtracking was looking for registers R1-R5
> * they should have been found already.
> @@ -521,7 +529,25 @@ static int backtrack_insn(struct bpf_verifier_env *env, int idx, int subseq_idx,
> return -EFAULT;
> }
> } else if (opcode == BPF_EXIT) {
> - bool r0_precise;
> + bool r0_precise, r2_precise = false;
> +
> + /* A subprog returning a value larger than 8 bytes (a
> + * struct/union or an __int128) uses R2 as a second
> + * return register alongside R0. When exiting such a
> + * subprog, R2 is a return register rather than a
> + * leftover argument, so handle it like R0 below.
> + */
Nit: the comment is too verbose.
> + if (subseq_idx - 1 >= 0 &&
> + bpf_pseudo_call(&env->prog->insnsi[subseq_idx - 1])) {
> + int call_idx = subseq_idx - 1;
> + int tgt = call_idx + env->prog->insnsi[call_idx].imm + 1;
> + int subprog = bpf_find_subprog(env, tgt);
> +
> + if (subprog >= 0 &&
> + bpf_ret_reg_pair(env, subprog) &&
> + bt_is_reg_set(bt, BPF_REG_2))
> + r2_precise = true;
> + }
>
> /* Backtracking to a nested function call, 'idx' is a part of
> * the inner frame 'subseq_idx' is a part of the outer frame.
[...]
next prev parent reply other threads:[~2026-07-10 0:31 UTC|newest]
Thread overview: 56+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-08 20:09 [PATCH bpf-next 00/12] bpf: Support 16-byte return values in the R0:R2 register pair Yonghong Song
2026-07-08 20:09 ` [PATCH bpf-next 01/12] bpf: Factor check_global_ret_scalar_reg() out of the global return check Yonghong Song
2026-07-08 20:09 ` [PATCH bpf-next 02/12] bpf: Add verifier support for 16-byte returns in R0:R2 Yonghong Song
2026-07-08 21:17 ` bot+bpf-ci
2026-07-09 16:40 ` Yonghong Song
2026-07-09 22:21 ` Eduard Zingerman
2026-07-10 4:57 ` Yonghong Song
2026-07-08 20:09 ` [PATCH bpf-next 03/12] bpf: Wire up JIT support for 16-byte kfunc returns Yonghong Song
2026-07-10 0:06 ` Eduard Zingerman
2026-07-08 20:10 ` [PATCH bpf-next 04/12] bpf: Track R2 of register-pair returns in precision backtracking Yonghong Song
2026-07-08 21:10 ` bot+bpf-ci
2026-07-09 16:41 ` Yonghong Song
2026-07-10 0:31 ` Eduard Zingerman [this message]
2026-07-08 20:10 ` [PATCH bpf-next 05/12] bpf: Account R2 of register-pair returns in live register analysis Yonghong Song
2026-07-08 21:10 ` bot+bpf-ci
2026-07-09 21:07 ` Eduard Zingerman
2026-07-10 5:06 ` Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 06/12] bpf: Force JIT for programs using the R0:R2 register pair Yonghong Song
2026-07-08 21:10 ` bot+bpf-ci
2026-07-09 3:15 ` Leon Hwang
2026-07-09 16:44 ` Yonghong Song
2026-07-09 20:30 ` Eduard Zingerman
2026-07-10 5:07 ` Yonghong Song
2026-07-09 22:27 ` Eduard Zingerman
2026-07-10 5:09 ` Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 07/12] bpf: Reject >8 byte return values on return-reading trampoline paths Yonghong Song
2026-07-09 3:16 ` Leon Hwang
2026-07-09 16:52 ` Yonghong Song
2026-07-10 2:01 ` Leon Hwang
2026-07-09 23:08 ` Eduard Zingerman
2026-07-10 2:02 ` Leon Hwang
2026-07-10 5:27 ` Yonghong Song
2026-07-10 5:12 ` Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 08/12] bpf: Enable 16-byte aggregate return types Yonghong Song
2026-07-08 20:28 ` sashiko-bot
2026-07-09 19:40 ` Yonghong Song
2026-07-10 0:45 ` Eduard Zingerman
2026-07-10 5:29 ` Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 09/12] selftests/bpf: Add C tests for 16-byte returns in R0:R2 Yonghong Song
2026-07-08 20:24 ` sashiko-bot
2026-07-09 19:51 ` Yonghong Song
2026-07-08 21:10 ` bot+bpf-ci
2026-07-09 19:54 ` Yonghong Song
2026-07-10 1:19 ` Eduard Zingerman
2026-07-10 5:32 ` Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 10/12] selftests/bpf: Add inline-asm and subprog tests for R0:R2 returns Yonghong Song
2026-07-08 20:28 ` sashiko-bot
2026-07-09 19:57 ` Yonghong Song
2026-07-10 1:38 ` Eduard Zingerman
2026-07-10 5:35 ` Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 11/12] selftests/bpf: Cover tracing on >8 and <=16 byte return targets Yonghong Song
2026-07-08 20:10 ` [PATCH bpf-next 12/12] Documentation/bpf: Document 16-byte kfunc return values in R0:R2 Yonghong Song
2026-07-10 0:56 ` [PATCH bpf-next 00/12] bpf: Support 16-byte return values in the R0:R2 register pair Eduard Zingerman
2026-07-10 6:00 ` Yonghong Song
2026-07-10 6:13 ` Eduard Zingerman
2026-07-10 15:18 ` 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=3f321b452fb19417ac317da7e8e55cb26b9488ef.camel@gmail.com \
--to=eddyz87@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=kernel-team@fb.com \
--cc=yonghong.song@linux.dev \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox