]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
bpf: Relax maybe_widen_reg() constraints
authorPuranjay Mohan <puranjay@kernel.org>
Tue, 3 Feb 2026 16:50:59 +0000 (08:50 -0800)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 3 Feb 2026 18:34:01 +0000 (10:34 -0800)
The maybe_widen_reg() function widens imprecise scalar registers to
unknown when their values differ between the cached and current states.
Previously, it used regs_exact() which also compared register IDs via
check_ids(), requiring registers to have matching IDs (or mapped IDs) to
be considered exact.

For scalar widening purposes, what matters is whether the value tracking
(bounds, tnum, var_off) is the same, not whether the IDs match. Two
scalars with identical value constraints but different IDs represent the
same abstract value and don't need to be widened.

Introduce scalars_exact_for_widen() that only compares the
value-tracking portion of bpf_reg_state (fields before 'id'). This
allows the verifier to preserve more scalar value information during
state merging when IDs differ but actual tracked values are identical,
reducing unnecessary widening and potentially improving verification
precision.

Signed-off-by: Puranjay Mohan <puranjay@kernel.org>
Link: https://lore.kernel.org/r/20260203165102.2302462-4-puranjay@kernel.org
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
kernel/bpf/verifier.c

index d92e10d4c2cc75ef87734f29add1cc0bbc665be6..80dc01350c77ff277796242f0075e98492011d69 100644 (file)
@@ -8995,15 +8995,24 @@ static bool regs_exact(const struct bpf_reg_state *rold,
                       const struct bpf_reg_state *rcur,
                       struct bpf_idmap *idmap);
 
+/*
+ * Check if scalar registers are exact for the purpose of not widening.
+ * More lenient than regs_exact()
+ */
+static bool scalars_exact_for_widen(const struct bpf_reg_state *rold,
+                                   const struct bpf_reg_state *rcur)
+{
+       return !memcmp(rold, rcur, offsetof(struct bpf_reg_state, id));
+}
+
 static void maybe_widen_reg(struct bpf_verifier_env *env,
-                           struct bpf_reg_state *rold, struct bpf_reg_state *rcur,
-                           struct bpf_idmap *idmap)
+                           struct bpf_reg_state *rold, struct bpf_reg_state *rcur)
 {
        if (rold->type != SCALAR_VALUE)
                return;
        if (rold->type != rcur->type)
                return;
-       if (rold->precise || rcur->precise || regs_exact(rold, rcur, idmap))
+       if (rold->precise || rcur->precise || scalars_exact_for_widen(rold, rcur))
                return;
        __mark_reg_unknown(env, rcur);
 }
@@ -9015,7 +9024,6 @@ static int widen_imprecise_scalars(struct bpf_verifier_env *env,
        struct bpf_func_state *fold, *fcur;
        int i, fr, num_slots;
 
-       reset_idmap_scratch(env);
        for (fr = old->curframe; fr >= 0; fr--) {
                fold = old->frame[fr];
                fcur = cur->frame[fr];
@@ -9023,8 +9031,7 @@ static int widen_imprecise_scalars(struct bpf_verifier_env *env,
                for (i = 0; i < MAX_BPF_REG; i++)
                        maybe_widen_reg(env,
                                        &fold->regs[i],
-                                       &fcur->regs[i],
-                                       &env->idmap_scratch);
+                                       &fcur->regs[i]);
 
                num_slots = min(fold->allocated_stack / BPF_REG_SIZE,
                                fcur->allocated_stack / BPF_REG_SIZE);
@@ -9035,8 +9042,7 @@ static int widen_imprecise_scalars(struct bpf_verifier_env *env,
 
                        maybe_widen_reg(env,
                                        &fold->stack[i].spilled_ptr,
-                                       &fcur->stack[i].spilled_ptr,
-                                       &env->idmap_scratch);
+                                       &fcur->stack[i].spilled_ptr);
                }
        }
        return 0;