Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

bpf: Track spill/fill of bounded scalars.

Under register pressure the llvm may spill registers with bounds into the stack.
The verifier has to track them through spill/fill otherwise many kinds of bound
errors will be seen. The spill/fill of induction variables was already
happening. This patch extends this logic from tracking spill/fill of a constant
into any bounded register. There is no need to track spill/fill of unbounded,
since no new information will be retrieved from the stack during register fill.

Though extra stack difference could cause state pruning to be less effective, no
adverse affects were seen from this patch on selftests and on cilium programs.

Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Acked-by: Andrii Nakryiko <andrii@kernel.org>
Acked-by: John Fastabend <john.fastabend@gmail.com>
Link: https://lore.kernel.org/bpf/20201009011240.48506-3-alexei.starovoitov@gmail.com

authored by

Yonghong Song and committed by
Daniel Borkmann
5689d49b 75748837

+15 -1
+15 -1
kernel/bpf/verifier.c
··· 2227 2227 return reg->type == SCALAR_VALUE && tnum_is_const(reg->var_off); 2228 2228 } 2229 2229 2230 + static bool __is_scalar_unbounded(struct bpf_reg_state *reg) 2231 + { 2232 + return tnum_is_unknown(reg->var_off) && 2233 + reg->smin_value == S64_MIN && reg->smax_value == S64_MAX && 2234 + reg->umin_value == 0 && reg->umax_value == U64_MAX && 2235 + reg->s32_min_value == S32_MIN && reg->s32_max_value == S32_MAX && 2236 + reg->u32_min_value == 0 && reg->u32_max_value == U32_MAX; 2237 + } 2238 + 2239 + static bool register_is_bounded(struct bpf_reg_state *reg) 2240 + { 2241 + return reg->type == SCALAR_VALUE && !__is_scalar_unbounded(reg); 2242 + } 2243 + 2230 2244 static bool __is_pointer_value(bool allow_ptr_leaks, 2231 2245 const struct bpf_reg_state *reg) 2232 2246 { ··· 2292 2278 if (value_regno >= 0) 2293 2279 reg = &cur->regs[value_regno]; 2294 2280 2295 - if (reg && size == BPF_REG_SIZE && register_is_const(reg) && 2281 + if (reg && size == BPF_REG_SIZE && register_is_bounded(reg) && 2296 2282 !register_is_null(reg) && env->bpf_capable) { 2297 2283 if (dst_reg != BPF_REG_FP) { 2298 2284 /* The backtracking logic can only recognize explicit