Commit b88822d2584f for kernel

commit b88822d2584f78cbdad1d8256510dcac108b5630
Author: Alexei Starovoitov <ast@kernel.org>
Date:   Thu Oct 1 14:52:54 2026 +0000

    bpf: Fix packet range of pointers sharing an id

    Since commit 022ac0750883 ("bpf: use reg->var_off instead of reg->off
    for pointers"), find_good_pkt_pointers() sets the range of all packet
    pointers sharing an id from the umax of the compared pointer, and
    check_packet_access() requires umax + off + size <= range.  That assumes
    the umax of two such pointers differ by exactly their constant distance.
    reg_bounds_sync() breaks it when var_off tightens one umax and not the
    other:

            r4 &= 0x38
            if r4 > 50 goto exit     ; umax 50, var_off (0x0; 0x38)
            r5 = pkt + r4            ; umax 50
            r6 = r5
            r6 += 8                  ; umax 56, not 58

    Comparing r6 with pkt_end sets the range to 56, and the valid 8-byte
    load at r5 is rejected (50 + 8 > 56).  Comparing r5 sets it to 50, and
    the out-of-bounds 1-byte load at r6 - 7, i.e. r5 + 1, is accepted
    (56 - 7 + 1 <= 50).

    Don't call reg_bounds_sync() on a packet pointer that keeps its id (a
    constant was added or subtracted) or its range (an unknown non-negative
    value was subtracted), so that var_off cannot tighten its umax.  Only
    update the 32-bit bounds from var_off: reg_bounds_sanity_check() wants
    them constant when the lower half of var_off is, e.g. for pkt + 8.

    This relies on nothing else changing the 64-bit bounds of a packet
    pointer, which holds today.

    var_off of such a pointer is no longer narrowed by its bounds.  Adjust
    three verifier_align expectations; the low bits, which the alignment
    checks use, don't change.  veristat on the selftests shows no verdict
    changes and +0.8% insns in test_cls_redirect_subprogs.

    Fixes: 022ac0750883 ("bpf: use reg->var_off instead of reg->off for pointers")
    Signed-off-by: Alexei Starovoitov <ast@kernel.org>
    Link: https://lore.kernel.org/bpf/20261001145255.855630-1-alexei.starovoitov@gmail.com
    Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>

diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 41b49c56e123..5f874979b8d7 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -14826,7 +14826,15 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, struct bpf_insn
 			"Tighten the scalar bounds before the arithmetic so the resulting pointer remains within the allowed range.");
 		return -EINVAL;
 	}
-	reg_bounds_sync(dst_reg);
+	/*
+	 * A packet pointer that keeps its id or range is checked against a
+	 * range set from the checked pointer's umax, so var_off must not tighten
+	 * its umax. r32 must still match var_off for reg_bounds_sanity_check().
+	 */
+	if (reg_is_pkt_pointer(dst_reg) && (known || dst_reg->range > 0))
+		__update_reg32_bounds(dst_reg);
+	else
+		reg_bounds_sync(dst_reg);
 	bounds_ret = sanitize_check_bounds(env, insn, dst_reg);
 	if (bounds_ret == -EACCES)
 		return bounds_ret;
diff --git a/tools/testing/selftests/bpf/progs/verifier_align.c b/tools/testing/selftests/bpf/progs/verifier_align.c
index 3e52686515ca..0083ef8b8ba7 100644
--- a/tools/testing/selftests/bpf/progs/verifier_align.c
+++ b/tools/testing/selftests/bpf/progs/verifier_align.c
@@ -284,7 +284,7 @@ __msg("26: {{.*}} R5=pkt(r=8,imm=14)")
  */
 __msg("28: {{.*}} R4={{[^)]*}}var_off=(0x2; 0x7fc){{.*}} R5={{[^)]*}}var_off=(0x2; 0x7fc)")
 /* Constant is added to R5 again, setting reg->off to 18. */
-__msg("29: {{.*}} R5=pkt(id=3,{{[^)]*}}var_off=(0x2; 0x7fc)")
+__msg("29: {{.*}} R5=pkt(id=3,{{[^)]*}}var_off=(0x2; 0xffc)")
 /* And once more we add a variable; resulting {{[^)]*}}var_off
  * is still (4n), fixed offset is not changed.
  * Also, we create a new reg->id.
@@ -359,7 +359,7 @@ __msg("7: {{.*}} R6={{[^)]*}}var_off=(0x0; 0x3fc)")
 __msg("8: {{.*}} R6={{[^)]*}}var_off=(0x2; 0x7fc)")
 /* Packet pointer has (4n+2) offset */
 __msg("11: {{.*}} R5={{[^)]*}}var_off=(0x2; 0x7fc)")
-__msg("12: {{.*}} R4={{[^)]*}}var_off=(0x2; 0x7fc)")
+__msg("12: {{.*}} R4={{[^)]*}}var_off=(0x2; 0xffc)")
 /* At the time the word size load is performed from R5,
  * its total fixed offset is NET_IP_ALIGN + reg->off (0)
  * which is 2.  Then the variable offset is (4n+2), so
@@ -375,7 +375,7 @@ __msg("17: {{.*}} R6={{[^)]*}}var_off=(0x0; 0x3fc)")
  * another (4n+2).
  */
 __msg("19: {{.*}} R5={{[^)]*}}var_off=(0x2; 0xffc)")
-__msg("20: {{.*}} R4={{[^)]*}}var_off=(0x2; 0xffc)")
+__msg("20: {{.*}} R4={{[^)]*}}var_off=(0x2; 0x1ffc)")
 /* At the time the word size load is performed from R5,
  * its total fixed offset is NET_IP_ALIGN + reg->off (0)
  * which is 2.  Then the variable offset is (4n+2), so