Re: [PATCH bpf-next] bpf: Simplify bounds refinement from s32

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Fri, Jul 25, 2025 at 05:21:38PM +0800, Shung-Hsi Yu wrote:
> On Thu, Jul 24, 2025 at 02:49:47PM -0700, Eduard Zingerman wrote:
> > On Thu, 2025-07-24 at 19:42 +0200, Paul Chaignon wrote:
> > > During the bounds refinement, we improve the precision of various ranges
> > > by looking at other ranges. Among others, we improve the following in
> > > this order (other things happen between 1 and 2):
> > > 
> > >   1. Improve u32 from s32 in __reg32_deduce_bounds.
> > >   2. Improve s/u64 from u32 in __reg_deduce_mixed_bounds.
> > >   3. Improve s/u64 from s32 in __reg_deduce_mixed_bounds.
> > > 
> > > In particular, if the s32 range forms a valid u32 range, we will use it
> > > to improve the u32 range in __reg32_deduce_bounds. In
> > > __reg_deduce_mixed_bounds, under the same condition, we will use the s32
> > > range to improve the s/u64 ranges.
> > > 
> > > If at (1) we were able to learn from s32 to improve u32, we'll then be
> > > able to use that in (2) to improve s/u64. Hence, as (3) happens under
> > > the same precondition as (1), it won't improve s/u64 ranges further than
> > > (1)+(2) did. Thus, we can get rid of (3).
> > > 
> > > In addition to the extensive suite of selftests for bounds refinement,
> > > this patch was also tested with the Agni formal verification tool [1].
> > > 
> > > Link: https://github.com/bpfverif/agni [1]
> > > Signed-off-by: Paul Chaignon <paul.chaignon@xxxxxxxxx>
> > > ---
> > 
> > So, the argument appears to be as follows:
> > 
> > Under precondition `(u32)reg->s32_min <= (u32)reg->s32_max`
> > __reg32_deduce_bounds produces:
> > 
> >   reg->u32_min = max_t(u32, reg->s32_min, reg->u32_min);
> >   reg->u32_max = min_t(u32, reg->s32_max, reg->u32_max);
> > 
> > And then first part of __reg_deduce_mixed_bounds assigns:
> > 
> >   a. reg->umin umax= (reg->umin & ~0xffffffffULL) | max_t(u32, reg->s32_min, reg->u32_min);
> >   b. reg->umax umin= (reg->umax & ~0xffffffffULL) | min_t(u32, reg->s32_max, reg->u32_max);
> > 
> > And then second part of __reg_deduce_mixed_bounds assigns:
> > 
> >   c. reg->umin umax= (reg->umin & ~0xffffffffULL) | (u32)reg->s32_min;
> >   d. reg->umax umin= (reg->umax & ~0xffffffffULL) | (u32)reg->s32_max;
> > 
> > But assignment (c) is a noop because:
> > 
> >    max_t(u32, reg->s32_min, reg->u32_min) >= (u32)reg->s32_min
> > 
> > Hence RHS(a) >= RHS(c) and umin= does nothing.
> > 
> > Also assignment (d) is a noop because:
> > 
> >   min_t(u32, reg->s32_max, reg->u32_max) <= (u32)reg->s32_max
> > 
> > Hence RHS(b) <= RHS(d) and umin= does nothing.
> > 
> > Plus the same reasoning for the part dealing with reg->s{min,max}_value:
> > 
> >   e. reg->smin_value smax= (reg->smin_value & ~0xffffffffULL) | max_t(u32, reg->s32_min_value, reg->u32_min_value);
> >   f. reg->smax_value smin= (reg->smax_value & ~0xffffffffULL) | min_t(u32, reg->s32_max_value, reg->u32_max_value);
> > 
> >     vs
> > 
> >   g. reg->smin_value smax= (reg->smin_value & ~0xffffffffULL) | (u32)reg->s32_min_value;
> >   h. reg->smax_value smin= (reg->smax_value & ~0xffffffffULL) | (u32)reg->s32_max_value;
> > 
> >     RHS(e) >= RHS(g) and RHS(f) <= RHS(h), hence smax=,smin= do nothing.
> > 
> > This appears to be correct.
> > 
> > Shung-Hsi, wdyt?
> 
> Agree with the reasoning above, it looks solid.
> 
> Beside going through the reasoning, I also played with CBMC a bit to
> double check that as far as a single run of __reg_deduce_bounds() is
> concerned (and that the register state matches certain handwavy
> expectations), the change indeed still preserve the original behavior.

Ah, I didn't even think about checking input-output equivalence. Thanks
for testing this!

> 
> Reviewed-by: Shung-Hsi Yu <shung-hsi.yu@xxxxxxxx>
> 
> Simplification of bound deduction logic! \o/

Yeah, I'll admit it felt too good to be true :')
I feel more confident with both of your reviews. Thank you both for
reviewing this closely!

[...]





[Index of Archives]     [Linux Samsung SoC]     [Linux Rockchip SoC]     [Linux Actions SoC]     [Linux for Synopsys ARC Processors]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]


  Powered by Linux