From: sashiko-bot@kernel.org
To: "Eduard Zingerman" <eddyz87@gmail.com>
Cc: bpf@vger.kernel.org
Subject: Re: [PATCH RFC bpf-next 1/4] bpf: representation and basic operations on circular numbers
Date: Tue, 21 Apr 2026 17:18:29 +0000 [thread overview]
Message-ID: <20260421171830.3881BC2BCB5@smtp.kernel.org> (raw)
In-Reply-To: <20260421-cnums-everywhere-rfc-v1-v1-1-8f8e98537f48@gmail.com>
Sashiko AI review found 4 potential issue(s):
- [Critical] `FN(cut)` emits wrapped chunks causing `FN(mk_mul_u)` to compute unsound narrow bounds.
- [Critical] `cnum32_from_cnum64()` can return a struct mathematically equivalent to the `CNUM32_EMPTY` sentinel.
- [High] Unconditional use of `__int128` breaks compilation on 32-bit architectures.
- [Medium] Missing emptiness checks in `cnum64_cnum32_intersect` and `cnum32_from_cnum64` resurrect unreachable states.
--
commit 5ab536543671bb2cd6865196d88e96f87d1e7888
Author: Eduard Zingerman <eddyz87@gmail.com>
bpf: representation and basic operations on circular numbers
This commit introduces cnum32 and cnum64 representations for unified
signed and unsigned numeric ranges in the BPF verifier. It includes
functions for intersection, multiplication, and range conversion to
refine bounds deductions.
Link: https://lore.kernel.org/all/ZTZxoDJJbX9mrQ9w@u94a/
Link: https://jorgenavas.github.io/papers/ACM-TOPLAS-wrapped.pdf
Link: https://github.com/eddyz87/cnum-verif/tree/master
> diff --git a/kernel/bpf/cnum.c b/kernel/bpf/cnum.c
> new file mode 100644
> index 0000000000000..38a805a6fc2a9
> --- /dev/null
> +++ b/kernel/bpf/cnum.c
[ ... ]
> +struct cnum32 cnum32_from_cnum64(struct cnum64 cnum)
> +{
Are we missing a check for empty inputs here? If an empty 64-bit range is
passed, does this code convert it directly into an unbounded 32-bit range?
> + if (cnum.size > U32_MAX)
> + return (struct cnum32){ .base = 0, .size = U32_MAX };
> + else
> + return (struct cnum32){ .base = (u32)cnum.base, .size = cnum.size };
> +}
Could this else branch return a value mathematically identical to the
CNUM32_EMPTY sentinel?
If a valid 64-bit range has a size of U32_MAX and a base ending in
0xFFFFFFFF, this would return { .base = 0xFFFFFFFF, .size = 0xFFFFFFFF }.
Would the verifier then incorrectly assume this code path is dead and
prune it?
[ ... ]
> +struct cnum64 cnum64_cnum32_intersect(struct cnum64 a, struct cnum32 b)
> +{
Does this function need to verify if the input ranges are empty before
operating on them? If the variable a is empty, could the arithmetic below
return a non-empty, garbage range, effectively resurrecting dead code paths?
> + /*
> + * To simplify reasoning, rotate the circles so that [virtual] a1 starts
> + * at u32 boundary, b1 represents b in this new frame of reference.
> + */
> + struct cnum32 b1 = { b.base - (u32)a.base, b.size };
[ ... ]
> diff --git a/kernel/bpf/cnum_defs.h b/kernel/bpf/cnum_defs.h
> new file mode 100644
> index 0000000000000..28dcb79ba6950
> --- /dev/null
> +++ b/kernel/bpf/cnum_defs.h
[ ... ]
> +#if T == 32
> +#define ut2 u64
> +#define st2 s64
> +#define utt u32
> +#define stt s32
> +#define EMPTY CNUM32_EMPTY
> +#elif T == 64
> +#define ut2 unsigned __int128
> +#define st2 signed __int128
Will the unconditional use of unsigned __int128 and signed __int128 break
compilation on 32-bit architectures? Since the BPF subsystem and verifier
are built on 32-bit kernels when CONFIG_BPF_SYSCALL is enabled, this
might cause widespread build failures.
> +#define utt u64
> +#define stt s64
> +#define EMPTY CNUM64_EMPTY
> +#else
> +#error "Unsupported T value, cannot define ut2/st2"
> +#endif
[ ... ]
> +static int FN(cut)(struct cnum_t a, struct cnum_t chunks[3])
> +{
> + int ncuts = 0;
> +
> + if (FN(srange_overflow)(a)) {
> + chunks[ncuts++] = FN(from_urange)(a.base, ST_MAX);
> + a = FN(from_urange)(ST_MIN, a.base + a.size);
> + }
Can this splitting logic emit wrapped chunks that cause bound deductions
to underflow?
When an arc crosses both boundaries, this splits it first at ST_MAX. The
resulting first chunk crosses the unsigned boundary 0.
When passed to FN(mul_chunk) with a multiplier, it falls into the fallback
branch utilizing FN(mk_mul_u):
static struct cnum_t FN(mk_mul_u)(utt a, utt b, utt c, utt d)
{
ut2 size = (ut2)c * d - (ut2)a * b;
Because the chunk wraps, its unsigned start is mathematically greater than
its end. Does this cause the subtraction to severely underflow in unsigned
arithmetic, producing an artificially tight size that misses valid
runtime products?
> + if (FN(urange_overflow)(a)) {
> + chunks[ncuts++] = FN(from_urange)(a.base, UT_MAX);
> + a = FN(from_urange)(0, a.base + a.size);
> + }
> + chunks[ncuts++] = a;
> + return ncuts;
> +}
[ ... ]
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260421-cnums-everywhere-rfc-v1-v1-0-8f8e98537f48@gmail.com?part=1
next prev parent reply other threads:[~2026-04-21 17:18 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-04-21 10:28 [PATCH RFC bpf-next 0/4] bpf: replace min/max fields with struct cnum{32,64} Eduard Zingerman
2026-04-21 10:28 ` [PATCH RFC bpf-next 1/4] bpf: representation and basic operations on circular numbers Eduard Zingerman
2026-04-21 11:16 ` bot+bpf-ci
2026-04-21 17:18 ` sashiko-bot [this message]
2026-04-21 17:45 ` Eduard Zingerman
2026-04-21 10:28 ` [PATCH RFC bpf-next 2/4] bpf: use accessor functions for bpf_reg_state min/max fields Eduard Zingerman
2026-04-21 10:28 ` [PATCH RFC bpf-next 3/4] bpf: replace min/max fields with struct cnum{32,64} Eduard Zingerman
2026-04-21 11:16 ` bot+bpf-ci
2026-04-21 16:23 ` Alexei Starovoitov
2026-04-21 16:48 ` Eduard Zingerman
2026-04-21 17:16 ` Alexei Starovoitov
2026-04-21 17:20 ` Eduard Zingerman
2026-04-21 18:06 ` sashiko-bot
2026-04-21 18:31 ` Eduard Zingerman
2026-04-21 10:28 ` [PATCH RFC bpf-next 4/4] selftests/bpf: new cases handled by 32->64 range refinements Eduard Zingerman
2026-04-21 16:10 ` [PATCH RFC bpf-next 0/4] bpf: replace min/max fields with struct cnum{32,64} Alexei Starovoitov
2026-04-21 16:33 ` Eduard Zingerman
2026-04-21 17:14 ` Alexei Starovoitov
2026-04-21 23:45 ` Eduard Zingerman
2026-04-22 14:50 ` Yazhou Tang
2026-04-22 15:03 ` Alexei Starovoitov
2026-04-22 15:32 ` Yazhou Tang
2026-04-22 16:13 ` Alexei Starovoitov
2026-04-22 19:05 ` Eduard Zingerman
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=20260421171830.3881BC2BCB5@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=eddyz87@gmail.com \
--cc=sashiko@lists.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