public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
From: David Laight <david.laight.linux@gmail.com>
To: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Cc: LKML <linux-kernel@vger.kernel.org>, bpf <bpf@vger.kernel.org>,
	Alexei Starovoitov <ast@kernel.org>,
	Andrii Nakryiko <andrii@kernel.org>,
	Daniel Borkmann <daniel@iogearbox.net>
Subject: Re: [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t()
Date: Sun, 23 Nov 2025 18:07:41 +0000	[thread overview]
Message-ID: <20251123180741.65cd2dd3@pumpkin> (raw)
In-Reply-To: <CAADnVQJFxWParvYg9_YZaD7HFFPW6yzStm7e1nKgdMQ+UYUtqw@mail.gmail.com>

On Sun, 23 Nov 2025 08:39:51 -0800
Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:

> On Fri, Nov 21, 2025 at 2:21 PM David Laight
> <david.laight.linux@gmail.com> wrote:
> >
> > On Fri, 21 Nov 2025 13:40:36 -0800
> > Alexei Starovoitov <alexei.starovoitov@gmail.com> wrote:
> >  
> > > On Wed, Nov 19, 2025 at 2:42 PM <david.laight.linux@gmail.com> wrote:  
> > > >
> > > > From: David Laight <david.laight.linux@gmail.com>
> > > >
> > > > min_t() and max_t() are normally used to change the signedness
> > > > of a positive value to avoid a signed-v-unsigned compare warning.
> > > >
> > > > However they are used here to convert an unsigned 64bit pattern
> > > > to a signed to a 32/64bit signed number.
> > > > To avoid any confusion use plain min()/max() and explicitely cast
> > > > the u64 expression to the correct signed value.
> > > >
> > > > Use a simple max() for the max_pkt_offset calulation and delete the
> > > > comment about why the cast to u32 is safe.
> > > >
> > > > Signed-off-by: David Laight <david.laight.linux@gmail.com>
> > > > ---
> > > >  kernel/bpf/verifier.c | 29 +++++++++++------------------
> > > >  1 file changed, 11 insertions(+), 18 deletions(-)
> > > >
> > > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > > > index ff40e5e65c43..22fa9769fbdb 100644
> > > > --- a/kernel/bpf/verifier.c
> > > > +++ b/kernel/bpf/verifier.c
> > > > @@ -2319,12 +2319,12 @@ static void __update_reg32_bounds(struct bpf_reg_state *reg)
> > > >         struct tnum var32_off = tnum_subreg(reg->var_off);
> > > >
> > > >         /* min signed is max(sign bit) | min(other bits) */
> > > > -       reg->s32_min_value = max_t(s32, reg->s32_min_value,
> > > > -                       var32_off.value | (var32_off.mask & S32_MIN));
> > > > +       reg->s32_min_value = max(reg->s32_min_value,
> > > > +                       (s32)(var32_off.value | (var32_off.mask & S32_MIN)));
> > > >         /* max signed is min(sign bit) | max(other bits) */
> > > > -       reg->s32_max_value = min_t(s32, reg->s32_max_value,
> > > > -                       var32_off.value | (var32_off.mask & S32_MAX));
> > > > -       reg->u32_min_value = max_t(u32, reg->u32_min_value, (u32)var32_off.value);
> > > > +       reg->s32_max_value = min(reg->s32_max_value,
> > > > +                       (s32)(var32_off.value | (var32_off.mask & S32_MAX)));  
> > >
> > > Nack.
> > > This is plain ugly for no good reason.
> > > Leave the code as-is.  
> >
> > It is really horrid before.
> > From what i remember var32_off.value (and .mask) are both u64.
> > The pattern actually patches that used a few lines down the file.
> >
> > I've been trying to build allmodconfig with the size test added to min_t()
> > and max_t().
> > The number of real (or potentially real) bugs I've found is stunning.
> > The only fix is to nuke min_t() and max_t() to they can't be used.  
> 
> No. min_t() is going to stay. It's not broken and
> this crusade against it is inappropriate.

I bet to differ...

> > The basic problem is the people have used the type of the target not that
> > of the largest parameter.
> > The might be ok for ulong v uint (on 64bit), but there are plenty of places
> > where u16 and u8 are used - a lot are pretty much buggy.
> >
> > Perhaps the worst ones I've found are with clamp_t(),
> > this is from 2/44:
> > -               (raw_inode)->xtime = cpu_to_le32(clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX));      \
> > +               (raw_inode)->xtime = cpu_to_le32(clamp((ts).tv_sec, S32_MIN, S32_MAX)); \
> > If also found clamp_t(u8, xxx, 0, 255).
> >
> > There are just so many broken examples.  
> 
> clamp_t(u8, xxx, 0, 255) is not wrong. It's silly, but
> it's doing the right thing and one can argue and explicit
> clamp values serve as a documentation.

Not when you look at some of the code that uses it.
The clear intention is to saturate a large value - which isn't what it does.

> clamp_t(int32_t, (ts).tv_sec, S32_MIN, S32_MAX)) is indeed incorrect,
> but it's a bug in the implementation of __clamp_once().
> Fix it, instead of spamming people with "_t" removal.

It is too late by the time you get to clamp_once().
The 'type' for all the xxx_t() functions is an input cast, not the type
for the result.
clamp_t(type, v, lo, hi) has always been clamp((type)v, (type)lo, type(hi)).
From a code correctness point of view you pretty much never want those casts.

I've already fixed clamp() so it doesn't complain about comparing s64 against s32.
The next stage is to change pretty much all the xxx_t() to plain xxx().

If you've got some spare time try issuing read calls with a 4GB buffer to all
the subsystems you can find - and see how many loop for ever.
(I think you can do that with readv() and a single buffer.)
The issue there is that a lot use min_t(u32, max_frag_size, xfer_size) to split
operations - and xfer_size is size_t (so I'm pretty sure there are ways to get
4GB in there).

	David



  reply	other threads:[~2025-11-23 18:07 UTC|newest]

Thread overview: 109+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-19 22:40 [PATCH 00/44] Change a lot of min_t() that might mask high bits david.laight.linux
2025-11-19 22:40 ` [PATCH 01/44] x86/asm/bitops: Change the return type of variable__ffs() to unsigned int david.laight.linux
2025-11-20 15:54   ` Yury Norov
2025-11-20 18:29     ` David Laight
2025-11-20 18:33       ` Yury Norov
2025-11-20 21:18         ` David Laight
2025-11-24 14:58           ` Yury Norov
2025-11-24 18:18             ` David Laight
2025-11-19 22:40 ` [PATCH 02/44] ext4: Fix saturation of 64bit inode times for old filesystems david.laight.linux
2025-11-19 22:40 ` [PATCH 03/44] perf: Fix branch stack callchain limit david.laight.linux
2025-11-26  5:25   ` Mi, Dapeng
2025-11-19 22:41 ` [PATCH 04/44] io_uring/net: Change some dubious min_t() david.laight.linux
2025-11-20 14:48   ` Jens Axboe
2025-11-20 15:48     ` David Laight
2025-11-20 15:53       ` Jens Axboe
2025-11-22 11:31         ` David Laight
2025-11-19 22:41 ` [PATCH 05/44] ipc/msg: Fix saturation of percpu counts in msgctl_info() david.laight.linux
2025-11-19 22:41 ` [PATCH 06/44] bpf: Verifier, remove some unusual uses of min_t() and max_t() david.laight.linux
2025-11-21 21:40   ` Alexei Starovoitov
2025-11-21 22:21     ` David Laight
2025-11-23 16:39       ` Alexei Starovoitov
2025-11-23 18:07         ` David Laight [this message]
2025-11-23 19:20           ` Alexei Starovoitov
2025-11-23 23:03             ` David Laight
2025-11-19 22:41 ` [PATCH 07/44] net/core/flow_dissector: Fix cap of __skb_flow_dissect() return value david.laight.linux
2025-11-19 22:41 ` [PATCH 08/44] net: ethtool: Use min3() instead of nested min_t(u16,...) david.laight.linux
2025-11-19 22:41 ` [PATCH 09/44] ipv6: __ip6_append_data() don't abuse max_t() casts david.laight.linux
2025-11-20  0:32   ` bot+bpf-ci
2025-11-20 11:16     ` David Laight
2025-11-20 13:50       ` Chris Mason
2025-11-19 22:41 ` [PATCH 10/44] x86/crypto: ctr_crypt() use min() instead of min_t() david.laight.linux
2025-11-19 22:41 ` [PATCH 11/44] arch/x96/kvm: " david.laight.linux
2025-11-19 22:41 ` [PATCH 12/44] block: " david.laight.linux
2025-11-20 14:44   ` Jens Axboe
2025-11-19 22:41 ` [PATCH 13/44] drivers/acpi: " david.laight.linux
2025-11-24 19:48   ` Rafael J. Wysocki
2025-11-19 22:41 ` [PATCH 14/44] drivers/char/hw_random: use min3() instead of nested min_t() david.laight.linux
2025-11-19 22:41 ` [PATCH 15/44] drivers/char/tpm: use min() instead of min_t() david.laight.linux
2025-11-21 20:11   ` Jarkko Sakkinen
2025-11-19 22:41 ` [PATCH 16/44] drivers/crypto/ccp: " david.laight.linux
2025-11-19 22:41 ` [PATCH 17/44] drivers/cxl: " david.laight.linux
2025-11-19 23:50   ` Dave Jiang
2025-11-19 22:41 ` [PATCH 18/44] drivers/gpio: " david.laight.linux
2025-11-20  8:01   ` Andy Shevchenko
2025-11-20  9:37     ` David Laight
2025-11-25  9:55       ` Andy Shevchenko
2025-11-19 22:41 ` [PATCH 19/44] drivers/gpu/drm/amd: " david.laight.linux
2025-11-19 22:41 ` [PATCH 20/44] drivers/i2c/busses: " david.laight.linux
2026-01-20 13:19   ` Andi Shyti
2025-11-19 22:41 ` [PATCH 21/44] drivers/net/ethernet/realtek: " david.laight.linux
2025-11-19 22:41 ` [PATCH 22/44] drivers/nvme: " david.laight.linux
2025-11-19 22:41 ` [PATCH 23/44] arch/x86/mm: " david.laight.linux
2025-11-19 22:41 ` [PATCH 24/44] drivers/nvmem: " david.laight.linux
2025-11-19 22:41 ` [PATCH 25/44] drivers/pci: " david.laight.linux
2025-11-24 21:04   ` Bjorn Helgaas
2025-11-24 21:42     ` David Laight
2025-11-19 22:41 ` [PATCH 26/44] drivers/scsi: " david.laight.linux
2025-11-19 23:09   ` Bart Van Assche
2025-11-20 18:44     ` David Laight
2025-11-22 21:50     ` David Laight
2025-11-19 22:41 ` [PATCH 27/44] drivers/tty/vt: use umin() instead of min_t(u16, ...) for row/col limits david.laight.linux
2025-11-20  7:23   ` Jiri Slaby
2025-11-19 22:41 ` [PATCH 28/44] drivers/usb/storage: use min() instead of min_t() david.laight.linux
2025-11-20  2:59   ` Alan Stern
2025-11-20  9:18     ` David Laight
2025-11-20 14:39       ` [usb-storage] " Alan Stern
2025-11-19 22:41 ` [PATCH 29/44] drivers/xen: " david.laight.linux
2025-11-20  8:13   ` Jürgen Groß
2025-11-19 22:41 ` [PATCH 30/44] fs: use min() or umin() " david.laight.linux
2025-11-25  9:06   ` Christian Brauner
2026-01-12 21:51   ` Brian Masney
2026-01-13  9:42     ` David Laight
2026-01-13 16:56   ` Mark Brown
2026-01-13 18:33     ` David Laight
2026-01-13 19:10       ` Mark Brown
2026-01-13 19:24       ` David Laight
2025-11-19 22:41 ` [PATCH 31/44] block: bvec.h: use min() " david.laight.linux
2025-11-19 22:41 ` [PATCH 32/44] nodemask: " david.laight.linux
2025-11-20 15:19   ` Yury Norov
2025-11-19 22:41 ` [PATCH 33/44] ipc: " david.laight.linux
2025-11-19 22:41 ` [PATCH 34/44] bpf: " david.laight.linux
2025-11-19 22:41 ` [PATCH 35/44] " david.laight.linux
2025-11-19 22:41 ` [PATCH 36/44] lib/bucket_locks: " david.laight.linux
2025-11-19 22:41 ` [PATCH 37/44] lib/crypto/mpi: " david.laight.linux
2025-11-19 22:41 ` [PATCH 38/44] lib/dynamic_queue_limits: use max() instead of max_t() david.laight.linux
2025-11-19 22:41 ` [PATCH 39/44] mm: use min() instead of min_t() david.laight.linux
2025-11-20  9:20   ` David Hildenbrand (Red Hat)
2025-11-20  9:59     ` David Laight
2025-11-20 23:45       ` Eric Biggers
2025-11-21  8:27         ` David Hildenbrand (Red Hat)
2025-11-21  9:15         ` David Laight
2025-11-20 10:36   ` Lorenzo Stoakes
2025-11-20 12:09     ` Lorenzo Stoakes
2025-11-20 12:55     ` David Laight
2025-11-20 13:42       ` David Hildenbrand (Red Hat)
2025-11-20 15:44         ` David Laight
2025-11-21  8:24           ` David Hildenbrand (Red Hat)
2025-11-19 22:41 ` [PATCH 40/44] net: Don't pass bitfields to max_t() david.laight.linux
2025-11-19 22:41 ` [PATCH 41/44] net/core: Change loop conditions so min() can be used david.laight.linux
2025-11-19 22:41 ` [PATCH 42/44] net: use min() instead of min_t() david.laight.linux
2025-11-19 22:41 ` [PATCH 43/44] net/netlink: Use umin() to avoid min_t(int, ...) discarding high bits david.laight.linux
2025-11-19 22:41 ` [PATCH 44/44] net/mptcp: Change some dubious min_t(int, ...) to min() david.laight.linux
2025-12-18 17:33   ` Matthieu Baerts
2025-12-18 20:15     ` David Laight
2025-12-19 10:48       ` Matthieu Baerts
2025-11-20  1:47 ` [PATCH 00/44] Change a lot of min_t() that might mask high bits Jakub Kicinski
2025-11-20  9:38 ` Lorenzo Stoakes
2025-11-20 14:52 ` (subset) " Jens Axboe
2025-11-24  9:49 ` Herbert Xu

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=20251123180741.65cd2dd3@pumpkin \
    --to=david.laight.linux@gmail.com \
    --cc=alexei.starovoitov@gmail.com \
    --cc=andrii@kernel.org \
    --cc=ast@kernel.org \
    --cc=bpf@vger.kernel.org \
    --cc=daniel@iogearbox.net \
    --cc=linux-kernel@vger.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox