Skip to content

Commit 691adf7

Browse files
borkmanngregkh
authored andcommitted
bpf: Enforce regsafe base id consistency for BPF_ADD_CONST scalars
[ Upstream commit 2f2ec8e ] When regsafe() compares two scalar registers that both carry BPF_ADD_CONST, check_scalar_ids() maps their full compound id (aka base | BPF_ADD_CONST flag) as one idmap entry. However, it never verifies that the underlying base ids, that is, with the flag stripped are consistent with existing idmap mappings. This allows construction of two verifier states where the old state has R3 = R2 + 10 (both sharing base id A) while the current state has R3 = R4 + 10 (base id C, unrelated to R2). The idmap creates two independent entries: A->B (for R2) and A|flag->C|flag (for R3), without catching that A->C conflicts with A->B. State pruning then incorrectly succeeds. Fix this by additionally verifying base ID mapping consistency whenever BPF_ADD_CONST is set: after mapping the compound ids, also invoke check_ids() on the base IDs (flag bits stripped). This ensures that if A was already mapped to B from comparing the source register, any ADD_CONST derivative must also derive from B, not an unrelated C. Fixes: 98d7ca3 ("bpf: Track delta between "linked" registers.") Reported-by: STAR Labs SG <info@starlabs.sg> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Link: https://lore.kernel.org/r/20260410232651.559778-1-daniel@iogearbox.net Signed-off-by: Alexei Starovoitov <ast@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent adaee08 commit 691adf7

1 file changed

Lines changed: 16 additions & 1 deletion

File tree

kernel/bpf/verifier.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18825,6 +18825,13 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
1882518825
* and r7.id=0 (both independent), without temp IDs both would map old_id=X
1882618826
* to cur_id=0 and pass. With temp IDs: r6 maps X->temp1, r7 tries to map
1882718827
* X->temp2, but X is already mapped to temp1, so the check fails correctly.
18828+
*
18829+
* When old_id has BPF_ADD_CONST set, the compound id (base | flag) and the
18830+
* base id (flag stripped) must both map consistently. Example: old has
18831+
* r2.id=A, r3.id=A|flag (r3 = r2 + delta), cur has r2.id=B, r3.id=C|flag
18832+
* (r3 derived from unrelated r4). Without the base check, idmap gets two
18833+
* independent entries A->B and A|flag->C|flag, missing that A->C conflicts
18834+
* with A->B. The base ID cross-check catches this.
1882818835
*/
1882918836
static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
1883018837
{
@@ -18833,7 +18840,15 @@ static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
1883318840

1883418841
cur_id = cur_id ? cur_id : ++idmap->tmp_id_gen;
1883518842

18836-
return check_ids(old_id, cur_id, idmap);
18843+
if (!check_ids(old_id, cur_id, idmap))
18844+
return false;
18845+
if (old_id & BPF_ADD_CONST) {
18846+
old_id &= ~BPF_ADD_CONST;
18847+
cur_id &= ~BPF_ADD_CONST;
18848+
if (!check_ids(old_id, cur_id, idmap))
18849+
return false;
18850+
}
18851+
return true;
1883718852
}
1883818853

1883918854
static void clean_func_state(struct bpf_verifier_env *env,

0 commit comments

Comments
 (0)