[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20200123161047.GQ4113@kitsune.suse.cz>
Date: Thu, 23 Jan 2020 17:10:47 +0100
From: Michal Suchánek <msuchanek@...e.de>
To: Nathan Lynch <nathanl@...ux.ibm.com>
Cc: Libor Pechacek <lpechacek@...e.cz>,
Benjamin Herrenschmidt <benh@...nel.crashing.org>,
Paul Mackerras <paulus@...ba.org>,
Michael Ellerman <mpe@...erman.id.au>,
Thomas Gleixner <tglx@...utronix.de>,
Allison Randal <allison@...utok.net>,
Leonardo Bras <leonardo@...ux.ibm.com>,
David Hildenbrand <david@...hat.com>,
linux-kernel@...r.kernel.org, linuxppc-dev@...ts.ozlabs.org
Subject: Re: [PATCH] powerpc: drmem: avoid NULL pointer dereference when
drmem is unavailable
On Thu, Jan 23, 2020 at 09:56:10AM -0600, Nathan Lynch wrote:
> Hello and thanks for the patch.
>
> Libor Pechacek <lpechacek@...e.cz> writes:
> > In KVM guests drmem structure is only zero initialized. Trying to
> > manipulate DLPAR parameters results in a crash in this environment.
>
> I think this statement needs qualification. Unless I'm mistaken, this
> happens only when you boot a guest without any hotpluggable memory
> configured, and then try to add or remove memory.
>
>
> > diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
> > index 3d76e1c388c2..28c3d936fdf3 100644
> > --- a/arch/powerpc/include/asm/drmem.h
> > +++ b/arch/powerpc/include/asm/drmem.h
> > @@ -27,12 +27,12 @@ struct drmem_lmb_info {
> > extern struct drmem_lmb_info *drmem_info;
> >
> > #define for_each_drmem_lmb_in_range(lmb, start, end) \
> > - for ((lmb) = (start); (lmb) <= (end); (lmb)++)
> > + for ((lmb) = (start); (lmb) < (end); (lmb)++)
> >
> > #define for_each_drmem_lmb(lmb) \
> > for_each_drmem_lmb_in_range((lmb), \
> > &drmem_info->lmbs[0], \
> > - &drmem_info->lmbs[drmem_info->n_lmbs - 1])
> > + &drmem_info->lmbs[drmem_info->n_lmbs])
> >
> > /*
> > * The of_drconf_cell_v1 struct defines the layout of the LMB data
> > diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
> > index c126b94d1943..4ea6af002e27 100644
> > --- a/arch/powerpc/platforms/pseries/hotplug-memory.c
> > +++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
> > @@ -236,9 +236,9 @@ static int get_lmb_range(u32 drc_index, int n_lmbs,
> > if (!start)
> > return -EINVAL;
> >
> > - end = &start[n_lmbs - 1];
> > + end = &start[n_lmbs];
> >
> > - last_lmb = &drmem_info->lmbs[drmem_info->n_lmbs - 1];
> > + last_lmb = &drmem_info->lmbs[drmem_info->n_lmbs];
> > if (end > last_lmb)
> > return -EINVAL;
>
> Is this not undefined behavior? I'd rather do this in a way that does
> not involve forming out-of-bounds pointers. Even if it's safe, naming
> that pointer "last_lmb" now actively hinders understanding of the code;
> it should be named "limit" or something.
Indeed, the name might be misleading now.
However, the loop differes from anything else we have in the kernel.
The standard explicitly allows the pointer to point just after the last
element to allow expressing the iteration limit without danger of
overflow.
Thanks
Michal
Powered by blists - more mailing lists