[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CAMuHMdWd_eAGjXRAODXvufoXT_QqqOpuLJTAj9ZG7d-EQyRKBw@mail.gmail.com>
Date: Tue, 15 Mar 2022 19:56:13 +0100
From: Geert Uytterhoeven <geert@...ux-m68k.org>
To: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Mark Brown <broonie@...nel.org>,
linux-spi <linux-spi@...r.kernel.org>,
Linux Kernel Mailing List <linux-kernel@...r.kernel.org>,
Biju Das <biju.das.jz@...renesas.com>
Subject: Re: [GIT PULL] SPI fixes for v5.17-rc7
Hi Linus,
On Tue, Mar 15, 2022 at 5:48 PM Linus Torvalds
<torvalds@...ux-foundation.org> wrote:
> On Tue, Mar 15, 2022 at 2:08 AM Geert Uytterhoeven <geert@...ux-m68k.org> wrote:
> > I had noticed while reviewing the patch, but changing to size_t wouldn't
> > help much, as other related code paths treat the value as unsigned int
> > anyway.
>
> .. but it really would.
>
> Note that the paths *after* this code don't matter. Because the result
> is guaranteed to fit in 'unsigned int' anyway.
>
> Put another way:
>
> min_t(unsigned int,x,y)
>
> is buggy if one of x/y is 'size_t'. Why? Because if that one gets
> truncated, you're doing 'min()' with a value that may be artificially
> much too small (that was exactly the problem commit 1a4e53d2fc4f:
> "spi: Fix invalid sgs value")fixed).
>
> But the situation is _not_ true in the reverse. Look:
>
> min(size_t,x,y)
>
> is guaranteed to fit in 'unsigned int' as long as _one_ of x,y fits in
> 'unsigned int' - even if the other doesn't. Because then 'min()' will
> just pick the one that already had the right size.
>
> To make it really concrete, compare
>
> min_t(unsigned int, 5, 0x100000001);
> min_t(size_t, 5, 0x100000001);
>
> on a 64-bit machine (ie size_t is 64-bits, and unsigned int is 32-bit).
>
> One returns 1. The other returns 5. Both fit the result in 'unsigned
> int', but one of them is wrong.
You're absolutely right. So the code should be changed to:
if (vmalloced_buf || kmap_buf) {
- desc_len = min_t(unsigned int, max_seg_size, PAGE_SIZE);
+ desc_len = min_t(unsigned long, max_seg_size, PAGE_SIZE);
sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len);
} else if (virt_addr_valid(buf)) {
- desc_len = min_t(unsigned int, max_seg_size, ctlr->max_dma_len);
+ desc_len = min_t(size_t, max_seg_size, ctlr->max_dma_len);
sgs = DIV_ROUND_UP(len, desc_len);
} else {
return -EINVAL;
}
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@...ux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
Powered by blists - more mailing lists