* [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
@ 2026-03-05 19:48 Eduard Zingerman
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
` (3 more replies)
0 siblings, 4 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-05 19:48 UTC (permalink / raw)
To: bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, emil,
arighi, shung-hsi.yu
Cover the following cases in range refinement logic for 32-bit ranges:
- s32 range crosses U32_MAX/0 boundary, positive part of the s32 range
overlaps with u32 range.
- s32 range crosses U32_MAX/0 boundary, negative part of the s32 range
overlaps with u32 range.
These cases are already handled for 64-bit range refinement.
Changelog:
- v1 -> v2:
- Extended commit message and comments (Emil)
- Targeting 'bpf' tree instead of bpf-next (Alexei)
v1: https://lore.kernel.org/bpf/9a23fbacdc6d33ec8fcb3f6988395b5129f75369.camel@gmail.com/T
---
Eduard Zingerman (2):
bpf: refine u32/s32 bounds when ranges cross min/max boundary
selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
kernel/bpf/verifier.c | 24 +++++++++
.../testing/selftests/bpf/prog_tests/reg_bounds.c | 62 ++++++++++++++++++++--
.../testing/selftests/bpf/progs/verifier_bounds.c | 37 +++++++++++++
3 files changed, 119 insertions(+), 4 deletions(-)
---
base-commit: 56145d237385ca0e7ca9ff7b226aaf2eb8ef368b
change-id: 20260305-bpf-32-bit-range-overflow-00351dfb8083
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary Eduard Zingerman
@ 2026-03-05 19:48 ` Eduard Zingerman
2026-03-05 20:28 ` bot+bpf-ci
` (2 more replies)
2026-03-05 19:48 ` [PATCH bpf v2 2/2] selftests/bpf: test refining " Eduard Zingerman
` (2 subsequent siblings)
3 siblings, 3 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-05 19:48 UTC (permalink / raw)
To: bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, emil,
arighi, shung-hsi.yu
Same as in __reg64_deduce_bounds(), refine s32/u32 ranges
in __reg32_deduce_bounds() in the following situations:
- s32 range crosses U32_MAX/0 boundary, positive part of the s32 range
overlaps with u32 range:
0 U32_MAX
| [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
|----------------------------|----------------------------|
|xxxxx s32 range xxxxxxxxx] [xxxxxxx|
0 S32_MAX S32_MIN -1
- s32 range crosses U32_MAX/0 boundary, negative part of the s32 range
overlaps with u32 range:
0 U32_MAX
| [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
|----------------------------|----------------------------|
|xxxxxxxxx] [xxxxxxxxxxxx s32 range |
0 S32_MAX S32_MIN -1
- No refinement if ranges overlap in two intervals.
This helps for e.g. consider the following program:
call %[bpf_get_prandom_u32];
w0 &= 0xffffffff;
if w0 < 0x3 goto 1f; // on fall-through u32 range [3..U32_MAX]
if w0 s> 0x1 goto 1f; // on fall-through s32 range [S32_MIN..1]
if w0 s< 0x0 goto 1f; // range can be narrowed to [S32_MIN..-1]
r10 = 0;
1: ...;
The reg_bounds.c selftest is updated to incorporate identical logic,
refinement based on non-overflowing range halves:
((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
Reported-by: Andrea Righi <arighi@nvidia.com>
Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
Closes: https://lore.kernel.org/bpf/aakqucg4vcujVwif@gpd4/T/
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
kernel/bpf/verifier.c | 24 +++++++++
.../testing/selftests/bpf/prog_tests/reg_bounds.c | 62 ++++++++++++++++++++--
2 files changed, 82 insertions(+), 4 deletions(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 401d6c4960eccfa90893660b7d8aece859787f7f..f960b382fdb3d4a4f5f2a66a525c2f594de529ff 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -2511,6 +2511,30 @@ static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
+ } else {
+ if (reg->u32_max_value < (u32)reg->s32_min_value) {
+ /* See __reg64_deduce_bounds() for detailed explanation.
+ * Refine ranges in the following situation:
+ *
+ * 0 U32_MAX
+ * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
+ * |----------------------------|----------------------------|
+ * |xxxxx s32 range xxxxxxxxx] [xxxxxxx|
+ * 0 S32_MAX S32_MIN -1
+ */
+ reg->s32_min_value = (s32)reg->u32_min_value;
+ reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
+ } else if ((u32)reg->s32_max_value < reg->u32_min_value) {
+ /*
+ * 0 U32_MAX
+ * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
+ * |----------------------------|----------------------------|
+ * |xxxxxxxxx] [xxxxxxxxxxxx s32 range |
+ * 0 S32_MAX S32_MIN -1
+ */
+ reg->s32_max_value = (s32)reg->u32_max_value;
+ reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
+ }
}
}
diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
--- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
+++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
@@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
}
}
-static struct range range_improve(enum num_t t, struct range old, struct range new)
+static struct range range_intersection(enum num_t t, struct range old, struct range new)
{
return range(t, max_t(t, old.a, new.a), min_t(t, old.b, new.b));
}
+/*
+ * Result is precise when 'x' and 'y' overlap or form a continuous range,
+ * result is an over-approximation if 'x' and 'y' do not overlap.
+ */
+static struct range range_union(enum num_t t, struct range x, struct range y)
+{
+ if (!is_valid_range(t, x))
+ return y;
+ if (!is_valid_range(t, y))
+ return x;
+ return range(t, min_t(t, x.a, y.a), max_t(t, x.b, y.b));
+}
+
+/*
+ * This function attempts to improve x range intersecting it with y.
+ * range_cast(... to_t ...) looses precision for ranges that pass to_t
+ * min/max boundaries. To avoid such precision loses this function
+ * splits both x and y into halves corresponding to non-overflowing
+ * sub-ranges: [0, smin] and [smax, -1].
+ * Final result is computed as follows:
+ *
+ * ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
+ * ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
+ *
+ * Precision might still be lost if final union is not a continuous range.
+ */
+static struct range range_refine_in_halves(enum num_t x_t, struct range x,
+ enum num_t y_t, struct range y)
+{
+ struct range x_pos, x_neg, y_pos, y_neg, r_pos, r_neg;
+ u64 smax, smin, neg_one;
+
+ if (t_is_32(x_t)) {
+ smax = (u64)(u32)S32_MAX;
+ smin = (u64)(u32)S32_MIN;
+ neg_one = (u64)(u32)(s32)(-1);
+ } else {
+ smax = (u64)S64_MAX;
+ smin = (u64)S64_MIN;
+ neg_one = U64_MAX;
+ }
+ x_pos = range_intersection(x_t, x, range(x_t, 0, smax));
+ x_neg = range_intersection(x_t, x, range(x_t, smin, neg_one));
+ y_pos = range_intersection(y_t, y, range(x_t, 0, smax));
+ y_neg = range_intersection(y_t, y, range(y_t, smin, neg_one));
+ r_pos = range_intersection(x_t, x_pos, range_cast(y_t, x_t, y_pos));
+ r_neg = range_intersection(x_t, x_neg, range_cast(y_t, x_t, y_neg));
+ return range_union(x_t, r_pos, r_neg);
+
+}
+
static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, struct range y)
{
struct range y_cast;
+ if (t_is_32(x_t) == t_is_32(y_t))
+ x = range_refine_in_halves(x_t, x, y_t, y);
+
y_cast = range_cast(y_t, x_t, y);
/* If we know that
@@ -444,7 +498,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
*/
if (x_t == S64 && y_t == S32 && y_cast.a <= S32_MAX && y_cast.b <= S32_MAX &&
(s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)
- return range_improve(x_t, x, y_cast);
+ return range_intersection(x_t, x, y_cast);
/* the case when new range knowledge, *y*, is a 32-bit subregister
* range, while previous range knowledge, *x*, is a full register
@@ -462,7 +516,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
x_swap = range(x_t, swap_low32(x.a, y_cast.a), swap_low32(x.b, y_cast.b));
if (!is_valid_range(x_t, x_swap))
return x;
- return range_improve(x_t, x, x_swap);
+ return range_intersection(x_t, x, x_swap);
}
if (!t_is_32(x_t) && !t_is_32(y_t) && x_t != y_t) {
@@ -480,7 +534,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
}
/* otherwise, plain range cast and intersection works */
- return range_improve(x_t, x, y_cast);
+ return range_intersection(x_t, x, y_cast);
}
/* =======================
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH bpf v2 2/2] selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary Eduard Zingerman
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
@ 2026-03-05 19:48 ` Eduard Zingerman
2026-03-05 19:54 ` Eduard Zingerman
` (2 more replies)
2026-03-05 22:59 ` [PATCH bpf v2 0/2] bpf: refine " Eduard Zingerman
2026-03-06 5:17 ` Shung-Hsi Yu
3 siblings, 3 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-05 19:48 UTC (permalink / raw)
To: bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, emil,
arighi, shung-hsi.yu
Two test cases for signed/unsigned 32-bit bounds refinement
when s32 range crosses the sign boundary:
- s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX],
s32 range tail before sign boundary overlaps with u32 range.
- s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3],
s32 range head after the sign boundary overlaps with u32 range.
This covers both branches added in the __reg32_deduce_bounds().
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
.../testing/selftests/bpf/progs/verifier_bounds.c | 37 ++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
index 97065a26cf70603c3e4b8d43d3a04248828398fc..60ef976959153d25c19ba08c3c2f265d8d83b33e 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
@@ -2000,4 +2000,41 @@ __naked void bounds_refinement_multiple_overlaps(void *ctx)
: __clobber_all);
}
+SEC("socket")
+__success
+__flag(BPF_F_TEST_REG_INVARIANTS)
+__naked void signed_unsigned_intersection32_case1(void *ctx)
+{
+ asm volatile(" \
+ call %[bpf_get_prandom_u32]; \
+ w0 &= 0xffffffff; \
+ if w0 < 0x3 goto 1f; /* on fall-through u32 range [3..U32_MAX] */ \
+ if w0 s> 0x1 goto 1f; /* on fall-through s32 range [S32_MIN..1] */ \
+ if w0 s< 0x0 goto 1f; /* range can be narrowed to [S32_MIN..-1] */ \
+ r10 = 0; /* thus predicting the jump. */ \
+1: exit; \
+" :
+ : __imm(bpf_get_prandom_u32)
+ : __clobber_all);
+}
+
+SEC("socket")
+__success
+__flag(BPF_F_TEST_REG_INVARIANTS)
+__naked void signed_unsigned_intersection32_case2(void *ctx)
+{
+ asm volatile(" \
+ call %[bpf_get_prandom_u32]; \
+ w0 &= 0xffffffff; \
+ if w0 > 0x80000003 goto 1f; /* on fall-through u32 range [0..S32_MIN+3] */ \
+ if w0 s< -3 goto 1f; /* on fall-through s32 range [-3..S32_MAX] */ \
+ if w0 s> 5 goto 1f; /* on fall-through s32 range [-3..5] */ \
+ if w0 <= 5 goto 1f; /* range can be narrowed to [0..5] */ \
+ r10 = 0; /* thus predicting the jump */ \
+1: exit; \
+" :
+ : __imm(bpf_get_prandom_u32)
+ : __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
--
2.53.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 2/2] selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 ` [PATCH bpf v2 2/2] selftests/bpf: test refining " Eduard Zingerman
@ 2026-03-05 19:54 ` Eduard Zingerman
2026-03-05 20:54 ` Emil Tsalapatis
2026-03-05 20:55 ` Emil Tsalapatis
2026-03-06 0:21 ` Paul Chaignon
2 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-05 19:54 UTC (permalink / raw)
To: bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, emil, arighi,
shung-hsi.yu
On Thu, 2026-03-05 at 11:48 -0800, Eduard Zingerman wrote:
> Two test cases for signed/unsigned 32-bit bounds refinement
> when s32 range crosses the sign boundary:
> - s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX],
> s32 range tail before sign boundary overlaps with u32 range.
> - s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3],
> s32 range head after the sign boundary overlaps with u32 range.
>
> This covers both branches added in the __reg32_deduce_bounds().
>
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> ---
I did not copy the reviewed-by tag from Emil from v1:
"Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>"
Sorry...
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
@ 2026-03-05 20:28 ` bot+bpf-ci
2026-03-05 20:31 ` Eduard Zingerman
2026-03-05 20:51 ` Emil Tsalapatis
2026-03-06 0:13 ` Paul Chaignon
2 siblings, 1 reply; 19+ messages in thread
From: bot+bpf-ci @ 2026-03-05 20:28 UTC (permalink / raw)
To: eddyz87, bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, eddyz87, emil,
arighi, shung-hsi.yu, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, clm, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 891 bytes --]
> Reported-by: Andrea Righi <arighi@nvidia.com>
> Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
> Closes: https://lore.kernel.org/bpf/aakqucg4vcujVwif@gpd4/T/
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
This commit fixes a missing refinement that was noted as a known gap
when the 64-bit version was added. Paul Chaignon's commit message for
00bf8d0c6c9b stated: "The same logic can probably apply to the s32/u32
ranges, but this patch doesn't implement that change."
Should a Fixes: tag be included to reference that commit? The
suggested tag would be:
Fixes: 00bf8d0c6c9b ("bpf: Improve bounds when s64 crosses sign boundary")
---
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/22734151945
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 20:28 ` bot+bpf-ci
@ 2026-03-05 20:31 ` Eduard Zingerman
0 siblings, 0 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-05 20:31 UTC (permalink / raw)
To: bot+bpf-ci, bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, emil, arighi,
shung-hsi.yu, martin.lau, clm, ihor.solodrai
On Thu, 2026-03-05 at 20:28 +0000, bot+bpf-ci@kernel.org wrote:
> > Reported-by: Andrea Righi <arighi@nvidia.com>
> > Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
> > Closes: https://lore.kernel.org/bpf/aakqucg4vcujVwif@gpd4/T/
> > Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
>
> This commit fixes a missing refinement that was noted as a known gap
> when the 64-bit version was added. Paul Chaignon's commit message for
> 00bf8d0c6c9b stated: "The same logic can probably apply to the s32/u32
> ranges, but this patch doesn't implement that change."
>
> Should a Fixes: tag be included to reference that commit? The
> suggested tag would be:
>
> Fixes: 00bf8d0c6c9b ("bpf: Improve bounds when s64 crosses sign boundary")
I disagree with this assessment, there is nothing wrong with 00bf8d0c6c9b.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
2026-03-05 20:28 ` bot+bpf-ci
@ 2026-03-05 20:51 ` Emil Tsalapatis
2026-03-06 0:13 ` Paul Chaignon
2 siblings, 0 replies; 19+ messages in thread
From: Emil Tsalapatis @ 2026-03-05 20:51 UTC (permalink / raw)
To: Eduard Zingerman, bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, arighi,
shung-hsi.yu
On Thu Mar 5, 2026 at 2:48 PM EST, Eduard Zingerman wrote:
> Same as in __reg64_deduce_bounds(), refine s32/u32 ranges
> in __reg32_deduce_bounds() in the following situations:
>
> - s32 range crosses U32_MAX/0 boundary, positive part of the s32 range
> overlaps with u32 range:
>
> 0 U32_MAX
> | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> |----------------------------|----------------------------|
> |xxxxx s32 range xxxxxxxxx] [xxxxxxx|
> 0 S32_MAX S32_MIN -1
>
> - s32 range crosses U32_MAX/0 boundary, negative part of the s32 range
> overlaps with u32 range:
>
> 0 U32_MAX
> | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> |----------------------------|----------------------------|
> |xxxxxxxxx] [xxxxxxxxxxxx s32 range |
> 0 S32_MAX S32_MIN -1
>
> - No refinement if ranges overlap in two intervals.
>
> This helps for e.g. consider the following program:
>
> call %[bpf_get_prandom_u32];
> w0 &= 0xffffffff;
> if w0 < 0x3 goto 1f; // on fall-through u32 range [3..U32_MAX]
> if w0 s> 0x1 goto 1f; // on fall-through s32 range [S32_MIN..1]
> if w0 s< 0x0 goto 1f; // range can be narrowed to [S32_MIN..-1]
> r10 = 0;
> 1: ...;
>
> The reg_bounds.c selftest is updated to incorporate identical logic,
> refinement based on non-overflowing range halves:
>
> ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
> ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
>
> Reported-by: Andrea Righi <arighi@nvidia.com>
> Reported-by: Emil Tsalapatis <emil@etsalapatis.com>
> Closes: https://lore.kernel.org/bpf/aakqucg4vcujVwif@gpd4/T/
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
> ---
> kernel/bpf/verifier.c | 24 +++++++++
> .../testing/selftests/bpf/prog_tests/reg_bounds.c | 62 ++++++++++++++++++++--
> 2 files changed, 82 insertions(+), 4 deletions(-)
>
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 401d6c4960eccfa90893660b7d8aece859787f7f..f960b382fdb3d4a4f5f2a66a525c2f594de529ff 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2511,6 +2511,30 @@ static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
> if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
> reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
> reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
> + } else {
> + if (reg->u32_max_value < (u32)reg->s32_min_value) {
> + /* See __reg64_deduce_bounds() for detailed explanation.
> + * Refine ranges in the following situation:
> + *
> + * 0 U32_MAX
> + * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> + * |----------------------------|----------------------------|
> + * |xxxxx s32 range xxxxxxxxx] [xxxxxxx|
> + * 0 S32_MAX S32_MIN -1
> + */
> + reg->s32_min_value = (s32)reg->u32_min_value;
> + reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
> + } else if ((u32)reg->s32_max_value < reg->u32_min_value) {
> + /*
> + * 0 U32_MAX
> + * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> + * |----------------------------|----------------------------|
> + * |xxxxxxxxx] [xxxxxxxxxxxx s32 range |
> + * 0 S32_MAX S32_MIN -1
> + */
> + reg->s32_max_value = (s32)reg->u32_max_value;
> + reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
> + }
> }
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
> }
> }
>
> -static struct range range_improve(enum num_t t, struct range old, struct range new)
> +static struct range range_intersection(enum num_t t, struct range old, struct range new)
> {
> return range(t, max_t(t, old.a, new.a), min_t(t, old.b, new.b));
> }
>
> +/*
> + * Result is precise when 'x' and 'y' overlap or form a continuous range,
> + * result is an over-approximation if 'x' and 'y' do not overlap.
> + */
> +static struct range range_union(enum num_t t, struct range x, struct range y)
> +{
> + if (!is_valid_range(t, x))
> + return y;
> + if (!is_valid_range(t, y))
> + return x;
> + return range(t, min_t(t, x.a, y.a), max_t(t, x.b, y.b));
> +}
> +
> +/*
> + * This function attempts to improve x range intersecting it with y.
> + * range_cast(... to_t ...) looses precision for ranges that pass to_t
> + * min/max boundaries. To avoid such precision loses this function
> + * splits both x and y into halves corresponding to non-overflowing
> + * sub-ranges: [0, smin] and [smax, -1].
> + * Final result is computed as follows:
> + *
> + * ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
> + * ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
> + *
> + * Precision might still be lost if final union is not a continuous range.
> + */
> +static struct range range_refine_in_halves(enum num_t x_t, struct range x,
> + enum num_t y_t, struct range y)
> +{
> + struct range x_pos, x_neg, y_pos, y_neg, r_pos, r_neg;
> + u64 smax, smin, neg_one;
> +
> + if (t_is_32(x_t)) {
> + smax = (u64)(u32)S32_MAX;
> + smin = (u64)(u32)S32_MIN;
> + neg_one = (u64)(u32)(s32)(-1);
> + } else {
> + smax = (u64)S64_MAX;
> + smin = (u64)S64_MIN;
> + neg_one = U64_MAX;
> + }
> + x_pos = range_intersection(x_t, x, range(x_t, 0, smax));
> + x_neg = range_intersection(x_t, x, range(x_t, smin, neg_one));
> + y_pos = range_intersection(y_t, y, range(x_t, 0, smax));
> + y_neg = range_intersection(y_t, y, range(y_t, smin, neg_one));
> + r_pos = range_intersection(x_t, x_pos, range_cast(y_t, x_t, y_pos));
> + r_neg = range_intersection(x_t, x_neg, range_cast(y_t, x_t, y_neg));
> + return range_union(x_t, r_pos, r_neg);
> +
> +}
> +
> static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, struct range y)
> {
> struct range y_cast;
>
> + if (t_is_32(x_t) == t_is_32(y_t))
> + x = range_refine_in_halves(x_t, x, y_t, y);
> +
> y_cast = range_cast(y_t, x_t, y);
>
> /* If we know that
> @@ -444,7 +498,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> */
> if (x_t == S64 && y_t == S32 && y_cast.a <= S32_MAX && y_cast.b <= S32_MAX &&
> (s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)
> - return range_improve(x_t, x, y_cast);
> + return range_intersection(x_t, x, y_cast);
>
> /* the case when new range knowledge, *y*, is a 32-bit subregister
> * range, while previous range knowledge, *x*, is a full register
> @@ -462,7 +516,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> x_swap = range(x_t, swap_low32(x.a, y_cast.a), swap_low32(x.b, y_cast.b));
> if (!is_valid_range(x_t, x_swap))
> return x;
> - return range_improve(x_t, x, x_swap);
> + return range_intersection(x_t, x, x_swap);
> }
>
> if (!t_is_32(x_t) && !t_is_32(y_t) && x_t != y_t) {
> @@ -480,7 +534,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> }
>
> /* otherwise, plain range cast and intersection works */
> - return range_improve(x_t, x, y_cast);
> + return range_intersection(x_t, x, y_cast);
> }
>
> /* =======================
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 2/2] selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:54 ` Eduard Zingerman
@ 2026-03-05 20:54 ` Emil Tsalapatis
0 siblings, 0 replies; 19+ messages in thread
From: Emil Tsalapatis @ 2026-03-05 20:54 UTC (permalink / raw)
To: Eduard Zingerman, bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, arighi,
shung-hsi.yu
On Thu Mar 5, 2026 at 2:54 PM EST, Eduard Zingerman wrote:
> On Thu, 2026-03-05 at 11:48 -0800, Eduard Zingerman wrote:
>> Two test cases for signed/unsigned 32-bit bounds refinement
>> when s32 range crosses the sign boundary:
>> - s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX],
>> s32 range tail before sign boundary overlaps with u32 range.
>> - s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3],
>> s32 range head after the sign boundary overlaps with u32 range.
>>
>> This covers both branches added in the __reg32_deduce_bounds().
>>
>> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
>> ---
>
> I did not copy the reviewed-by tag from Emil from v1:
>
> "Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>"
>
> Sorry...
No worries :) I can add it again on the v2.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 2/2] selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 ` [PATCH bpf v2 2/2] selftests/bpf: test refining " Eduard Zingerman
2026-03-05 19:54 ` Eduard Zingerman
@ 2026-03-05 20:55 ` Emil Tsalapatis
2026-03-06 0:21 ` Paul Chaignon
2 siblings, 0 replies; 19+ messages in thread
From: Emil Tsalapatis @ 2026-03-05 20:55 UTC (permalink / raw)
To: Eduard Zingerman, bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, arighi,
shung-hsi.yu
On Thu Mar 5, 2026 at 2:48 PM EST, Eduard Zingerman wrote:
> Two test cases for signed/unsigned 32-bit bounds refinement
> when s32 range crosses the sign boundary:
> - s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX],
> s32 range tail before sign boundary overlaps with u32 range.
> - s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3],
> s32 range head after the sign boundary overlaps with u32 range.
>
> This covers both branches added in the __reg32_deduce_bounds().
>
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Reviewed-by: Emil Tsalapatis <emil@etsalapatis.com>
> ---
> .../testing/selftests/bpf/progs/verifier_bounds.c | 37 ++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
> index 97065a26cf70603c3e4b8d43d3a04248828398fc..60ef976959153d25c19ba08c3c2f265d8d83b33e 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
> @@ -2000,4 +2000,41 @@ __naked void bounds_refinement_multiple_overlaps(void *ctx)
> : __clobber_all);
> }
>
> +SEC("socket")
> +__success
> +__flag(BPF_F_TEST_REG_INVARIANTS)
> +__naked void signed_unsigned_intersection32_case1(void *ctx)
> +{
> + asm volatile(" \
> + call %[bpf_get_prandom_u32]; \
> + w0 &= 0xffffffff; \
> + if w0 < 0x3 goto 1f; /* on fall-through u32 range [3..U32_MAX] */ \
> + if w0 s> 0x1 goto 1f; /* on fall-through s32 range [S32_MIN..1] */ \
> + if w0 s< 0x0 goto 1f; /* range can be narrowed to [S32_MIN..-1] */ \
> + r10 = 0; /* thus predicting the jump. */ \
> +1: exit; \
> +" :
> + : __imm(bpf_get_prandom_u32)
> + : __clobber_all);
> +}
> +
> +SEC("socket")
> +__success
> +__flag(BPF_F_TEST_REG_INVARIANTS)
> +__naked void signed_unsigned_intersection32_case2(void *ctx)
> +{
> + asm volatile(" \
> + call %[bpf_get_prandom_u32]; \
> + w0 &= 0xffffffff; \
> + if w0 > 0x80000003 goto 1f; /* on fall-through u32 range [0..S32_MIN+3] */ \
> + if w0 s< -3 goto 1f; /* on fall-through s32 range [-3..S32_MAX] */ \
> + if w0 s> 5 goto 1f; /* on fall-through s32 range [-3..5] */ \
> + if w0 <= 5 goto 1f; /* range can be narrowed to [0..5] */ \
> + r10 = 0; /* thus predicting the jump */ \
> +1: exit; \
> +" :
> + : __imm(bpf_get_prandom_u32)
> + : __clobber_all);
> +}
> +
> char _license[] SEC("license") = "GPL";
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary Eduard Zingerman
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
2026-03-05 19:48 ` [PATCH bpf v2 2/2] selftests/bpf: test refining " Eduard Zingerman
@ 2026-03-05 22:59 ` Eduard Zingerman
2026-03-06 5:17 ` Shung-Hsi Yu
3 siblings, 0 replies; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-05 22:59 UTC (permalink / raw)
To: bpf, ast, andrii
Cc: daniel, martin.lau, kernel-team, yonghong.song, emil, arighi,
shung-hsi.yu
On Thu, 2026-03-05 at 11:48 -0800, Eduard Zingerman wrote:
> Cover the following cases in range refinement logic for 32-bit ranges:
> - s32 range crosses U32_MAX/0 boundary, positive part of the s32 range
> overlaps with u32 range.
> - s32 range crosses U32_MAX/0 boundary, negative part of the s32 range
> overlaps with u32 range.
>
> These cases are already handled for 64-bit range refinement.
>
> Changelog:
> - v1 -> v2:
> - Extended commit message and comments (Emil)
> - Targeting 'bpf' tree instead of bpf-next (Alexei)
>
> v1: https://lore.kernel.org/bpf/9a23fbacdc6d33ec8fcb3f6988395b5129f75369.camel@gmail.com/T
> ---
On the other hand cnum approach as in [1] might make sense,
as it "one shots" all s32 <-> u32 range inference.
Need to double-check if meaningful __reg{32,64}_deduce_bounds()
simplification is possible.
[1] https://github.com/eddyz87/bpf/tree/cnum-sync-bounds
[...]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
2026-03-05 20:28 ` bot+bpf-ci
2026-03-05 20:51 ` Emil Tsalapatis
@ 2026-03-06 0:13 ` Paul Chaignon
2026-03-06 0:18 ` Eduard Zingerman
2 siblings, 1 reply; 19+ messages in thread
From: Paul Chaignon @ 2026-03-06 0:13 UTC (permalink / raw)
To: Eduard Zingerman
Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
emil, arighi, shung-hsi.yu
On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
[...]
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 401d6c4960eccfa90893660b7d8aece859787f7f..f960b382fdb3d4a4f5f2a66a525c2f594de529ff 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -2511,6 +2511,30 @@ static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
> if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
> reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
> reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
> + } else {
> + if (reg->u32_max_value < (u32)reg->s32_min_value) {
> + /* See __reg64_deduce_bounds() for detailed explanation.
> + * Refine ranges in the following situation:
> + *
> + * 0 U32_MAX
> + * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> + * |----------------------------|----------------------------|
> + * |xxxxx s32 range xxxxxxxxx] [xxxxxxx|
> + * 0 S32_MAX S32_MIN -1
> + */
> + reg->s32_min_value = (s32)reg->u32_min_value;
> + reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
> + } else if ((u32)reg->s32_max_value < reg->u32_min_value) {
> + /*
> + * 0 U32_MAX
> + * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> + * |----------------------------|----------------------------|
> + * |xxxxxxxxx] [xxxxxxxxxxxx s32 range |
> + * 0 S32_MAX S32_MIN -1
> + */
> + reg->s32_max_value = (s32)reg->u32_max_value;
> + reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
> + }
Looks good to me. I also ran it through Agni and __reg_deduce_bounds
(aka special instruction BPF_SYNC2) is still found to be sound.
> }
> }
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
> }
> }
>
> -static struct range range_improve(enum num_t t, struct range old, struct range new)
> +static struct range range_intersection(enum num_t t, struct range old, struct range new)
> {
> return range(t, max_t(t, old.a, new.a), min_t(t, old.b, new.b));
> }
>
> +/*
> + * Result is precise when 'x' and 'y' overlap or form a continuous range,
> + * result is an over-approximation if 'x' and 'y' do not overlap.
> + */
> +static struct range range_union(enum num_t t, struct range x, struct range y)
> +{
> + if (!is_valid_range(t, x))
> + return y;
> + if (!is_valid_range(t, y))
> + return x;
> + return range(t, min_t(t, x.a, y.a), max_t(t, x.b, y.b));
> +}
> +
> +/*
> + * This function attempts to improve x range intersecting it with y.
> + * range_cast(... to_t ...) looses precision for ranges that pass to_t
> + * min/max boundaries. To avoid such precision loses this function
> + * splits both x and y into halves corresponding to non-overflowing
> + * sub-ranges: [0, smin] and [smax, -1].
> + * Final result is computed as follows:
> + *
> + * ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
> + * ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
> + *
> + * Precision might still be lost if final union is not a continuous range.
> + */
> +static struct range range_refine_in_halves(enum num_t x_t, struct range x,
> + enum num_t y_t, struct range y)
> +{
> + struct range x_pos, x_neg, y_pos, y_neg, r_pos, r_neg;
> + u64 smax, smin, neg_one;
> +
> + if (t_is_32(x_t)) {
> + smax = (u64)(u32)S32_MAX;
> + smin = (u64)(u32)S32_MIN;
> + neg_one = (u64)(u32)(s32)(-1);
> + } else {
> + smax = (u64)S64_MAX;
> + smin = (u64)S64_MIN;
> + neg_one = U64_MAX;
> + }
> + x_pos = range_intersection(x_t, x, range(x_t, 0, smax));
> + x_neg = range_intersection(x_t, x, range(x_t, smin, neg_one));
> + y_pos = range_intersection(y_t, y, range(x_t, 0, smax));
> + y_neg = range_intersection(y_t, y, range(y_t, smin, neg_one));
> + r_pos = range_intersection(x_t, x_pos, range_cast(y_t, x_t, y_pos));
> + r_neg = range_intersection(x_t, x_neg, range_cast(y_t, x_t, y_neg));
> + return range_union(x_t, r_pos, r_neg);
> +
> +}
> +
> static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, struct range y)
> {
> struct range y_cast;
>
> + if (t_is_32(x_t) == t_is_32(y_t))
> + x = range_refine_in_halves(x_t, x, y_t, y);
Don't we usually put changes to this file in a separate commit, as for
test changes in general?
Also I believe with these changes, we can now revert commit da653de268d3
("selftests/bpf: Update reg_bound range refinement logic").
> +
> y_cast = range_cast(y_t, x_t, y);
>
> /* If we know that
> @@ -444,7 +498,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> */
> if (x_t == S64 && y_t == S32 && y_cast.a <= S32_MAX && y_cast.b <= S32_MAX &&
> (s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)
> - return range_improve(x_t, x, y_cast);
> + return range_intersection(x_t, x, y_cast);
>
> /* the case when new range knowledge, *y*, is a 32-bit subregister
> * range, while previous range knowledge, *x*, is a full register
> @@ -462,7 +516,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> x_swap = range(x_t, swap_low32(x.a, y_cast.a), swap_low32(x.b, y_cast.b));
> if (!is_valid_range(x_t, x_swap))
> return x;
> - return range_improve(x_t, x, x_swap);
> + return range_intersection(x_t, x, x_swap);
> }
>
> if (!t_is_32(x_t) && !t_is_32(y_t) && x_t != y_t) {
> @@ -480,7 +534,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> }
>
> /* otherwise, plain range cast and intersection works */
> - return range_improve(x_t, x, y_cast);
> + return range_intersection(x_t, x, y_cast);
> }
>
> /* =======================
>
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-06 0:13 ` Paul Chaignon
@ 2026-03-06 0:18 ` Eduard Zingerman
2026-03-06 0:24 ` Paul Chaignon
0 siblings, 1 reply; 19+ messages in thread
From: Eduard Zingerman @ 2026-03-06 0:18 UTC (permalink / raw)
To: Paul Chaignon
Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
emil, arighi, shung-hsi.yu
On Fri, 2026-03-06 at 01:13 +0100, Paul Chaignon wrote:
> On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
>
> [...]
>
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 401d6c4960eccfa90893660b7d8aece859787f7f..f960b382fdb3d4a4f5f2a66a525c2f594de529ff 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -2511,6 +2511,30 @@ static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
> > if ((u32)reg->s32_min_value <= (u32)reg->s32_max_value) {
> > reg->u32_min_value = max_t(u32, reg->s32_min_value, reg->u32_min_value);
> > reg->u32_max_value = min_t(u32, reg->s32_max_value, reg->u32_max_value);
> > + } else {
> > + if (reg->u32_max_value < (u32)reg->s32_min_value) {
> > + /* See __reg64_deduce_bounds() for detailed explanation.
> > + * Refine ranges in the following situation:
> > + *
> > + * 0 U32_MAX
> > + * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> > + * |----------------------------|----------------------------|
> > + * |xxxxx s32 range xxxxxxxxx] [xxxxxxx|
> > + * 0 S32_MAX S32_MIN -1
> > + */
> > + reg->s32_min_value = (s32)reg->u32_min_value;
> > + reg->u32_max_value = min_t(u32, reg->u32_max_value, reg->s32_max_value);
> > + } else if ((u32)reg->s32_max_value < reg->u32_min_value) {
> > + /*
> > + * 0 U32_MAX
> > + * | [xxxxxxxxxxxxxx u32 range xxxxxxxxxxxxxx] |
> > + * |----------------------------|----------------------------|
> > + * |xxxxxxxxx] [xxxxxxxxxxxx s32 range |
> > + * 0 S32_MAX S32_MIN -1
> > + */
> > + reg->s32_max_value = (s32)reg->u32_max_value;
> > + reg->u32_min_value = max_t(u32, reg->u32_min_value, reg->s32_min_value);
> > + }
>
> Looks good to me. I also ran it through Agni and __reg_deduce_bounds
> (aka special instruction BPF_SYNC2) is still found to be sound.
Great, thank you!
>
> > }
> > }
> >
> > diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> > --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
> > }
> > }
> >
> > -static struct range range_improve(enum num_t t, struct range old, struct range new)
> > +static struct range range_intersection(enum num_t t, struct range old, struct range new)
> > {
> > return range(t, max_t(t, old.a, new.a), min_t(t, old.b, new.b));
> > }
> >
> > +/*
> > + * Result is precise when 'x' and 'y' overlap or form a continuous range,
> > + * result is an over-approximation if 'x' and 'y' do not overlap.
> > + */
> > +static struct range range_union(enum num_t t, struct range x, struct range y)
> > +{
> > + if (!is_valid_range(t, x))
> > + return y;
> > + if (!is_valid_range(t, y))
> > + return x;
> > + return range(t, min_t(t, x.a, y.a), max_t(t, x.b, y.b));
> > +}
> > +
> > +/*
> > + * This function attempts to improve x range intersecting it with y.
> > + * range_cast(... to_t ...) looses precision for ranges that pass to_t
> > + * min/max boundaries. To avoid such precision loses this function
> > + * splits both x and y into halves corresponding to non-overflowing
> > + * sub-ranges: [0, smin] and [smax, -1].
> > + * Final result is computed as follows:
> > + *
> > + * ((x ∩ [0, smax]) ∩ (y ∩ [0, smax])) ∪
> > + * ((x ∩ [smin,-1]) ∩ (y ∩ [smin,-1]))
> > + *
> > + * Precision might still be lost if final union is not a continuous range.
> > + */
> > +static struct range range_refine_in_halves(enum num_t x_t, struct range x,
> > + enum num_t y_t, struct range y)
> > +{
> > + struct range x_pos, x_neg, y_pos, y_neg, r_pos, r_neg;
> > + u64 smax, smin, neg_one;
> > +
> > + if (t_is_32(x_t)) {
> > + smax = (u64)(u32)S32_MAX;
> > + smin = (u64)(u32)S32_MIN;
> > + neg_one = (u64)(u32)(s32)(-1);
> > + } else {
> > + smax = (u64)S64_MAX;
> > + smin = (u64)S64_MIN;
> > + neg_one = U64_MAX;
> > + }
> > + x_pos = range_intersection(x_t, x, range(x_t, 0, smax));
> > + x_neg = range_intersection(x_t, x, range(x_t, smin, neg_one));
> > + y_pos = range_intersection(y_t, y, range(x_t, 0, smax));
> > + y_neg = range_intersection(y_t, y, range(y_t, smin, neg_one));
> > + r_pos = range_intersection(x_t, x_pos, range_cast(y_t, x_t, y_pos));
> > + r_neg = range_intersection(x_t, x_neg, range_cast(y_t, x_t, y_neg));
> > + return range_union(x_t, r_pos, r_neg);
> > +
> > +}
> > +
> > static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t, struct range y)
> > {
> > struct range y_cast;
> >
> > + if (t_is_32(x_t) == t_is_32(y_t))
> > + x = range_refine_in_halves(x_t, x, y_t, y);
>
> Don't we usually put changes to this file in a separate commit, as for
> test changes in general?
W/o this change the reg_bounds.c tests would fail.
So far we tried to keep selftests passing for every commit,
to help with any potential bisecting.
>
> Also I believe with these changes, we can now revert commit da653de268d3
> ("selftests/bpf: Update reg_bound range refinement logic").
Makes sense, thank you for pointing this out.
> > +
> > y_cast = range_cast(y_t, x_t, y);
> >
> > /* If we know that
> > @@ -444,7 +498,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> > */
> > if (x_t == S64 && y_t == S32 && y_cast.a <= S32_MAX && y_cast.b <= S32_MAX &&
> > (s64)x.a >= S32_MIN && (s64)x.b <= S32_MAX)
> > - return range_improve(x_t, x, y_cast);
> > + return range_intersection(x_t, x, y_cast);
> >
> > /* the case when new range knowledge, *y*, is a 32-bit subregister
> > * range, while previous range knowledge, *x*, is a full register
> > @@ -462,7 +516,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> > x_swap = range(x_t, swap_low32(x.a, y_cast.a), swap_low32(x.b, y_cast.b));
> > if (!is_valid_range(x_t, x_swap))
> > return x;
> > - return range_improve(x_t, x, x_swap);
> > + return range_intersection(x_t, x, x_swap);
> > }
> >
> > if (!t_is_32(x_t) && !t_is_32(y_t) && x_t != y_t) {
> > @@ -480,7 +534,7 @@ static struct range range_refine(enum num_t x_t, struct range x, enum num_t y_t,
> > }
> >
> > /* otherwise, plain range cast and intersection works */
> > - return range_improve(x_t, x, y_cast);
> > + return range_intersection(x_t, x, y_cast);
> > }
> >
> > /* =======================
> >
> > --
> > 2.53.0
> >
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 2/2] selftests/bpf: test refining u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 ` [PATCH bpf v2 2/2] selftests/bpf: test refining " Eduard Zingerman
2026-03-05 19:54 ` Eduard Zingerman
2026-03-05 20:55 ` Emil Tsalapatis
@ 2026-03-06 0:21 ` Paul Chaignon
2 siblings, 0 replies; 19+ messages in thread
From: Paul Chaignon @ 2026-03-06 0:21 UTC (permalink / raw)
To: Eduard Zingerman
Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
emil, arighi, shung-hsi.yu
On Thu, Mar 05, 2026 at 11:48:23AM -0800, Eduard Zingerman wrote:
> Two test cases for signed/unsigned 32-bit bounds refinement
> when s32 range crosses the sign boundary:
> - s32 range [S32_MIN..1] overlapping with u32 range [3..U32_MAX],
> s32 range tail before sign boundary overlaps with u32 range.
> - s32 range [-3..5] overlapping with u32 range [0..S32_MIN+3],
> s32 range head after the sign boundary overlaps with u32 range.
>
> This covers both branches added in the __reg32_deduce_bounds().
>
> Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
> ---
As mentioned in the other thread, we can now also switch the
BPF_F_TEST_REG_INVARIANTS flag on the existing test:
diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
index 60ef97695915..e526315c718a 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
@@ -1148,7 +1148,7 @@ l0_%=: r0 = 0; \
SEC("xdp")
__description("bound check with JMP32_JSLT for crossing 32-bit signed boundary")
__success __retval(0)
-__flag(!BPF_F_TEST_REG_INVARIANTS) /* known invariants violation */
+__flag(BPF_F_TEST_REG_INVARIANTS)
__naked void crossing_32_bit_signed_boundary_2(void)
{
asm volatile ("
With that,
Reviewed-by: Paul Chaignon <paul.chaignon@gmail.com>
> .../testing/selftests/bpf/progs/verifier_bounds.c | 37 ++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
>
> diff --git a/tools/testing/selftests/bpf/progs/verifier_bounds.c b/tools/testing/selftests/bpf/progs/verifier_bounds.c
> index 97065a26cf70603c3e4b8d43d3a04248828398fc..60ef976959153d25c19ba08c3c2f265d8d83b33e 100644
> --- a/tools/testing/selftests/bpf/progs/verifier_bounds.c
> +++ b/tools/testing/selftests/bpf/progs/verifier_bounds.c
> @@ -2000,4 +2000,41 @@ __naked void bounds_refinement_multiple_overlaps(void *ctx)
> : __clobber_all);
> }
>
> +SEC("socket")
> +__success
> +__flag(BPF_F_TEST_REG_INVARIANTS)
> +__naked void signed_unsigned_intersection32_case1(void *ctx)
> +{
> + asm volatile(" \
> + call %[bpf_get_prandom_u32]; \
> + w0 &= 0xffffffff; \
> + if w0 < 0x3 goto 1f; /* on fall-through u32 range [3..U32_MAX] */ \
> + if w0 s> 0x1 goto 1f; /* on fall-through s32 range [S32_MIN..1] */ \
> + if w0 s< 0x0 goto 1f; /* range can be narrowed to [S32_MIN..-1] */ \
> + r10 = 0; /* thus predicting the jump. */ \
> +1: exit; \
> +" :
> + : __imm(bpf_get_prandom_u32)
> + : __clobber_all);
> +}
> +
> +SEC("socket")
> +__success
> +__flag(BPF_F_TEST_REG_INVARIANTS)
> +__naked void signed_unsigned_intersection32_case2(void *ctx)
> +{
> + asm volatile(" \
> + call %[bpf_get_prandom_u32]; \
> + w0 &= 0xffffffff; \
> + if w0 > 0x80000003 goto 1f; /* on fall-through u32 range [0..S32_MIN+3] */ \
> + if w0 s< -3 goto 1f; /* on fall-through s32 range [-3..S32_MAX] */ \
> + if w0 s> 5 goto 1f; /* on fall-through s32 range [-3..5] */ \
> + if w0 <= 5 goto 1f; /* range can be narrowed to [0..5] */ \
> + r10 = 0; /* thus predicting the jump */ \
> +1: exit; \
> +" :
> + : __imm(bpf_get_prandom_u32)
> + : __clobber_all);
> +}
> +
> char _license[] SEC("license") = "GPL";
>
> --
> 2.53.0
>
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-06 0:18 ` Eduard Zingerman
@ 2026-03-06 0:24 ` Paul Chaignon
2026-03-12 6:45 ` Shung-Hsi Yu
0 siblings, 1 reply; 19+ messages in thread
From: Paul Chaignon @ 2026-03-06 0:24 UTC (permalink / raw)
To: Eduard Zingerman
Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
emil, arighi, shung-hsi.yu
On Thu, Mar 05, 2026 at 04:18:42PM -0800, Eduard Zingerman wrote:
> On Fri, 2026-03-06 at 01:13 +0100, Paul Chaignon wrote:
> > On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
[...]
> > > diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> > > --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
[...]
> > Don't we usually put changes to this file in a separate commit, as for
> > test changes in general?
>
> W/o this change the reg_bounds.c tests would fail.
> So far we tried to keep selftests passing for every commit,
> to help with any potential bisecting.
Ah, I didn't know that. Definitely makes sense for bisecting.
I probably broke it at least once :(
[...]
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-05 19:48 [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary Eduard Zingerman
` (2 preceding siblings ...)
2026-03-05 22:59 ` [PATCH bpf v2 0/2] bpf: refine " Eduard Zingerman
@ 2026-03-06 5:17 ` Shung-Hsi Yu
3 siblings, 0 replies; 19+ messages in thread
From: Shung-Hsi Yu @ 2026-03-06 5:17 UTC (permalink / raw)
To: Eduard Zingerman
Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
emil, arighi
On Thu, Mar 05, 2026 at 11:48:21AM -0800, Eduard Zingerman wrote:
> Cover the following cases in range refinement logic for 32-bit ranges:
> - s32 range crosses U32_MAX/0 boundary, positive part of the s32 range
> overlaps with u32 range.
> - s32 range crosses U32_MAX/0 boundary, negative part of the s32 range
> overlaps with u32 range.
>
> These cases are already handled for 64-bit range refinement.
LGTM.
Acked-by: Shung-Hsi Yu <shung-hsi.yu@suse.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-06 0:24 ` Paul Chaignon
@ 2026-03-12 6:45 ` Shung-Hsi Yu
2026-03-17 15:37 ` Paul Chaignon
0 siblings, 1 reply; 19+ messages in thread
From: Shung-Hsi Yu @ 2026-03-12 6:45 UTC (permalink / raw)
To: Paul Chaignon
Cc: Eduard Zingerman, bpf, ast, andrii, daniel, martin.lau,
kernel-team, yonghong.song, emil, arighi
On Fri, Mar 06, 2026 at 01:24:28AM +0100, Paul Chaignon wrote:
> On Thu, Mar 05, 2026 at 04:18:42PM -0800, Eduard Zingerman wrote:
> > On Fri, 2026-03-06 at 01:13 +0100, Paul Chaignon wrote:
> > > On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
>
> [...]
>
> > > > diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> > > > --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
>
> [...]
>
> > > Don't we usually put changes to this file in a separate commit, as for
> > > test changes in general?
> >
> > W/o this change the reg_bounds.c tests would fail.
> > So far we tried to keep selftests passing for every commit,
> > to help with any potential bisecting.
Similarly we have stable AUTOSEL tends to just pick up kernel/bpf/
changes and not the selftests ones. e.g. both 76e954155b45 ("bpf:
Introduce tnum_step to step through tnum's members") and efc11a667878
("bpf: Improve bounds when tnum has a single possible value") got picked
for 6.18.17-rc1, but not 024cea2d647e "selftests/bpf: Avoid
simplification of crafted bounds test".
> Ah, I didn't know that. Definitely makes sense for bisecting.
> I probably broke it at least once :(
>
> [...]
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-12 6:45 ` Shung-Hsi Yu
@ 2026-03-17 15:37 ` Paul Chaignon
2026-03-19 7:03 ` Shung-Hsi Yu
0 siblings, 1 reply; 19+ messages in thread
From: Paul Chaignon @ 2026-03-17 15:37 UTC (permalink / raw)
To: Shung-Hsi Yu
Cc: Eduard Zingerman, bpf, ast, andrii, daniel, martin.lau,
kernel-team, yonghong.song, emil, arighi
On Thu, Mar 12, 2026 at 02:45:47PM +0800, Shung-Hsi Yu wrote:
> On Fri, Mar 06, 2026 at 01:24:28AM +0100, Paul Chaignon wrote:
> > On Thu, Mar 05, 2026 at 04:18:42PM -0800, Eduard Zingerman wrote:
> > > On Fri, 2026-03-06 at 01:13 +0100, Paul Chaignon wrote:
> > > > On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
> >
> > [...]
> >
> > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> > > > > --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
> >
> > [...]
> >
> > > > Don't we usually put changes to this file in a separate commit, as for
> > > > test changes in general?
> > >
> > > W/o this change the reg_bounds.c tests would fail.
> > > So far we tried to keep selftests passing for every commit,
> > > to help with any potential bisecting.
>
> Similarly we have stable AUTOSEL tends to just pick up kernel/bpf/
> changes and not the selftests ones. e.g. both 76e954155b45 ("bpf:
> Introduce tnum_step to step through tnum's members") and efc11a667878
> ("bpf: Improve bounds when tnum has a single possible value") got picked
> for 6.18.17-rc1, but not 024cea2d647e "selftests/bpf: Avoid
> simplification of crafted bounds test".
I can send the selftest backports to the stable ml (unless you already
are on it?)
Do you know if there's anything I could have done differently to have
the selftests picked up? Or maybe something we could change in AUTOSEL?
>
> > Ah, I didn't know that. Definitely makes sense for bisecting.
> > I probably broke it at least once :(
> >
> > [...]
> >
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-17 15:37 ` Paul Chaignon
@ 2026-03-19 7:03 ` Shung-Hsi Yu
2026-03-19 10:21 ` Paul Chaignon
0 siblings, 1 reply; 19+ messages in thread
From: Shung-Hsi Yu @ 2026-03-19 7:03 UTC (permalink / raw)
To: Paul Chaignon
Cc: Eduard Zingerman, bpf, ast, andrii, daniel, martin.lau,
kernel-team, yonghong.song, emil, arighi
On Tue, Mar 17, 2026 at 04:37:59PM +0100, Paul Chaignon wrote:
> On Thu, Mar 12, 2026 at 02:45:47PM +0800, Shung-Hsi Yu wrote:
> > On Fri, Mar 06, 2026 at 01:24:28AM +0100, Paul Chaignon wrote:
> > > On Thu, Mar 05, 2026 at 04:18:42PM -0800, Eduard Zingerman wrote:
> > > > On Fri, 2026-03-06 at 01:13 +0100, Paul Chaignon wrote:
> > > > > On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
> > >
> > > [...]
> > >
> > > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > > index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> > > > > > --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > > +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > > @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
> > >
> > > [...]
> > >
> > > > > Don't we usually put changes to this file in a separate commit, as for
> > > > > test changes in general?
> > > >
> > > > W/o this change the reg_bounds.c tests would fail.
> > > > So far we tried to keep selftests passing for every commit,
> > > > to help with any potential bisecting.
> >
> > Similarly we have stable AUTOSEL tends to just pick up kernel/bpf/
> > changes and not the selftests ones. e.g. both 76e954155b45 ("bpf:
> > Introduce tnum_step to step through tnum's members") and efc11a667878
> > ("bpf: Improve bounds when tnum has a single possible value") got picked
> > for 6.18.17-rc1, but not 024cea2d647e "selftests/bpf: Avoid
> > simplification of crafted bounds test".
>
> I can send the selftest backports to the stable ml (unless you already
> are on it?)
Requested in https://lore.kernel.org/all/xbjybmha7fdnnm5gn6p6jyppf4ud2r72rfabvej6egg545ozsu@a4qj43d3iu36/
We should be good now.
> Do you know if there's anything I could have done differently to have
> the selftests picked up? ...
In this specific case above it would to be have the selftest change
along with the kernel/bpf/verifier.c changes, all in one commit, like
Eduard has reasoned.
> Or maybe something we could change in AUTOSEL?
We can argue that the selftest was dependency that should go together,
and that AUTOSEL should pick it up, but IIRC it is design to only pick
up dependencies that comes before a commit. OTOH it would be nice to
have it try picking up selftests in the same series whenever it picks a
commit from there, but that sounds like a bigger ask.
...
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH bpf v2 1/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary
2026-03-19 7:03 ` Shung-Hsi Yu
@ 2026-03-19 10:21 ` Paul Chaignon
0 siblings, 0 replies; 19+ messages in thread
From: Paul Chaignon @ 2026-03-19 10:21 UTC (permalink / raw)
To: Shung-Hsi Yu
Cc: Eduard Zingerman, bpf, ast, andrii, daniel, martin.lau,
kernel-team, yonghong.song, emil, arighi
On Thu, Mar 19, 2026 at 03:03:07PM +0800, Shung-Hsi Yu wrote:
> On Tue, Mar 17, 2026 at 04:37:59PM +0100, Paul Chaignon wrote:
> > On Thu, Mar 12, 2026 at 02:45:47PM +0800, Shung-Hsi Yu wrote:
> > > On Fri, Mar 06, 2026 at 01:24:28AM +0100, Paul Chaignon wrote:
> > > > On Thu, Mar 05, 2026 at 04:18:42PM -0800, Eduard Zingerman wrote:
> > > > > On Fri, 2026-03-06 at 01:13 +0100, Paul Chaignon wrote:
> > > > > > On Thu, Mar 05, 2026 at 11:48:22AM -0800, Eduard Zingerman wrote:
> > > >
> > > > [...]
> > > >
> > > > > > > diff --git a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > > > index 0322f817d07be5d003c17dd7cedfa3aa4197678e..04938d0d431b38e086b50fe28b99e4ad2682742e 100644
> > > > > > > --- a/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > > > +++ b/tools/testing/selftests/bpf/prog_tests/reg_bounds.c
> > > > > > > @@ -422,15 +422,69 @@ static bool is_valid_range(enum num_t t, struct range x)
> > > >
> > > > [...]
> > > >
> > > > > > Don't we usually put changes to this file in a separate commit, as for
> > > > > > test changes in general?
> > > > >
> > > > > W/o this change the reg_bounds.c tests would fail.
> > > > > So far we tried to keep selftests passing for every commit,
> > > > > to help with any potential bisecting.
> > >
> > > Similarly we have stable AUTOSEL tends to just pick up kernel/bpf/
> > > changes and not the selftests ones. e.g. both 76e954155b45 ("bpf:
> > > Introduce tnum_step to step through tnum's members") and efc11a667878
> > > ("bpf: Improve bounds when tnum has a single possible value") got picked
> > > for 6.18.17-rc1, but not 024cea2d647e "selftests/bpf: Avoid
> > > simplification of crafted bounds test".
> >
> > I can send the selftest backports to the stable ml (unless you already
> > are on it?)
>
> Requested in https://lore.kernel.org/all/xbjybmha7fdnnm5gn6p6jyppf4ud2r72rfabvej6egg545ozsu@a4qj43d3iu36/
>
> We should be good now.
Thanks!
>
> > Do you know if there's anything I could have done differently to have
> > the selftests picked up? ...
>
> In this specific case above it would to be have the selftest change
> along with the kernel/bpf/verifier.c changes, all in one commit, like
> Eduard has reasoned.
I realized after sending that I was probably unclear. I meant anything I
could have done to have the *new* selftests picked up. From your answer
below, it sounds like no.
>
> > Or maybe something we could change in AUTOSEL?
>
> We can argue that the selftest was dependency that should go together,
> and that AUTOSEL should pick it up, but IIRC it is design to only pick
> up dependencies that comes before a commit. OTOH it would be nice to
> have it try picking up selftests in the same series whenever it picks a
> commit from there, but that sounds like a bigger ask.
Agree it would be nice but probably too much load for stable, even
assuming we have a fully-working stable BPF CI :(
>
> ...
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-03-19 10:21 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-03-05 19:48 [PATCH bpf v2 0/2] bpf: refine u32/s32 bounds when ranges cross min/max boundary Eduard Zingerman
2026-03-05 19:48 ` [PATCH bpf v2 1/2] " Eduard Zingerman
2026-03-05 20:28 ` bot+bpf-ci
2026-03-05 20:31 ` Eduard Zingerman
2026-03-05 20:51 ` Emil Tsalapatis
2026-03-06 0:13 ` Paul Chaignon
2026-03-06 0:18 ` Eduard Zingerman
2026-03-06 0:24 ` Paul Chaignon
2026-03-12 6:45 ` Shung-Hsi Yu
2026-03-17 15:37 ` Paul Chaignon
2026-03-19 7:03 ` Shung-Hsi Yu
2026-03-19 10:21 ` Paul Chaignon
2026-03-05 19:48 ` [PATCH bpf v2 2/2] selftests/bpf: test refining " Eduard Zingerman
2026-03-05 19:54 ` Eduard Zingerman
2026-03-05 20:54 ` Emil Tsalapatis
2026-03-05 20:55 ` Emil Tsalapatis
2026-03-06 0:21 ` Paul Chaignon
2026-03-05 22:59 ` [PATCH bpf v2 0/2] bpf: refine " Eduard Zingerman
2026-03-06 5:17 ` Shung-Hsi Yu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox