All of lore.kernel.org
 help / color / mirror / Atom feed
From: Shung-Hsi Yu <shung-hsi.yu@suse.com>
To: Andrii Nakryiko <andrii.nakryiko@gmail.com>
Cc: Andrii Nakryiko <andrii@kernel.org>,
	bpf@vger.kernel.org, ast@kernel.org, daniel@iogearbox.net,
	martin.lau@kernel.org, kernel-team@meta.com
Subject: Re: [PATCH v4 bpf-next 3/7] bpf: enhance subregister bounds deduction logic
Date: Tue, 24 Oct 2023 20:05:38 +0800	[thread overview]
Message-ID: <ZTezEiltEz8Gab5B@u94a> (raw)
In-Reply-To: <CAEf4BzZeOt-u+vZsrdj_8o6hMCiPuYrvE5=CCfAhDadSLTC42g@mail.gmail.com>

On Mon, Oct 23, 2023 at 09:23:57AM -0700, Andrii Nakryiko wrote:
> On Sun, Oct 22, 2023 at 8:57 PM Shung-Hsi Yu <shung-hsi.yu@suse.com> wrote:
> >
> > On Mon, Oct 23, 2023 at 11:20:46AM +0800, Shung-Hsi Yu wrote:
> > > On Sun, Oct 22, 2023 at 01:57:39PM -0700, Andrii Nakryiko wrote:
> > > > Add handling of a bunch of possible cases which allows deducing extra
> > > > information about subregister bounds, both u32 and s32, from full register
> > > > u64/s64 bounds.
> > > >
> > > > Also add smin32/smax32 bounds derivation from corresponding umin32/umax32
> > > > bounds, similar to what we did with smin/smax from umin/umax derivation in
> > > > previous patch.
> > > >
> > > > Signed-off-by: Andrii Nakryiko <andrii@kernel.org>
> > > >
> > > > ---
> > > >  kernel/bpf/verifier.c | 52 +++++++++++++++++++++++++++++++++++++++++++
> > > >  1 file changed, 52 insertions(+)
> > > >
> > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > index 885dd4a2ff3a..3fc9bd5e72b8 100644
> > > > --- a/kernel/bpf/verifier.c
> > > > +++ b/kernel/bpf/verifier.c
> > > > @@ -2130,6 +2130,58 @@ static void __update_reg_bounds(struct bpf_reg_state *reg)
> > > >  /* Uses signed min/max values to inform unsigned, and vice-versa */
> > > >  static void __reg32_deduce_bounds(struct bpf_reg_state *reg)
> > > >  {
> > > > +   /* if upper 32 bits of u64/s64 range don't change,
> > > > +    * we can use lower 32 bits to improve our u32/s32 boundaries
> > > > +    */
> > > > +   if ((reg->umin_value >> 32) == (reg->umax_value >> 32)) {
> > > > +           /* u64 to u32 casting preserves validity of low 32 bits as
> > > > +            * a range, if upper 32 bits are the same
> > > > +            */
> > > > +           reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)reg->umin_value);
> > > > +           reg->u32_max_value = min_t(u32, reg->u32_max_value, (u32)reg->umax_value);
> > > > +
> > > > +           if ((s32)reg->umin_value <= (s32)reg->umax_value) {
> > > > +                   reg->s32_min_value = max_t(s32, reg->s32_min_value, (s32)reg->umin_value);
> > > > +                   reg->s32_max_value = min_t(s32, reg->s32_max_value, (s32)reg->umax_value);
> > > > +           }
> > > > +   }
> > > > +   if ((reg->smin_value >> 32) == (reg->smax_value >> 32)) {
> > > > +           /* low 32 bits should form a proper u32 range */
> > > > +           if ((u32)reg->smin_value <= (u32)reg->smax_value) {
> > > > +                   reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)reg->smin_value);
> > > > +                   reg->u32_max_value = min_t(u32, reg->u32_max_value, (u32)reg->smax_value);
> > > > +           }
> > > > +           /* low 32 bits should form a proper s32 range */
> > > > +           if ((s32)reg->smin_value <= (s32)reg->smax_value) {
> > > > +                   reg->s32_min_value = max_t(s32, reg->s32_min_value, (s32)reg->smin_value);
> > > > +                   reg->s32_max_value = min_t(s32, reg->s32_max_value, (s32)reg->smax_value);
> > > > +           }
> > > > +   }
> > > > +   /* Special case where upper bits form a small sequence of two
> > > > +    * sequential numbers (in 32-bit unsigned space, so 0xffffffff to
> > > > +    * 0x00000000 is also valid), while lower bits form a proper s32 range
> > > > +    * going from negative numbers to positive numbers.
> > > > +    * E.g.: [0xfffffff0ffffff00; 0xfffffff100000010]. Iterating
> > > > +    * over full 64-bit numbers range will form a proper [-16, 16]
> > > > +    * ([0xffffff00; 0x00000010]) range in its lower 32 bits.
> > > > +    */
> >
> > ... [graph removed]
> 
> Yeah, tbh, the graphs above weren't really all that helpful, rather
> more confusing. But I think you got the point correctly, that we are
> stitching two s32 ranges, if we can. And we can if upper 32 bits are
> two consecutive numbers and lower 32-bits goes from negative to
> positive (as s32).

Alright, graph removed. FWIW I think "stitching two s32 ranges together" is
a great way to put it concisely to give some intuitive sense, it'd be nice
if it can be incorporated into the above comment.

> > > > +   if ((u32)(reg->umin_value >> 32) + 1 == (u32)(reg->umax_value >> 32) &&
> > > > +       (s32)reg->umin_value < 0 && (s32)reg->umax_value >= 0) {
> > > > +           reg->s32_min_value = max_t(s32, reg->s32_min_value, (s32)reg->umin_value);
> > > > +           reg->s32_max_value = min_t(s32, reg->s32_max_value, (s32)reg->umax_value);
> > > > +   }
> > > > +   if ((u32)(reg->smin_value >> 32) + 1 == (u32)(reg->smax_value >> 32) &&
> > > > +       (s32)reg->smin_value < 0 && (s32)reg->smax_value >= 0) {
> > > > +           reg->s32_min_value = max_t(s32, reg->s32_min_value, (s32)reg->smin_value);
> > > > +           reg->s32_max_value = min_t(s32, reg->s32_max_value, (s32)reg->smax_value);
> > > > +   }
> > > > +   /* if u32 range forms a valid s32 range (due to matching sign bit),
> > > > +    * try to learn from that
> > > > +    */
> > > > +   if ((s32)reg->u32_min_value <= (s32)reg->u32_max_value) {
> > > > +           reg->s32_min_value = max_t(s32, reg->s32_min_value, reg->u32_min_value);
> > > > +           reg->s32_max_value = min_t(s32, reg->s32_max_value, reg->u32_max_value);
> > > > +   }
> > > >     /* Learn sign from signed bounds.
> > > >      * If we cannot cross the sign boundary, then signed and unsigned bounds
> > > >      * are the same, so combine.  This works even in the negative case, e.g.
> > > > --
> > > > 2.34.1
> > > >

  reply	other threads:[~2023-10-24 12:05 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-10-22 20:57 [PATCH v4 bpf-next 0/7] BPF register bounds logic and testing improvements Andrii Nakryiko
2023-10-22 20:57 ` [PATCH v4 bpf-next 1/7] bpf: improve JEQ/JNE branch taken logic Andrii Nakryiko
2023-10-23  2:33   ` Shung-Hsi Yu
2023-10-22 20:57 ` [PATCH v4 bpf-next 2/7] bpf: derive smin/smax from umin/max bounds Andrii Nakryiko
2023-10-23  2:36   ` Shung-Hsi Yu
2023-10-24 13:08   ` Daniel Borkmann
2023-10-24 14:53     ` Andrii Nakryiko
2023-10-24 15:43       ` Daniel Borkmann
2023-10-22 20:57 ` [PATCH v4 bpf-next 3/7] bpf: enhance subregister bounds deduction logic Andrii Nakryiko
2023-10-23  3:20   ` Shung-Hsi Yu
2023-10-23  3:56     ` Shung-Hsi Yu
2023-10-23 16:23       ` Andrii Nakryiko
2023-10-24 12:05         ` Shung-Hsi Yu [this message]
2023-10-24 12:22   ` Shung-Hsi Yu
2023-10-24 15:31     ` Alexei Starovoitov
2023-10-27  8:16       ` Shung-Hsi Yu
2023-10-22 20:57 ` [PATCH v4 bpf-next 4/7] bpf: improve deduction of 64-bit bounds from 32-bit bounds Andrii Nakryiko
2023-10-22 20:57 ` [PATCH v4 bpf-next 5/7] bpf: try harder to deduce register bounds from different numeric domains Andrii Nakryiko
2023-10-22 20:57 ` [PATCH v4 bpf-next 6/7] bpf: drop knowledge-losing __reg_combine_{32,64}_into_{64,32} logic Andrii Nakryiko
2023-10-22 20:57 ` [PATCH v4 bpf-next 7/7] selftests/bpf: BPF register range bounds tester Andrii Nakryiko
2023-10-22 23:01   ` kernel test robot
2023-10-24 13:40 ` [PATCH v4 bpf-next 0/7] BPF register bounds logic and testing improvements patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=ZTezEiltEz8Gab5B@u94a \
    --to=shung-hsi.yu@suse.com \
    --cc=andrii.nakryiko@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=kernel-team@meta.com \
    --cc=martin.lau@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.