From: Mykyta Yatsenko <mykyta.yatsenko5@gmail.com>
To: Paul Chaignon <paul.chaignon@gmail.com>, bpf@vger.kernel.org
Cc: Alexei Starovoitov <ast@kernel.org>,
Daniel Borkmann <daniel@iogearbox.net>,
Andrii Nakryiko <andrii@kernel.org>,
Eduard Zingerman <eddyz87@gmail.com>,
Harishankar Vishwanathan <harishankar.vishwanathan@gmail.com>,
Shung-Hsi Yu <shung-hsi.yu@suse.com>,
Srinivas Narayana <srinivas.narayana@rutgers.edu>,
Santosh Nagarakatte <santosh.nagarakatte@rutgers.edu>
Subject: Re: [PATCH v2 bpf-next 2/6] bpf: Use bpf_verifier_env buffers for reg_set_min_max
Date: Mon, 23 Mar 2026 15:33:39 +0000 [thread overview]
Message-ID: <87o6kek1bg.fsf@gmail.com> (raw)
In-Reply-To: <9fdf9830803fe3a5c4059341c84a03836105f5bf.1774025082.git.paul.chaignon@gmail.com>
Paul Chaignon <paul.chaignon@gmail.com> writes:
> In a subsequent patch, the regs_refine_cond_op and reg_bounds_sync
> functions will be called in is_branch_taken instead of reg_set_min_max,
> to simulate each branch's outcome. Since they will run before we branch
> out, these two functions will need to work on temporary registers for
> the two branches.
>
> This refactoring patch prepares for that change, by introducing the
> temporary registers on bpf_verifier_env and using them in
> reg_set_min_max.
>
> This change also allows us to save one fake_reg slot as we don't need to
> allocate an additional temporary buffer in case of a BPF_K condition.
>
> Finally, you may notice that this patch removes the check for
> "false_reg1 == false_reg2" in reg_set_min_max. That check was introduced
> in commit d43ad9da8052 ("bpf: Skip bounds adjustment for conditional
> jumps on same scalar register") to avoid an invariant violation. Given
> that "env->false_reg1 == env->false_reg2" doesn't make sense and
> invariant violations are addressed in a subsequent commit, this patch
> just removes the check.
>
> Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
> Co-developed-by: Harishankar Vishwanathan <harishankar.vishwanathan@gmail.com>
> Signed-off-by: Harishankar Vishwanathan <harishankar.vishwanathan@gmail.com>
> Signed-off-by: Paul Chaignon <paul.chaignon@gmail.com>
> ---
> include/linux/bpf_verifier.h | 4 ++-
> kernel/bpf/verifier.c | 64 +++++++++++++-----------------------
> 2 files changed, 26 insertions(+), 42 deletions(-)
>
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index 090aa26d1c98..b129e0aaee20 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -837,7 +837,9 @@ struct bpf_verifier_env {
> u64 scratched_stack_slots;
> u64 prev_log_pos, prev_insn_print_pos;
> /* buffer used to temporary hold constants as scalar registers */
> - struct bpf_reg_state fake_reg[2];
> + struct bpf_reg_state fake_reg[1];
> + /* buffers used to save updated reg states while simulating branches */
> + struct bpf_reg_state true_reg1, true_reg2, false_reg1, false_reg2;
I can see Eduard suggested to store this in env to reduce stack usage by
the verifier. The rest of the refactoring looks like a correct
alignment. The only difference with the base version is removal of the
if (false_reg1 == false_reg2) condition, which is explained in the
commit message.
Acked-by: Mykyta Yatsenko <yatsenko@meta.com>
> /* buffer used to generate temporary string representations,
> * e.g., in reg_type_str() to generate reg_type string
> */
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index b638ab841c10..fbc29fb96a60 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -17184,10 +17184,6 @@ static void regs_refine_cond_op(struct bpf_reg_state *reg1, struct bpf_reg_state
> * but we don't support that right now.
> */
> static int reg_set_min_max(struct bpf_verifier_env *env,
> - struct bpf_reg_state *true_reg1,
> - struct bpf_reg_state *true_reg2,
> - struct bpf_reg_state *false_reg1,
> - struct bpf_reg_state *false_reg2,
> u8 opcode, bool is_jmp32)
> {
> int err;
> @@ -17196,30 +17192,23 @@ static int reg_set_min_max(struct bpf_verifier_env *env,
> * variable offset from the compare (unless they were a pointer into
> * the same object, but we don't bother with that).
> */
> - if (false_reg1->type != SCALAR_VALUE || false_reg2->type != SCALAR_VALUE)
> - return 0;
> -
> - /* We compute branch direction for same SCALAR_VALUE registers in
> - * is_scalar_branch_taken(). For unknown branch directions (e.g., BPF_JSET)
> - * on the same registers, we don't need to adjust the min/max values.
> - */
> - if (false_reg1 == false_reg2)
> + if (env->false_reg1.type != SCALAR_VALUE || env->false_reg2.type != SCALAR_VALUE)
> return 0;
>
> /* fallthrough (FALSE) branch */
> - regs_refine_cond_op(false_reg1, false_reg2, rev_opcode(opcode), is_jmp32);
> - reg_bounds_sync(false_reg1);
> - reg_bounds_sync(false_reg2);
> + regs_refine_cond_op(&env->false_reg1, &env->false_reg2, rev_opcode(opcode), is_jmp32);
> + reg_bounds_sync(&env->false_reg1);
> + reg_bounds_sync(&env->false_reg2);
>
> /* jump (TRUE) branch */
> - regs_refine_cond_op(true_reg1, true_reg2, opcode, is_jmp32);
> - reg_bounds_sync(true_reg1);
> - reg_bounds_sync(true_reg2);
> -
> - err = reg_bounds_sanity_check(env, true_reg1, "true_reg1");
> - err = err ?: reg_bounds_sanity_check(env, true_reg2, "true_reg2");
> - err = err ?: reg_bounds_sanity_check(env, false_reg1, "false_reg1");
> - err = err ?: reg_bounds_sanity_check(env, false_reg2, "false_reg2");
> + regs_refine_cond_op(&env->true_reg1, &env->true_reg2, opcode, is_jmp32);
> + reg_bounds_sync(&env->true_reg1);
> + reg_bounds_sync(&env->true_reg2);
> +
> + err = reg_bounds_sanity_check(env, &env->true_reg1, "true_reg1");
> + err = err ?: reg_bounds_sanity_check(env, &env->true_reg2, "true_reg2");
> + err = err ?: reg_bounds_sanity_check(env, &env->false_reg1, "false_reg1");
> + err = err ?: reg_bounds_sanity_check(env, &env->false_reg2, "false_reg2");
> return err;
> }
>
> @@ -17597,6 +17586,10 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
> }
>
> is_jmp32 = BPF_CLASS(insn->code) == BPF_JMP32;
> + copy_register_state(&env->false_reg1, dst_reg);
> + copy_register_state(&env->false_reg2, src_reg);
> + copy_register_state(&env->true_reg1, dst_reg);
> + copy_register_state(&env->true_reg2, src_reg);
> pred = is_branch_taken(dst_reg, src_reg, opcode, is_jmp32);
> if (pred >= 0) {
> /* If we get here with a dst_reg pointer type it is because
> @@ -17661,27 +17654,16 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
> return PTR_ERR(other_branch);
> other_branch_regs = other_branch->frame[other_branch->curframe]->regs;
>
> - if (BPF_SRC(insn->code) == BPF_X) {
> - err = reg_set_min_max(env,
> - &other_branch_regs[insn->dst_reg],
> - &other_branch_regs[insn->src_reg],
> - dst_reg, src_reg, opcode, is_jmp32);
> - } else /* BPF_SRC(insn->code) == BPF_K */ {
> - /* reg_set_min_max() can mangle the fake_reg. Make a copy
> - * so that these are two different memory locations. The
> - * src_reg is not used beyond here in context of K.
> - */
> - memcpy(&env->fake_reg[1], &env->fake_reg[0],
> - sizeof(env->fake_reg[0]));
> - err = reg_set_min_max(env,
> - &other_branch_regs[insn->dst_reg],
> - &env->fake_reg[0],
> - dst_reg, &env->fake_reg[1],
> - opcode, is_jmp32);
> - }
> + err = reg_set_min_max(env, opcode, is_jmp32);
> if (err)
> return err;
>
> + copy_register_state(dst_reg, &env->false_reg1);
> + copy_register_state(src_reg, &env->false_reg2);
> + copy_register_state(&other_branch_regs[insn->dst_reg], &env->true_reg1);
> + if (BPF_SRC(insn->code) == BPF_X)
> + copy_register_state(&other_branch_regs[insn->src_reg], &env->true_reg2);
> +
> if (BPF_SRC(insn->code) == BPF_X &&
> src_reg->type == SCALAR_VALUE && src_reg->id &&
> !WARN_ON_ONCE(src_reg->id != other_branch_regs[insn->src_reg].id)) {
> --
> 2.43.0
next prev parent reply other threads:[~2026-03-23 15:33 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-20 16:45 [PATCH v2 bpf-next 0/6] Fix invariant violations and improve branch detection Paul Chaignon
2026-03-20 16:47 ` [PATCH v2 bpf-next 1/6] bpf: Refactor reg_bounds_sanity_check Paul Chaignon
2026-03-23 8:01 ` Shung-Hsi Yu
2026-03-23 14:16 ` Mykyta Yatsenko
2026-03-24 16:56 ` Harishankar Vishwanathan
2026-03-24 18:16 ` Mykyta Yatsenko
2026-03-20 16:49 ` [PATCH v2 bpf-next 2/6] bpf: Use bpf_verifier_env buffers for reg_set_min_max Paul Chaignon
2026-03-23 8:15 ` Shung-Hsi Yu
2026-03-23 15:33 ` Mykyta Yatsenko [this message]
2026-03-23 18:42 ` Eduard Zingerman
2026-03-20 16:49 ` [PATCH v2 bpf-next 3/6] bpf: Exit early if reg_bounds_sync gets invalid inputs Paul Chaignon
2026-03-23 12:12 ` Shung-Hsi Yu
2026-03-24 17:46 ` Harishankar Vishwanathan
2026-03-23 18:47 ` Eduard Zingerman
2026-03-24 19:28 ` Harishankar Vishwanathan
2026-03-24 19:33 ` Eduard Zingerman
2026-03-20 16:49 ` [PATCH v2 bpf-next 4/6] bpf: Simulate branches to prune based on range violations Paul Chaignon
2026-03-23 12:23 ` Shung-Hsi Yu
2026-03-23 16:19 ` Mykyta Yatsenko
2026-03-24 20:36 ` Harishankar Vishwanathan
2026-03-25 13:52 ` Mykyta Yatsenko
2026-03-23 19:05 ` Eduard Zingerman
2026-03-24 23:59 ` Harishankar Vishwanathan
2026-03-25 0:08 ` Eduard Zingerman
2026-03-20 16:50 ` [PATCH v2 bpf-next 5/6] selftests/bpf: Cover invariant violation cases from syzbot Paul Chaignon
2026-03-23 17:46 ` Mykyta Yatsenko
2026-03-28 16:20 ` Paul Chaignon
2026-03-28 17:31 ` Alexei Starovoitov
2026-03-20 16:50 ` [PATCH v2 bpf-next 6/6] selftests/bpf: Remove invariant violation flags Paul Chaignon
2026-03-23 18:04 ` Mykyta Yatsenko
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=87o6kek1bg.fsf@gmail.com \
--to=mykyta.yatsenko5@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=harishankar.vishwanathan@gmail.com \
--cc=paul.chaignon@gmail.com \
--cc=santosh.nagarakatte@rutgers.edu \
--cc=shung-hsi.yu@suse.com \
--cc=srinivas.narayana@rutgers.edu \
/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