mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
bpf: Reject pointer operands for 32-bit recurrences/latches
Avoid inferring loop bounds for the following program shapes:
32-bit latch (A) | 32-bit recurrence (B)
-------------------------+--------------------------
r1 = ... pointer ... | r1 = ... pointer ...
r2 = ... pointer ... | r2 = ... pointer ...
l: r1 += 8 | l: w1 += 8
... | ...
if w1 < w2 goto l | if r1 < r2 goto l
(A) Scalar bounds for pointers represent only offsets from their
common origin values. The 32-bit operations also depend on the
runtime base address: the addresses can wrap at 32 bits without
the tracked offsets wrapping. Thus, offsets alone do not determine
the iteration count.
(B) 32-bit operations on pointers either prohibited (wX += 1)
or convert them to scalars (wX = wX). No need to deal with
this at SCEV level.
Fixes: 32e962577d ("bpf: Support 32-bit linear scalar evolution")
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261026-scev-simpler-clamp-v2-1-f373aec9825f@gmail.com
This commit is contained in:
parent
195a3519ff
commit
c463b378ea
|
|
@ -2024,7 +2024,8 @@ static void log_incompatible_scev_values(struct bpf_verifier_env *env, const cha
|
|||
}
|
||||
|
||||
static bool scev_value_compatible(struct bpf_verifier_env *env, struct bpf_func_state *st,
|
||||
const struct scev_value *a, const struct scev_value *b)
|
||||
const struct scev_value *a, const struct scev_value *b,
|
||||
const struct linear_latch *latch)
|
||||
{
|
||||
const struct bpf_reg_state *ra, *rb;
|
||||
|
||||
|
|
@ -2035,7 +2036,7 @@ static bool scev_value_compatible(struct bpf_verifier_env *env, struct bpf_func_
|
|||
}
|
||||
ra = scev_reg_for_read(env, st, a->ptr_reg);
|
||||
rb = scev_reg_for_read(env, st, b->ptr_reg);
|
||||
if (ra && rb && bpf_same_memory_origin(ra, rb))
|
||||
if (ra && rb && bpf_same_memory_origin(ra, rb) && !latch->zext32 && !latch->jmp32)
|
||||
return true;
|
||||
|
||||
incompatible:
|
||||
|
|
@ -2267,7 +2268,7 @@ static bool compute_max_iters(struct bpf_verifier_env *env,
|
|||
}
|
||||
return false;
|
||||
}
|
||||
if (!scev_value_compatible(env, st, &initial_val, &bound_val))
|
||||
if (!scev_value_compatible(env, st, &initial_val, &bound_val, latch))
|
||||
return false;
|
||||
|
||||
initial = initial_val.value;
|
||||
|
|
@ -2700,6 +2701,9 @@ int bpf_compute_loop_iters(struct bpf_verifier_env *env, struct bpf_verifier_sta
|
|||
reg = scev_reg_for_linear(cur_func, r);
|
||||
/* If SCEV for r is (linear <reg> <slope>) */
|
||||
if (reg && is_simple_linear(scev, r_scev, &coefs) && is_widenable_reg_type(reg)) {
|
||||
/* 32-bit ALU operations on pointers convert them to scalars */
|
||||
if (coefs.zext32 && reg->type != SCALAR_VALUE)
|
||||
goto cant_widen;
|
||||
/* Spills at varying offsets lose precision */
|
||||
if (test_bit(r, loop->store_base_regs)) {
|
||||
spill_base = true;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user