2014-07-06 09:38:21

by Grant Likely

[permalink] [raw]
Subject: [GIT PULL] bug fix for devicetree memory parsing

Hi Linus,

Can you pull this bug fix into your tree please?

Thanks,
g.

The following changes since commit a497c3ba1d97fc69c1e78e7b96435ba8c2cb42ee:

Linux 3.16-rc2 (2014-06-21 19:02:54 -1000)

are available in the git repository at:

git://git.secretlab.ca/git/linux tags/dt-for-linus

for you to fetch changes up to a67a6ed15513541579d38bcbd127e7be170710e5:

of: Check for phys_addr_t overflows in early_init_dt_add_memory_arch
(2014-06-26 17:28:28 +0100)

----------------------------------------------------------------
Devicetree bugfixe for v3.16

Important bug fix for parsing 64-bit addresses on 32-bit platforms.
Without this patch the kernel will try to use memory ranges that cannot
be reached.

----------------------------------------------------------------
Laura Abbott (1):
of: Check for phys_addr_t overflows in early_init_dt_add_memory_arch

drivers/of/fdt.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)


2014-07-06 19:24:45

by Linus Torvalds

[permalink] [raw]
Subject: Re: [GIT PULL] bug fix for devicetree memory parsing

On Sun, Jul 6, 2014 at 2:37 AM, Grant Likely <[email protected]> wrote:
>
> Can you pull this bug fix into your tree please?

I took it, but I think both your explanation and the patch itself is
actually crap. It may fix the issue, but it's seriously confused.

Your explanation says that it's a 32-bit platform issue. No it's not.
Most 32-bit configurations still have a 64-bit phys_addr_t (ie
PAE/LPAE etc).

And the code is crap, because it uses ULONG_MAX etc in ways that
simply make no f*cking sense. And why does it care about sizeof?

Why does the code not just do something like

#define MAX_PHYS_ADDR ((phys_addr_t) ~0)

and then do

if (base > MAX_PHYS_ADDR || base + size > MAX_PHYS_ADDR)
...

and be done with it? All those sizeof tests are completely pointless.
If it turns out that phys_addr_t is the same size as u64, then the
tests will never be true, and the compiler will happily optimize them
away.

So I think this fixes a problem, but it's all ugly as hell. I ended up
pulling it because I'm lazy and don't have a machine to test a proper
fix on anyway, but I hope this can get cleaned up. And more
importantly, I hope maintainers will spend a bit more time thinking
about things like this. It's not just that the code is unnecessarily
complex, it's WRONG. Comparing things to "ULONG_MAX" makes absolutely
zero sense, since "ULONG_MAX" has nothing to do with anything. It's
just stupid and misleading, and it just so happens to work by random
luck because it so *happens* that phys_addr_t is smaller than "u64"
only when ULONG_MAX happens to be the same size. But even that is not
guaranteed (ie some stupid broken architecture might have a 32-bit
physical address space despite having a 64-bit "long")

Linus

2014-07-07 00:52:58

by Grant Likely

[permalink] [raw]
Subject: Re: [GIT PULL] bug fix for devicetree memory parsing

On Sun, Jul 6, 2014 at 8:24 PM, Linus Torvalds
<[email protected]> wrote:
> On Sun, Jul 6, 2014 at 2:37 AM, Grant Likely <[email protected]> wrote:
>>
>> Can you pull this bug fix into your tree please?
>
> I took it, but I think both your explanation and the patch itself is
> actually crap. It may fix the issue, but it's seriously confused.
>
> Your explanation says that it's a 32-bit platform issue. No it's not.
> Most 32-bit configurations still have a 64-bit phys_addr_t (ie
> PAE/LPAE etc).
>
> And the code is crap, because it uses ULONG_MAX etc in ways that
> simply make no f*cking sense. And why does it care about sizeof?
>
> Why does the code not just do something like
>
> #define MAX_PHYS_ADDR ((phys_addr_t) ~0)
>
> and then do
>
> if (base > MAX_PHYS_ADDR || base + size > MAX_PHYS_ADDR)
> ...

Sure. I'll make sure a cleanup patch gets written and queued up.

g.

2014-07-08 17:55:46

by Linus Torvalds

[permalink] [raw]
Subject: Re: [GIT PULL] bug fix for devicetree memory parsing

On Sun, Jul 6, 2014 at 12:24 PM, Linus Torvalds
<[email protected]> wrote:
>
> Why does the code not just do something like
>
> #define MAX_PHYS_ADDR ((phys_addr_t) ~0)
>
> and then do
>
> if (base > MAX_PHYS_ADDR || base + size > MAX_PHYS_ADDR)

Actually, there's an even better model, which is to just check if a
value fits in a type.

You could do something like

#define FITS(type, value) ((value) == (type)(value))

and then you can just use

if (!FITS(phys_addr_t, base) || !FITS(phys_addr_t, base+size))

instead. The compiler will trivially turn the comparisons into no-ops
if the type is sufficient to hold the value.

We already do this in a few places, it might even be worth it making a
generic macro. People have been confused by the "x == x" kind of
comparisons before, see for example fs/buffer.c:grow_buffers(), which
does

index = block >> sizebits;
if (unlikely(index != block >> sizebits)) {

where "index" is a pgoff_t, but "block >> sizebits" is a sector_t, so
that comparison actually checks that "block >> sizebits" fits in the
type, even though it looks like it compares the same computed value
against itself.

Linus