Skip to content

Commit 13c0288

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 647585d commit 13c0288

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
@@ -17442,6 +17442,13 @@ static bool check_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
1744217442
* and r7.id=0 (both independent), without temp IDs both would map old_id=X
1744317443
* to cur_id=0 and pass. With temp IDs: r6 maps X->temp1, r7 tries to map
1744417444
* X->temp2, but X is already mapped to temp1, so the check fails correctly.
17445+
*
17446+
* When old_id has BPF_ADD_CONST set, the compound id (base | flag) and the
17447+
* base id (flag stripped) must both map consistently. Example: old has
17448+
* r2.id=A, r3.id=A|flag (r3 = r2 + delta), cur has r2.id=B, r3.id=C|flag
17449+
* (r3 derived from unrelated r4). Without the base check, idmap gets two
17450+
* independent entries A->B and A|flag->C|flag, missing that A->C conflicts
17451+
* with A->B. The base ID cross-check catches this.
1744517452
*/
1744617453
static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
1744717454
{
@@ -17450,7 +17457,15 @@ static bool check_scalar_ids(u32 old_id, u32 cur_id, struct bpf_idmap *idmap)
1745017457

1745117458
cur_id = cur_id ? cur_id : ++idmap->tmp_id_gen;
1745217459

17453-
return check_ids(old_id, cur_id, idmap);
17460+
if (!check_ids(old_id, cur_id, idmap))
17461+
return false;
17462+
if (old_id & BPF_ADD_CONST) {
17463+
old_id &= ~BPF_ADD_CONST;
17464+
cur_id &= ~BPF_ADD_CONST;
17465+
if (!check_ids(old_id, cur_id, idmap))
17466+
return false;
17467+
}
17468+
return true;
1745417469
}
1745517470

1745617471
static void clean_func_state(struct bpf_verifier_env *env,

0 commit comments

Comments
 (0)