diff options
| author | Alexei Starovoitov <ast@kernel.org> | 2026-10-27 19:03:06 +0000 |
|---|---|---|
| committer | Alexei Starovoitov <ast@kernel.org> | 2026-10-28 04:07:03 +0000 |
| commit | 41750e5d682ab0703a9d2af3ec31a508b253b38f (patch) | |
| tree | 65a2fb5d1c02ad4bbe7fc84b0ba225bfb79538ef /kernel/bpf | |
| parent | 3c0ca9f9a98e6b8bbaea13c5e39613237d50fe47 (diff) | |
bpf: Don't widen a pointer to a buffer in scalar evolution
Scalar evolution widens counted loops. Since that change the verifier
rejects a loop over the per-cpu values of a map element:
SEC("iter/bpf_map_elem")
...
for (i = 0; i < n; i++) {
out[i] = *(__u32 *)pptr;
pptr += 8;
}
loop header at 12, widening r2 to 0..56 step 8
R2 invalid variable buffer offset: off=0, var_off=(0x0; 0x38)
pptr is a pointer to a buffer (PTR_TO_BUF). Scalar evolution replaces its
offset with the range over all iterations. But __check_buffer_access()
accepts only a constant offset. Thus a prog cannot use a widened
PTR_TO_BUF.
Do not widen it. Then the verifier verifies the loop one iteration at a
time, as it did before.
loop before SCEV with SCEV this patch
-------------------------------- ----------- ---------- ----------
counts in i, reads through pptr loads rejected loads
counts in p ('p < end'), no read 1M insns loads 1M insns
counts in p, reads through p 1M insns rejected 1M insns
The verifier cannot decide a comparison of two pointers to a buffer. Thus
it follows 'p < end' until the limit of 1M insns.
bpf_iter_bpf_percpu_array_map.c and bpf_iter_bpf_percpu_hash_map.c have the
first loop. They load today because num_cpus is volatile. The prog reads
the bound again in each iteration. Scalar evolution cannot count such a
loop, and it widens nothing.
Fixes: 6ccf49f79327 ("bpf: Use SCEV to widen bounded loops")
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261027190314.1440199-12-alexei.starovoitov@gmail.com
Diffstat (limited to 'kernel/bpf')
| -rw-r--r-- | kernel/bpf/scev.c | 1 |
1 files changed, 0 insertions, 1 deletions
diff --git a/kernel/bpf/scev.c b/kernel/bpf/scev.c index 3f7534cda47a..6231d16aa311 100644 --- a/kernel/bpf/scev.c +++ b/kernel/bpf/scev.c @@ -2379,7 +2379,6 @@ static bool is_widenable_reg_type(const struct bpf_reg_state *reg) case PTR_TO_PACKET: case PTR_TO_PACKET_META: case PTR_TO_MEM: - case PTR_TO_BUF: case PTR_TO_BTF_ID: return true; default: |
