lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAHmME9oySGYZ=r5P6dUJnWp5R9TbwGGXLNWm8O5oyES2dn-PwQ@mail.gmail.com>
Date:   Fri, 23 Sep 2022 18:42:56 +0200
From:   "Jason A. Donenfeld" <Jason@...c4.com>
To:     Kees Cook <keescook@...omium.org>
Cc:     Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
        linux-kernel@...r.kernel.org,
        Andrew Morton <akpm@...ux-foundation.org>
Subject: Re: [PATCH v2] minmax: clamp more efficiently by avoiding extra comparison

On Fri, Sep 23, 2022 at 6:41 PM Kees Cook <keescook@...omium.org> wrote:
>
> On Fri, Sep 23, 2022 at 05:40:01PM +0200, Jason A. Donenfeld wrote:
> > Currently the clamp algorithm does:
> >
> >       if (val > hi)
> >               val = hi;
> >       if (val < lo)
> >               val = lo;
> >
> > But since hi > lo by definition, this can be made more efficient with:
> >
> >       if (val > hi)
> >               val = hi;
> >       else if (val < lo)
> >               val = lo;
> >
> > So fix up the clamp and clamp_t functions to do this, adding the same
> > argument checking as for min and min_t.
> >
> > Cc: Andy Shevchenko <andriy.shevchenko@...ux.intel.com>
> > Cc: Andrew Morton <akpm@...ux-foundation.org>
> > Cc: Kees Cook <keescook@...omium.org>
> > Signed-off-by: Jason A. Donenfeld <Jason@...c4.com>
> > ---
> >  include/linux/minmax.h | 25 +++++++++++++++++++++++--
> >  1 file changed, 23 insertions(+), 2 deletions(-)
> >
> > diff --git a/include/linux/minmax.h b/include/linux/minmax.h
> > index 5433c08fcc68..30e2e2cd0f44 100644
> > --- a/include/linux/minmax.h
> > +++ b/include/linux/minmax.h
> > @@ -37,6 +37,27 @@
> >               __cmp(x, y, op), \
> >               __cmp_once(x, y, __UNIQUE_ID(__x), __UNIQUE_ID(__y), op))
> >
> > +#define __clamp(val, lo, hi)                                                 \
> > +     ((val) >= (hi) ? (hi) : ((val) <= (lo) ? (lo) : (val)))
> > +
> > +#define __clamp_once(val, lo, hi, unique_val, unique_lo, unique_hi) ({               \
> > +             typeof(val) unique_val = (val);                                 \
> > +             typeof(lo) unique_lo = (lo);                                    \
> > +             typeof(hi) unique_hi = (hi);                                    \
> > +             __clamp(unique_val, unique_lo, unique_hi); })
> > +
> > +#define __clamp_input_check(lo, hi)                                          \
> > +        (BUILD_BUG_ON_ZERO(__builtin_choose_expr(                            \
> > +                __is_constexpr((lo) > (hi)), (lo) > (hi), false)))
>
> Nice. :)
>
> > +
> > +#define __careful_clamp(val, lo, hi) ({                                              \
> > +     __clamp_input_check(lo, hi) +                                           \
> > +     __builtin_choose_expr(__typecheck(val, lo) && __typecheck(val, hi) &&   \
> > +                           __typecheck(hi, lo) && __is_constexpr(val) &&     \
> > +                           __is_constexpr(lo) && __is_constexpr(hi),         \
>
> I really like it! I might have used:
>
>         __safe_cmp(val, lo) && __safe_cmp(val, hi)
>
> instead of the "open coded" __typecheck()s and __is_constexpr()s, but
> it's the same result.
>
> > +             __clamp(val, lo, hi),                                           \
> > +             __clamp_once(val, lo, hi, __UNIQUE_ID(__val), __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); })
>
> *complaint about line being >100 characters, but I don't really care* If
> anyone is really bothered, this looks fine, too:
>
>                 __clamp_once(val, lo, hi,                                       \
>                              __UNIQUE_ID(__val), __UNIQUE_ID(__lo), __UNIQUE_ID(__hi))); })
>
> *shrug*
>
> > +
> >  /**
> >   * min - return minimum of two values of the same or compatible types
> >   * @x: first value
> > @@ -86,7 +107,7 @@
> >   * This macro does strict typechecking of @lo/@hi to make sure they are of the
> >   * same type as @val.  See the unnecessary pointer comparisons.
> >   */
> > -#define clamp(val, lo, hi) min((typeof(val))max(val, lo), hi)
> > +#define clamp(val, lo, hi) __careful_clamp(val, lo, hi)
> >
> >  /*
> >   * ..and if you can't take the strict
> > @@ -121,7 +142,7 @@
> >   * This macro does no typechecking and uses temporary variables of type
> >   * @type to make all the comparisons.
> >   */
> > -#define clamp_t(type, val, lo, hi) min_t(type, max_t(type, val, lo), hi)
> > +#define clamp_t(type, val, lo, hi) __careful_clamp((type)(val), (type)(lo), (type)(hi))
> >
> >  /**
> >   * clamp_val - return a value clamped to a given range using val's type
> > --
> > 2.37.3
> >
>
> Reviewed-by: Kees Cook <keescook@...omium.org>
>
> I can take this unless akpm wants it?

Fine by me.

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ