From: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>
To: "Vineet Gupta" <vineet.gupta@linux.dev>, <ast@kernel.org>,
<daniel@iogearbox.net>, <andrii@kernel.org>, <eddyz87@gmail.com>,
<memxor@gmail.com>
Cc: <martin.lau@linux.dev>, <song@kernel.org>,
<yonghong.song@linux.dev>, <jolsa@kernel.org>,
<emil@etsalapatis.com>, <ihor.solodrai@linux.dev>,
<john.fastabend@gmail.com>, <shuah@kernel.org>,
<bpf@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-kselftest@vger.kernel.org>
Subject: Re: [PATCH bpf-next v2 01/13] bpf: move linked-scalar flags out of bpf_reg_state->id [NFC]
Date: Sat, 12 Sep 2026 11:50:54 -0700 [thread overview]
Message-ID: <DLDKB6BTHVXE.PFK87O3QY1J5@gmail.com> (raw)
In-Reply-To: <20260910164635.459558-2-vineet.gupta@linux.dev>
On Thu Sep 10, 2026 at 9:46 AM PDT, Vineet Gupta wrote:
> bpf_reg_state->id doubles as a linked-register id and, in its top two
> bits, as a record of how the register relates to that set:
>
> #define BPF_ADD_CONST64 (1U << 31)
> #define BPF_ADD_CONST32 (1U << 30)
>
> Every user of ->id therefore has to mask, and more link kinds are coming.
> Move the two bits into a bitfield next to ->precise, which is the last
> field of the struct and outside every memcmp() window used for state
> comparison, so the layout and all byte-wise comparisons are unchanged. The
> two kinds are mutually exclusive, so a 2-bit enum captures them and makes
> ADD_CONST_32 vs ADD_CONST_64 explicit at each use.
>
> ->id becomes a plain 32-bit identifier: no masking anywhere, and
> check_scalar_ids() loses its two-level "check the compound id, then the
> base id" dance in favour of a single check_ids().
>
> While here, use regs_exact() for the explore_alu_limits case in regsafe():
> it is what that open-coded memcmp+check_scalar_ids pair amounts to, and it
> picks up the add_const comparison for free (parent_id is 0 for
> SCALAR_VALUE).
>
> check_stack_write_fixed_off() cleared ->id directly on a narrowing spill,
> which would now leave ->add_const set without an id; use
> clear_scalar_id().
>
> Moving the kind out of ->id also drops an incidental comparison in
> regs_exact(), which used to see it as part of the idmap key; the next
> patch restores it. Otherwise no functional change intended.
>
> Suggested-by: Eduard Zingerman <eddyz87@gmail.com>
> Signed-off-by: Vineet Gupta <vineet.gupta@linux.dev>
> ---
> v2: was RFC 2/6.
> - kinds are a 2-bit enum bitfield, not a byte of flags; RFC 1/6, which
> turned ->precise into that byte, is dropped (Eduard)
> - use regs_exact() for the explore_alu_limits case
> - clear_scalar_id() on the narrowing spill, which would otherwise leave
> ->add_const set without an id
>
> include/linux/bpf_verifier.h | 25 ++++++++-----
> kernel/bpf/log.c | 4 +--
> kernel/bpf/states.c | 35 +++++--------------
> kernel/bpf/verifier.c | 35 +++++++++++--------
> .../bpf/progs/verifier_linked_scalars.c | 34 +++++++++---------
> 5 files changed, 65 insertions(+), 68 deletions(-)
>
> diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
> index 9727df5af83a..afb1e5628698 100644
> --- a/include/linux/bpf_verifier.h
> +++ b/include/linux/bpf_verifier.h
> @@ -35,6 +35,17 @@ enum bpf_iter_state {
> BPF_ITER_STATE_DRAINED,
> };
>
> +/*
> + * Records that a register is (base + ->delta) within its ->id set:
> + * r1 += 10; r1 gets ADD_CONST_64 delta
> + * w3 += 10; r3 gets ADD_CONST_32 delta
w3 gets ?
> + */
> +enum bpf_add_const {
> + ADD_CONST_NONE = 0,
> + ADD_CONST_32, /* delta was added with a 32-bit ALU op */
> + ADD_CONST_64, /* ... with a 64-bit ALU op */
> +};
> +
> struct bpf_reg_state {
> /* Ordering of fields matters. See states_equal() */
> enum bpf_reg_type type;
> @@ -136,16 +147,9 @@ struct bpf_reg_state {
> * to a specific instance of bpf_iter.
> */
> /*
> - * Upper bit of ID is used to remember relationship between "linked"
> - * registers. Example:
> + * Registers sharing an ->id are "linked":
> * r1 = r2; both will have r1->id == r2->id == N
> - * r1 += 10; r1->id == N | BPF_ADD_CONST and r1->delta == 10
> - * r3 = r2; both will have r3->id == r2->id == N
> - * w3 += 10; r3->id == N | BPF_ADD_CONST32 and r3->delta == 10
> */
> -#define BPF_ADD_CONST64 (1U << 31)
> -#define BPF_ADD_CONST32 (1U << 30)
> -#define BPF_ADD_CONST (BPF_ADD_CONST64 | BPF_ADD_CONST32)
> u32 id;
> /*
> * Tracks the parent object this register was derived from.
> @@ -164,6 +168,11 @@ struct bpf_reg_state {
> u32 frameno;
> /* if (!precise && SCALAR_VALUE) min/max/tnum don't affect safety */
> bool precise;
> + /*
> + * How this register relates to the others sharing its ->id.
> + * Non-zero only if ->id is.
> + */
> + enum bpf_add_const add_const:2;
> };
>
> static inline s64 reg_smin(const struct bpf_reg_state *reg)
> diff --git a/kernel/bpf/log.c b/kernel/bpf/log.c
> index fb032dfdc0de..f8d7a5c8052f 100644
> --- a/kernel/bpf/log.c
> +++ b/kernel/bpf/log.c
> @@ -651,8 +651,8 @@ static void print_reg_state(struct bpf_verifier_env *env,
> verbose(env, "%s", btf_type_name(reg->btf, reg->btf_id));
> verbose(env, "(");
> if (reg->id)
> - verbose_a("id=%d", reg->id & ~BPF_ADD_CONST);
> - if (reg->id & BPF_ADD_CONST)
> + verbose_a("id=%d", reg->id);
> + if (reg->add_const)
> verbose(env, "%+d", reg->delta);
> if (reg->parent_id)
> verbose_a("parent_id=%d", reg->parent_id);
> diff --git a/kernel/bpf/states.c b/kernel/bpf/states.c
> index 66fb11b6c6a7..d974baad37ee 100644
> --- a/kernel/bpf/states.c
> +++ b/kernel/bpf/states.c
> @@ -369,13 +369,6 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
> * and r7.id=0 (both independent), without temp IDs both would map old_id=X
> * to cur_id=0 and pass. With temp IDs: r6 maps X->temp1, r7 tries to map
> * X->temp2, but X is already mapped to temp1, so the check fails correctly.
> - *
> - * When old_id has BPF_ADD_CONST set, the compound id (base | flag) and the
> - * base id (flag stripped) must both map consistently. Example: old has
> - * r2.id=A, r3.id=A|flag (r3 = r2 + delta), cur has r2.id=B, r3.id=C|flag
> - * (r3 derived from unrelated r4). Without the base check, idmap gets two
> - * independent entries A->B and A|flag->C|flag, missing that A->C conflicts
> - * with A->B. The base ID cross-check catches this.
> */
> static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
> {
> @@ -384,15 +377,7 @@ static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
>
> cur_id = cur_id ? cur_id : ++idmap->tmp_id_gen;
>
> - if (!check_ids(old_id, cur_id, idmap))
> - return false;
> - if (old_id & BPF_ADD_CONST) {
> - old_id &= ~BPF_ADD_CONST;
> - cur_id &= ~BPF_ADD_CONST;
> - if (!check_ids(old_id, cur_id, idmap))
> - return false;
> - }
> - return true;
> + return check_ids(old_id, cur_id, idmap);
> }
>
> static void __clean_func_state(struct bpf_verifier_env *env,
> @@ -542,8 +527,7 @@ static bool regsafe(struct bpf_verifier_env *env, struct bpf_reg_state *rold,
> /* explore_alu_limits disables tnum_in() and range_within()
> * logic and requires everything to be strict
> */
> - return memcmp(rold, rcur, offsetof(struct bpf_reg_state, id)) == 0 &&
> - check_scalar_ids(rold->id, rcur->id, idmap);
> + return regs_exact(rold, rcur, idmap);
Why drop memcmp() ? Doesn't look correct.
Also even after above change to check_scalar_ids() the check_scalar_ids() is still
no equivalent to check_ids() that regs_exact() is doing.
This patch should have been refactoring, if so, this change looks
unrelated and dubious.
The rest looks fine.
next prev parent reply other threads:[~2026-09-12 18:50 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 16:46 [PATCH bpf-next v2 00/13] bpf: track scalar equality across the low 32 bits Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 01/13] bpf: move linked-scalar flags out of bpf_reg_state->id [NFC] Vineet Gupta
2026-09-10 17:00 ` sashiko-bot
2026-09-11 6:56 ` Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-12 18:50 ` Alexei Starovoitov [this message]
2026-09-10 16:46 ` [PATCH bpf-next v2 02/13] bpf: compare linked-scalar kinds in regs_exact() Vineet Gupta
2026-09-12 18:51 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 03/13] bpf: track low-32 scalar equality across zero-extending movs Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 9:29 ` Vineet Gupta
2026-09-12 18:59 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 04/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 05/13] bpf: keep the range across a sign extension that cannot change it Vineet Gupta
2026-09-10 17:08 ` sashiko-bot
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 10:37 ` Vineet Gupta
2026-09-12 19:02 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 06/13] selftests/bpf: cover sign extensions that cannot change the range Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 07/13] bpf: track low-32 scalar equality across sign-extending movs Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 10:00 ` Vineet Gupta
2026-09-12 19:09 ` Alexei Starovoitov
2026-09-10 16:46 ` [PATCH bpf-next v2 08/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
2026-09-10 17:52 ` bot+bpf-ci
2026-09-11 8:00 ` Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 09/13] bpf: track low-32 scalar equality across narrowing stack fills Vineet Gupta
2026-09-10 17:04 ` sashiko-bot
2026-09-11 6:07 ` Vineet Gupta
2026-09-11 6:43 ` Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 10/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
2026-09-10 17:00 ` sashiko-bot
2026-09-11 5:34 ` Vineet Gupta
2026-09-10 17:31 ` bot+bpf-ci
2026-09-11 5:07 ` Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 11/13] bpf: record what a narrowing spill actually stores Vineet Gupta
2026-09-10 16:46 ` [PATCH bpf-next v2 12/13] bpf: track low-32 scalar equality across narrowing stack spills Vineet Gupta
2026-09-10 17:05 ` sashiko-bot
2026-09-10 16:46 ` [PATCH bpf-next v2 13/13] selftests/bpf: cover the low-32 link for " Vineet Gupta
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=DLDKB6BTHVXE.PFK87O3QY1J5@gmail.com \
--to=alexei.starovoitov@gmail.com \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=emil@etsalapatis.com \
--cc=ihor.solodrai@linux.dev \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=memxor@gmail.com \
--cc=shuah@kernel.org \
--cc=song@kernel.org \
--cc=vineet.gupta@linux.dev \
--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 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.